命令注入攻击是通过有漏洞的应用程序在主机操作系统上执行任意命令进行攻击。当应用程序将不安全的用户提供的数据(表单、cookie、HTTP头等)传递给系统shell时,就可能会发生命令注入攻击。在这种攻击中,攻击者使用的操作系统命令通常以有漏洞的应用程序的权限执行。发生命令注入攻击主要是由于对输入的验证不足。
这种攻击不同于代码注入(sql injection,XSS等),代码注入允许攻击者添加自己的代码,然后由应用程序自身执行。在命令注入中,攻击者扩展了应用程序的默认功能,该应用程序执行系统命令,而无需注入代码。
在命令执行中,常用的命令连接符号有以下个:
- && 前一个指令执行成功,后面的指令才继续执行,就像进行与操作一样。例如:
ipconfig&&dir
- || 前一个命令执行失败,后面的才继续执行,类似于或操作
ping 10.10.10.10||dir
- & 直接连接多个命令。无论前面的命令执行成功或者失败,都执行后面命令。
- | 管道符,将前一个命令的输出作为下一个命令的输入。
dos命令符号参见 https://blog.csdn.net/quincylk/article/details/8315548
例:查找当前目录下desktop文件(不分大小写)
dir|findstr /I desktop
现在来看实例
low
这里原先目的是测试目标地址是否可以ping通,那我们尝试是否可以把自己需要的命令注入
192.168.99.100&pwd
嗯,能看到当前目录了
再来一个
192.168.99.100&&ps
看看源码
<?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>";
}
?>
我用的docker toolbox是linux内核,所以以下代码生效
$cmd = shell_exec( 'ping -c 4 ' . $target );
tartget来自界面输入,什么都没有处理,直接接在ping后面被执行了。
medium
先看源码吧
<?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>";
}
?>
代码中把符号 &&和;去除了。
先设置符号黑名单,然后用str_replace函数替换
现在以下命令是不能执行了
192.168.99.100&&ps
但是下面的命令可以执行
255.255.255.255||ps
high
还是先看源码
<?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>";
}
?>
很简单,也就是过滤了更加多的字符。 不过黑名单写的时候有失误, '| ’ => ‘’。管道符号后面有空格。
执行以下命令
192/168.99.100|ps
结果
impossible
看源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// 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>";
}
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
说明
- stripslashes,去反斜杠
- explode,把输入按照.符号分割为数组
- 最后检查数组,数组长度为4,同时都是数字,那才重新按照ip地址格式组装起来