准备知识:
Command injection顾名思义就是攻击者将系统命令提交给服务器端,获取信息,执行恶意代码来实现自己的目的。
Command injection通过命令连接符使系统执行注入的命令。
常用的命令连接符:
- | :管道操作符, 无论前者是否执行正确,后者都执行。
- ; : Linux系统, 无论前者是否执行正确,后者都执行。
- & :Windows系统,无论前者是否执行正确,后者都执行。
- || :逻辑或,仅当前者执行失败时,后者执行。
- && :逻辑与,仅当前者执行正确时,后者执行。
常见的cmd命令:
- whoami(查看用户名)
- ipconfig(查看网卡信息)
- shutdown -s -t 0 (关机 ,-t为等待时间)
- net user[username][password]/add( 增加一个新用户,用户名为username,密码为password)
- type[file_name] (查看文件内容)
.......更多命令可自行查找学习
渗透测试的解决方法:
白盒测试:可看到源代码,查看过滤机制。
黑盒测试: 看不到源代码,依次尝试命令连接符。
1.Low level :完全无任何过滤
source:
<?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>";
}
?>
Input:127.0.0.0&whoami
Output:
防御命令执
行最高效的方法:过滤命令连接符(将这些符号替换为空,或判断为特殊符号就终止)
2.Medium level : 将'&&'和';'替换为空
无法过滤'&' , '|', '||' 等命令连接符
Source:
<?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>";
}
?>
Input:127.0.0.1&&whoami
Output:
Input:127.0.0.1&&whoami
Output:
3.High 拓宽了替换数组,包含各种命令连接符
但是'| '中有空格,无法有效防御'|'。
Source:
<?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>";
}
?>
Input: 127.0.0.1| whoami
Output:(有空格 能防御)
Input: 127.0.0.1|whoami
Output:(无空格 不能防御)
4.Impossible 防御典范
将127.0.0.1 按'.'分成4部分,分别判断是不是数字,最后再拼起来成ip地址。严格规定输入格式。
Source:
<?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();
?>