命令注入漏洞
命令注入:在某种开放需要中,需要引入对系统本地命令来完成某些特定的功能,当未可控制输入的参数严格进行过滤,则有可能发生命令注入。攻击者会使用命令注入来执行系统终端命令,从而来掌控服务器的控制权限。
low
<?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>";
}
?>
可以发现对输入的内容没有过滤。或者限制,直接运行
php_uname()函数检查php的操作系统描述
如果是windows执行第一条,如果是linux就执行第二条
shell_exec函数是php的内置函数,用于通过shell执行命令,并且以字符串的形式返回网站的输出。
ping和starget拼接然后执行这个命令。
输入127.0.0.1 | dir#可以查看当前windows显示目录的文件
当然也可以用&&,||,|,&等管道运算符
Medium
Command Injection Source
vulnerabilities/exec/source/medium.php
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the characters 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>";
}
?>
array_keys:获取数组的键
这里看到str_repalce()函数对&&,;进行过滤替。
但是我们仍然可以用|,||进行利用
127.0.0.1| dir
High
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 characters 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>";
}
?>
好家伙对很多字符过滤了,但是仔细看的话,字符串|后面有一个过滤,说明'| '过滤,但是,不是'|'对过滤,所以仍然可以使用|进行执行。
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();
?>
使用了Token进行了CSRF防护,
explode()函数以'.'打散成数组。
并且对它进行了分隔,'.'分隔,而且is_numeric()判断是不是数值。所以导致无法进命令执行
防范:
- 过滤黑名单
- 添加Token机制,增加安全性
- 对IP地址,进行'.'进行分隔,把内容打散成数组,然后判断每一位是否是数值is_numeric()