前言
命令注入是未一些函数的参数做过滤或过滤不严导致的,可以执行系统或者应用指令(CMD命令或者bash命令)的一种注入攻击手段。>PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一。
管道符
利用命令注入,很多时候需要利用管道符,下面将分别介绍Windows和Linux的管道符;
Windows
-
|,直接执行后面的语句,例如:ping 127.0.0.1 | whoami;
-
||,如果前面的语句执行出错,则执行后面的语句;要执行后面的语句,前面的语句只能为假,例如:ping 2 || whoami;
-
&,无论前面的语句的真假,都会执行两个语句,例如:ping 2 & whoami
-
&&,如果前面的语句为假则直接出错,也不执行后面的语句;要执行后面的语句,前面的语句只能为真,例如:ping 127.0.0.1 && whoami;
Linux
-
;,执行完前面的语句再执行后面的,例如: ping 127.0.0.1;whoami;
-
|,只显示后面语句的执行结果,例如:ping 127.0.0.1 | whoami;
-
||,当前面的语句执行出错时,执行后面的语句;要执行后面的语句,前面的语句只能为假,例如:ping 1|| whoami;
-
&, 无论前面的语句的真假,都会执行两个语句,例如:ping 127.0.0.1 & whoami;
-
&&,如果前面的语句为假则直接出错,也不执行后面的;要执行后面的语句,前面的语句只能为真,例如:ping 127.0.0.1 && whoami;
LOW
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <?php if( isset( $_POST[ 'Submit' ] ) ) { $target = $_REQUEST[ 'ip' ]; if( stristr( php_uname( 's' ), 'Windows NT' ) ) { $cmd = shell_exec( 'ping ' . $target ); } else { $cmd = shell_exec( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd}</pre>"; } ?>
|
分析:
函数
stristr(string,search,before_search)
stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配点),如果未找到所搜索的字符串,则返回 FALSE。
- 参数string规定被搜索的字符串,
- 参数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符),
- 可选参数before_true为布尔型,默认为“false” ,如果设置为 “true”,
函数将返回 search 参数第一次出现之前的字符串部分。
php_uname(mode)
这个函数会返回运行php的操作系统的相关描述,参数mode可取值
-
a (此为默认,包含序列”snrvm”里的所有模式)
-
s (返回操作系统名称)
-
n(返回主机名)
-
r(返回版本名称)
-
v(返回版本信息)
-
m(返回机器类型)
功能:
获取 IP 的值,直接传参使用 shell_exec 执行。
-
Windows 的话执行 ping 命令。
-
linux 的话,执行 ping -c 4 命令。
未对输入数据做过滤处理,可以使用管道添加其他命令,达到攻击的目的;

MEDIUM
分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php if( isset( $_POST[ 'Submit' ] ) ) { $target = $_REQUEST[ 'ip' ]; $substitutions = array( '&&' => '', ';' => '', ); $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); if( stristr( php_uname( 's' ), 'Windows NT' ) ) { $cmd = shell_exec( 'ping ' . $target ); } else { $cmd = shell_exec( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd}</pre>"; } ?>
|
分析:
str_replace函数将&&,;替换为空字符,过滤了&&、;,但是其他 的符号仍然可用;

HIGH
分析
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
| <?php if( isset( $_POST[ 'Submit' ] ) ) { $target = trim($_REQUEST[ 'ip' ]); $substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '', ); $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); if( stristr( php_uname( 's' ), 'Windows NT' ) ) { $cmd = shell_exec( 'ping ' . $target ); } else { $cmd = shell_exec( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd}</pre>"; } ?>
|
分析:
黑名单看似过滤了所有的非法字符,但仔细观察到是把| (注意这里|后有一个空格)替换为空字符,于是|就有用了;
输入127.0.0.1|ifconfig执行后面的命令;

IMPOSSIBLE
分析
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
| <?php if( isset( $_POST[ 'Submit' ] ) ) { checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); $target = $_REQUEST[ 'ip' ]; $target = stripslashes( $target ); $octet = explode( ".", $target ); if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) { $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; if( stristr( php_uname( 's' ), 'Windows NT' ) ) { $cmd = shell_exec( 'ping ' . $target ); } else { $cmd = shell_exec( 'ping -c 4 ' . $target ); } echo "<pre>{$cmd}</pre>"; } else { echo '<pre>ERROR: You have entered an invalid IP.</pre>'; } } generateSessionToken(); ?>
|
分析:
加入了Anti-CSRF token,同时对参数ip进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。