DVWA学习日记——命令注入(Command Injection)
命令注入(Command Injection),是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。
Low级别
window和linux系统都可以用&&来执行多条命令
127.0.0.1 && net user
<?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>";
}
?>
相关函数:
stristr(string,search,before_search)
查找“search”在“string”中的第一次出现并返回字符串的剩余部分
before_search默认为“false”,如果设置为 “true”,它将返回 “search”第一次出现之前的字符串部分
php_uname (mode)
mode为单个字符
‘a’:此为默认。包含序列 “s n r v m” 里的所有模式。
‘s’:操作系统名称。
‘n’:主机名。
‘r’:版本名称。
‘v’:版本信息。
‘m’:机器类型。
Medium级别
127.0.0.1 & net user
127.0.0.1 &;& net user
<?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(find,replace,string,count)
在被查找字符串string中用replace替换find。
可以看到相比Low级别,服务器端对传入的ip参数进行了一定过滤,把“&&” “;”删除。即采用了黑名单的方式,因此仍存在安全问题
过滤“&&”但“&”仍可用,由于使用str_replace会把“&&” “;”替换为空字符所以还有一种绕过黑名单的方式“&;&”
High级别
127.0.0.1|net user
<?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>";
}
?>
可以看到相比Medium级别完善了黑名单过滤了更多的字符但是’| ’ => ''增加了一个字符所以‘|’成为漏网之鱼
A|B
|”是管道符,表示将A的输出作为B的输入,并且只打印B执行的结果
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(string)
删除字符串中’'并返回已剥离反斜杠的字符串
explode(separator,string,limit)
此函数返回由字符串组成的数组separator规定在哪分割字符串,string需要分割的字符串
limit(可选)
大于 0 - 返回包含最多 limit 个元素的数组
小于 0 - 返回包含除了最后的 -limit 个元素以外的所有元素的数组
0 - 返回包含一个元素的数组
可以看到Impossible级别的代码加入了Anti-CSRF token,同时用白名单的方式对ip进行了限制,只有如数字.数字.数字.数字”的输入才会被接收执行,因此不存在命令注入漏洞。
总结
Command Injection
条件
- 是否调用系统命令
- 函数或函数的参数是否可控
- 是否拼接命令注入
Windows下常用拼接命令符号
命令 | 描述 |
---|---|
A&B | 简单的拼接,AB之间无制约关系 |
A&&B | A执行成功后才会执行B |
A|B | A的输出作为B的输入 |
A||B | A执行失败后才会执行B |
没有回显怎么办
-
延时注入
Windows ping 127.0.0.1 -n 5 >nul
Linux sleep 5 -
远程请求
Windows ping,telnet等
Linux wget,curl等
修复
黑名单×
黑名单可以绕过如:用"“绕过
whoami——who”“am”"i
白名单√
上一篇: Linux命令行操作