前言
命令注入是未一些函数的参数做过滤或过滤不严导致的,可以执行系统或者应用指令(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进行了严格的限制,只有诸如“数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。