DVWA靶场保姆级通关教程---02命令注入
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
-
目录
文章目录
前言
基本的命令注入原理
简单的注入技巧与命令连接符的使用
Linux中的 : (冒号)
简单绕过手法
一、low级别
low级别源码分析
二、medium级别
代码分析:
注入方法
三、high级别
源码分析
四、impossible级别
源码分析
前言
基本的命令注入原理
-
理解服务器在后台执行系统命令时,如何把用户输入拼接到命令字符串中。
-
如果输入没有正确过滤,攻击者可以注入额外的系统命令并执行,比如:
127.0.0.1; whoami
简单的注入技巧与命令连接符的使用
-
熟练掌握各种操作系统的命令连接符:
-
Linux/Unix下常用:
;
,&&
,|
,||
-
Windows下也可以使用:
&
,|
-
在 Windows cmd 中,
|
也是管道符(pipe),把前一个命令的输出作为后一个命令的输入。和Linux一致。 -
在 Windows cmd 中,
&
是顺序执行(不论前一个命令是否成功,都会继续执行后一个命令)。相当于Linux的;(分号)。
-
Linux中的 :
(冒号)
在 Linux(Shell里),冒号 :
是一个非常特别的内置命令,叫做 "空命令"(null command)。
👉 它的特点是:
-
什么也不做,但返回成功(退出码0)。
-
常用于占位、写流程时需要一个“啥也不做但要占个位置”的情况。
127.0.0.1 && cat /etc/passwd
简单绕过手法
-
比如,直接用替代连接符
&&
或用 URL 编码%26%26
。 -
或者注入拼接无害内容使得原命令完成后继续执行新的命令。
提示:以下是本篇文章正文内容,下面案例可供参考
一、low级别
输入127.0.0.1点击提交出现乱码
在phpstudy中打开网站根目录,找到DVWA中对应的文件 然后把编码形式进行修改,把utf-8改为gb2312
文件路径在dvwa/includes/dvwapage.inc.php
修改完成之后,再点击提交或者刷新页面即可
那么可以尝试用管道符(|)将ping的结果交给管道后面的命令处理,查看可以查看当前用户是谁
尝试用分号去拼接两个命令报错,分号拼接前后两个命令之间没有逻辑关系
在Linux里,命令行中的 &&
是用来串联两个命令的执行关系的,具体来说:
-
只有当前一个命令执行成功(返回值是0),后一个命令才会执行。
-
如果前一个命令执行失败(返回非0退出码),后面的命令就不会执行。
所以,&&
在Shell中体现的逻辑是:“如果前面的命令成功了,那么继续执行后面的命令”。
这里&&后面除了用ipconfig查看ip,也可以whoami查看用户、systeminfo查看系统信息,dir查看目录,可以自己尝试
也可以将上面的两个&&替换成winds中一个&表示顺序执行,无论前面的地址是否能够ping通,后面的命令都会执行,但是输入一个ping不通的地址,等待返回超时,需要多等会儿。而这时候如果这个地址ping不通,是不能用&&的,两个&&链接的命令是有逻辑关系的,前面命令成功才会执行后面的命令,前面地址ping不通,那么&&后面的命令也不执行。
那么如果前面地址ping不通的情况下,使用||表示逻辑或
在 Linux (比如 bash/zsh 这些Shell)中,
||
是逻辑或(OR)操作符,意思是:
如果前一个命令失败(退出状态码非0),那么就执行后一个命令;
如果前一个命令成功(退出码是0),那么后一个命令不会执行。
以下情况由于地址192.168.10.1ping不通(执行失败),那么执行||后的命令whoami
low级别源码分析
<?phpif( isset( $_POST[ 'Submit' ] ) ) { // 如果用户提交了表单(点击了Submit按钮)// Get input$target = $_REQUEST[ 'ip' ]; // 从请求中获取ip参数(可能来自GET或POST)// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // 判断服务器操作系统是不是Windows// Windows$cmd = shell_exec( 'ping ' . $target ); // Windows系统下执行 ping 命令}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target ); // Linux/Unix系统下执行 ping 命令,加上参数-c 4表示只发送4次}// Feedback for the end userecho "<pre>{$cmd}</pre>"; // 把ping命令的执行结果输出到页面上,并用<pre>标签保留格式
}?>
这里隐藏的漏洞点:
-
$target
直接拿用户输入,没有经过任何过滤(比如禁止特殊字符&
、|
、;
之类的)。 -
shell_exec()
是直接调用操作系统的Shell命令执行函数。 -
所以如果用户在
ip
参数里不仅传IP,还加了| whoami
,那么整个Shell执行的命令就变成了:-
Windows:
ping 127.0.0.1 | whoami
-
Linux:
ping -c 4 127.0.0.1 | whoami
-
结果就可以直接命令注入执行了!
二、medium级别
有了前面low级别的基础,直接来分析源码
<?phpif( isset( $_POST[ 'Submit' ] ) ) { // 如果用户提交了表单(点击了Submit按钮)// Get input$target = $_REQUEST[ 'ip' ]; // 从请求中获取 'ip' 参数的值,可能来自 GET 或 POST 请求// 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// Windows$cmd = shell_exec( 'ping ' . $target ); // 如果是Windows,执行 ping 命令,ping目标是用户提供的IP地址}else {// *nix$cmd = shell_exec( 'ping -c 4 ' . $target ); // 如果是 Linux 或 Unix 系统,执行带有 -c 4 参数的 ping 命令,指定只发送4个包}// Feedback for the end userecho "<pre>{$cmd}</pre>"; // 将命令执行结果输出到页面,保留格式输出(<pre>标签保持换行和空格)
}?>
代码分析:
-
黑名单过滤:
-
通过创建一个
$substitutions
数组,代码尝试过滤掉可能导致命令注入的字符,比如&&
(命令链)和;
(命令分隔符)。这是为了防止用户在输入中注入多个命令。 -
但是,这个方法并不完全安全,因为还有其他特殊字符或者更复杂的注入方式(如管道符
|
)没有被拦截。
-
-
操作系统判断:
-
使用
php_uname('s')
判断操作系统是 Windows 还是类 Unix 系统,然后分别执行不同的ping
命令。 -
这个判断是根据操作系统不同选择不同的命令格式,这本身是合理的。
-
-
命令执行:
-
shell_exec()
函数用来执行拼接出来的命令,并返回命令的输出。 -
如果用户输入的
ip
包含不安全的字符,str_replace()
可能可以在一定程度上避免注入,但是这并不是一个完整的安全解决方案,因为它只过滤了少数几个字符。
-
-
用户反馈:
-
命令执行结果会被输出到网页上,使用
<pre>
标签进行格式化显示。这使得用户能够看到ping
命令的执行结果。
-
注入方法
使用不在黑名单里面的命令连接符,比如 | 或者 || 或者 & ,同样可以拼接前面的命令
三、high级别
源码分析
<?phpif( isset( $_POST[ 'Submit' ] ) ) { // 如果用户提交了表单(点击了Submit按钮)// Get input$target = trim($_REQUEST[ 'ip' ]); // 获取用户提交的IP地址,并用trim去除前后空格// Set blacklist$substitutions = array( // 定义一个黑名单,把一些危险字符列出来'&' => '', // 单个&,用于连接命令,清除';' => '', // 分号,能分隔多个命令,清除'| ' => '', // 管道符后带空格的,清除'-' => '', // 减号,可能用来传参数,如ping命令参数,清除'$' => '', // 美元符号,能用来执行如$(命令)或环境变量,清除'(' => '', // 左括号,配合$用于子命令执行,清除')' => '', // 右括号,配合$用于子命令执行,清除'`' => '', // 反引号,可执行反引号内的命令,清除'||' => '', // 双竖线,逻辑或连接符,可分开执行命令,清除);// 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(根据系统名中是否有"Windows NT"判断)// Windows系统下执行ping命令$cmd = shell_exec( 'ping ' . $target );}else {// *nix系统(比如Linux)下执行ping命令,加参数-c 4,表示ping 4次$cmd = shell_exec( 'ping -c 4 ' . $target );}// Feedback for the end userecho "<pre>{$cmd}</pre>"; // 把命令执行结果用pre标签包裹,格式化输出到网页上
}?>
仔细看这里的 '| '后面有一个空格,所以依然可以用 | 这个注入。我们之前在注入的时候
127.0.0.1 | whoami #|后面是有个空格的,是可以成功的
这次high级别写的时候|后面不要加空格,加上空格会被黑名单过滤
简单总结一下:
-
这一版比
medium.php
更加严格了,过滤了更多危险字符。 -
尤其是把单独的
&
、|
、反引号`
、美元符号$()
等都清除了。 -
但它依然是基于黑名单过滤,理论上还是可能被绕过(比如编码、空格变形、双写等手法)。
四、impossible级别
源码分析
<?phpif( isset( $_POST[ 'Submit' ] ) ) { // 如果点击了提交按钮// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // 检查CSRF防护令牌,防止跨站请求伪造攻击// Get input$target = $_REQUEST[ 'ip' ]; // 获取用户提交的IP地址$target = stripslashes( $target ); // 去除字符串中的反斜杠(如果有)// Split the IP into 4 octects$octet = explode( ".", $target ); // 按点号"."分割成4段(四个8位字节)// Check IF each octet is an integerif( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {// 如果每一段都是数字,且总共有4段,说明输入的是合法IP格式// If all 4 octets are int's put the IP back together.$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3]; // 将IP重新组合成标准格式// Determine OS and execute the ping command.if( stristr( php_uname( 's' ), 'Windows NT' ) ) { // 如果服务器是Windows系统$cmd = shell_exec( 'ping ' . $target ); // 执行ping命令}else {// 否则认为是Linux或Unix系统$cmd = shell_exec( 'ping -c 4 ' . $target ); // 执行ping命令并指定4次}// Feedback for the end userecho "<pre>{$cmd}</pre>"; // 把ping结果输出给用户}else {// 如果输入的IP不合法echo '<pre>ERROR: You have entered an invalid IP.</pre>'; // 提示错误信息}
}// Generate Anti-CSRF token
generateSessionToken(); // 重新生成新的CSRF防护令牌?>
🛡️ 过滤方式 | 只允许格式正确的IP地址(四段数字,用"."分隔),其他任何输入直接拒绝。 |
🛡️ CSRF防护 | 使用了token机制防止跨站请求伪造。 |
🛡️ 命令执行点 | 只有经过严格校验的纯数字IP才能进入执行流程,避免了注入。 |
🔥 注入可能性 | 理论上基本没法注入(除非PHP本身或服务器存在其他漏洞,比如某些超老版本PHP漏洞) |