Command Injection,即命令注入,是指通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一
用户通过浏览器提交执行命令,由于服务器端没有对执行函数进行过滤,从而造成可以执行危险命令。
命令连接符:
command1 && command2 先执行command1后执行command2
command1 | command2 只执行command2
command1 & command2 先执行command2后执行command1
以上三种连接符在windows和linux环境下都支持
常用的注入命令:
command1 & command2
不管command1执行成功与否,都会执行command2(将上一个命令的输出作为下一个命令的输入)
command1 && command2
先执行command1执行成功后才会执行command2
command1 | command2
只执行command2
command1 || command2
command1执行失败,再执行command2(若command1执行成功,就不再执行command2)
常用的url编码:
%20 = 空格
%5c =
%26 = &
%7c = |
应该有人和我一样,DVWA回显是乱码,如下:
以下是解决方式:
首先找到这个文件
把字符集编码utf-8改为GB2312
问题完美解决
Low
代码分析:在包含注入命令数据提交后可根据回显结果是否包含执行命令结果特征进行判断是否存在注入命令漏洞,例如在输入命令中包含id的数据,查看响应结果是否包含uid和gid,观察以下代码,我们发现,没有进行任何过滤,我们只需要通过“&&”“&”“|”就可以完成注入
<?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)
stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配点),如果未找到所搜索的字符串,则返回 FALSE。参数string规定被搜索的字符串,参数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符),可选参数before_true为布尔型,默认为“false” ,如果设置为 “true”,函数将返回 search 参数第一次出现之前的字符串部分。
php_uname(mode)
这个函数会返回运行php的操作系统的相关描述,参数mode可取值”a” (此为默认,包含序列”s n r v m”里的所有模式),”s ”(返回操作系统名称),”n”(返回主机名),” r”(返回版本名称),”v”(返回版本信息), ”m”(返回机器类型)。
可以看到,服务器通过判断操作系统执行不同ping命令,但是对ip参数并未做任何的过滤,导致了严重的命令注入漏洞。
1.输入192.168.29.76&&dir,得到如下结果(192.168.29.76是我的主机地址,用本机回环地址127.0.0.1也可以):
2.输入192.168.29.76&net user(net user可以查看用户,然后可以创建用户,把用户添加到管理员组)
我的DVWA出现了一个没有解决的问题就是net user不起作用,与不加的时候显示效果一样),如下: PS:我的问题解决了,解决办法请看文章最后:)
其实输入 192.168.29.76&net user结果应该是这样的(来源:https://blog.csdn.net/ai_64/article/details/92062825)
3.输入 192.168.29.76|dir
Medium
代码分析:在包含注入命令数据提交后可根据回显结果是否包含执行命令结果特征进行判断是否存在注入命令漏洞,例如在输入命令中包含net user的数据,查看响应结果是否包含administrator
<?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>"; } ?>
命令行注入增加了一些过滤,通过查看源码可以看到,他将&&和:过滤成了空字符,但是他并没有过滤“|”,所以我们依然可以进行注入。
1.输入192.168.29.76|net user可以得到如下结果
2.输入192.168.29.76&dir可以得到如下结果
3.这种级别输入127.0.0.1&&net user,结果如下图,;也一样
此时避开“&&”“;”输入&、|等都是可以完成注入的
High
代码分析:在包含注入命令数据提交后可根据回显结果是否包含执行命令结果特征进行判断是否存在注入命令漏洞,例如在输入命令中包含net user的数据,查看响应结果是否包含administrator
<?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>"; } ?>
high等级的命令行注入过滤的东西比较多,但是他在过滤的时候有bug。
这个BUG就是‘| ’替换为空格,后面还有一个空格,所以‘|’就可以利用(源码中是“| ”,所以我们可以用“|”)
我们输入192.168.29.76|net user,如下
关于我的net user没用的解决方法,装的不同的DVWA对应的PHP study版本不一样,打开PHP study,右边有一个切换版本,我将版本切换成下图,再回去submit,问题就解决了