今天我们我们讨论下命令注入,在之前我已经就命令注入的理论注入的理论知识做了介绍,所以只是在简单说一下,不再缀述。
命令执行执行漏洞是指攻击者可以随意执行系统命令,它属于高危漏洞之一,也属于代码执行的一部分。
漏洞产生原因:
1.过多调用系统命令,或者说是在调用系统命令时不慎重。
2.在调用系统命令时过滤不严格。
3.在web开发中使用了一些不可控的函数或使用类不恰当,如eval()(动态执行php代码的函数)和java开发中的Runtime类。
4.动态函数的调用带来的隐患。
实验部分
初级测试
首先查看php源码
<?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 {
// linux
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
经过分析可知服务器通过判断不同的操作系统来执行命令,并未做任何的过滤,下面我们开始测试。
首先测试下正常情况
开始注入
发现轻松注入成功,如果是在linux在可以输入www.baidu.com&&cat /etc/shadow 可见危害之大
中级测试
if( isset( _POST[ ‘Submit’ ] ) ) {
// Get inputtarget = $_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>";
}黑名单,对一些命令连接符进行了过滤,如:“&&”,“;”。但我们知道命令连接符不止这些,还有诸如:&,|,||等。
##开始注入
同样注入成功!
高级测试
查看源码
<?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>";
}
?>
经过分析代码,我们发现这一次服务器端进行了严格的过滤,黑名单的过滤程度十分严格,似乎无懈可击,但我们仔细查看发现对‘| ’的过滤,后面有个空格,这是一个突破口,我们只需要在输入‘| ’时把后面的空格去掉就可以了绕过过滤了。
安全代码
<?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();
?>
通过分析代码,我们知道这段代码增加了Token机制的验证来预防csrf攻击,至于Token的原理前面我已经做了介绍,并且对输入的ip限制必须是纯数字,有效预防了命令注入。