命令注入和DVWA命令注入实例
Posted Zeker62
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了命令注入和DVWA命令注入实例相关的知识,希望对你有一定的参考价值。
什么是命令注入?
在开发者开发程序过程中,一些高级应用可能需要调用一些外部程序:比如命令行获取信息、exe可执行文件等等。调用的时候会用到一些系统命令函数,通过这些函数,可以在其中注入一些恶意代码
命令注入漏洞产生原因
- 用户输入作为拼接
- 没有足够的安全过滤
危害
- 继承web服务器程序执行系统命令
- 继承web服务器权限,读写文件
- 反弹shell,即服务器主动联系攻击方
- 控制网站
- 控制服务器
相关函数(php)
- system() / passthru()函数:可以将字符串参数直接作为系统命令来执行:
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
system($str);
}
?>
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
passthru($str);
}
?>
可以这样传递参数,比如:
?cmd=ipconfig
- exec()函数:效果和system()函数一致,但是返回的结果有限,且不打印输出。
- shell_exec()函数:效果和system()一致,但是没有打印输出。
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
print exec($str);
}
?>
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
print shell_exec($str);
}
?>
- popen()效果和system()一样,但是不返回结果,返回结果指针
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
popen($str,'r/w') >> 1.txt;
}
?>
- 反引号 ` :反引号里面的内容被当做命令
<?php
if($_GET['cmd']){
$str=$_GET['cmd'];
print `$str`
}
?>
漏洞利用
- 查看文件:?cmd=type C:\\windows…
- 显示当前路径(绝对路径):?cmd=cd
- 写入文件:?cmd=echo “<?php @$_GET['aaa'];?>” > C://windows…
防御方法:
- 减少命令函数的使用,并且使用disable_function=里面禁掉一些函数
- 在进入命令执行的函数或者方法之前对参数进行过滤
- 参数的值尽量使用单引号包裹,在拼接的时候使用addslashes()函数对单引号,反斜杠,双引号进行转义
实战 DVWA
知识点:
- command1 & command2 :两个命令都执行
- command1 && command2 :与执行,第一个成功执行第二个才会执行
- command1 | command2 :或执行,只执行第二个
- command1 || command2:第一个执行成功,第二个不执行。第一个执行失败,第二个执行
low难度:
使用以下命令:
- 127.0.0.1 & whoami
- 127.0.0.1 && whoami
- 127.0.0.1 | whoami
- 127.0.0.0.1 || whoami
发现都可以得到whoami,下面进行代码审计:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ]; //获取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() 函数搜索字符串在另一字符串中的第一次出现的位置,返回剩余的字符串 注释:该函数是二进制安全的。
注释:该函数是不区分大小写的。如需进行区分大小写的搜索,请使用 strstr() 函数。
php_uname — 返回运行 PHP 的系统的有关信息 ‘a’:此为默认。包含序列 “s n r v m” 里的所有模式。
‘s’:操作系统名称。例如: FreeBSD。
‘n’:主机名。例如: localhost.example.com。
‘r’:版本名称,例如: 5.1.2-RELEASE。
‘v’:版本信息。操作系统之间有很大的不同。 ‘m’:机器类型。例如:i386。
发现,这个难度情况下并没有对输入的命令进行过滤,所以我们可以为所欲为
Medium难度:
使用刚才的四个命令测试,发现只有127.0.0.1 && whoami这个命令不管用,猜测可能是对&&进行了过滤:
代码审计:
<?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>";
}
?>
发现关键过滤代码:
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
对&&和;替换成了空字符串
High难度:
输入刚才四条命令,发现四个都不可以:
这时候代码审计:
关键代码:
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
好像对所有的可能性都进行了过滤?但是仔细观察发现,对于竖线的过滤,后面还有一个空格,所以我们在输入管线代码的时候不要加上空格:
就可以成功了。
Impossible难度:
输入前面所有的可能,发现怎么做都不对
代码审计:
关键代码:
// 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];
。。。。。。。
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
又是一大堆看不懂的函数:
stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
explode() 函数把字符串打散为数组。
is_numeric() 函数用于检测变量是否为数字或数字字符串。
那么很显然,这个过滤器先将字符串按照 . 将命令进行分割成数组,然后看看每个数组是不是数字,如果不是就报错。
这种暂时还没想到破解之法,这种过滤是非常严格了,但是代码执行起来肯定好慢,先进行代码审计进行学习一波。
以上是关于命令注入和DVWA命令注入实例的主要内容,如果未能解决你的问题,请参考以下文章