【靶场练习】--DVWA第二关Command Injection(命令执行)全难度分析
本来我是打算写细化的小知识点,但是我发现去找那种细小的知识点很难。哪怕我知道这个知识点,但是面对一片空白,真到要你去创造的时候,还是很难一个一个地总结出来。所以暂时打算通过复习巩固靶场来慢慢梳理。
DVWA
- 简介
- 说明
- Command Injection(命令执行)
- 基础命令连接符
- 1. 顺序执行符 `;`
- 2. 逻辑与符 `&&`
- 3. 逻辑或符 `||`
- 4. 后台执行符 `&`
- 5. 管道符 `|`
- 6. 命令替换符 `$()` 或 `` ` ` ``
- 7. 重定向符 `>` `>>` `<`
- 等等
- 提前说明
- LOW
- MEDIUM
- HIGH
- IMPOSSIBLE
简介
DVWA(Damn Vulnerable Web Application)即 “该死的易受攻击的 Web 应用程序”,是一款基于 PHP 和 MySQL 的开源 Web 安全脆弱性演示应用程序,主要用于帮助安全专业人员、开发人员和爱好者学习和测试常见 Web 漏洞。
说明
相关靶场搭建可以看"苒汐在想你ᵃ"的文章
每一关都有对应的低,中,高,不可能四个等级:
一共有:
这些关卡。
如果要查看源码可以在以下目录中看: (因为我会做全难度的解析那么肯定绕不开代码,不然连不同难度的区别具体是什么都不知道。当然,代码肯定只是用来结合理解的,实际情况是很难看到源码的)
dvwa/
└── vulnerabilities/ # 所有漏洞关卡的根目录├── api/ # API相关漏洞场景├── authbypass/ # 身份认证绕过漏洞场景├── brute/ # 暴力破解漏洞场景├── captcha/ # 验证码相关漏洞场景├── cryptography/ # 加密相关漏洞场景├── csp/ # 内容安全策略(CSP)相关漏洞场景├── csrf/ # 跨站请求伪造(CSRF)漏洞场景├── exec/ # 命令执行漏洞场景├── fi/ # 文件包含漏洞场景├── javascript/ # JavaScript相关漏洞场景├── open_redirect/ # 开放重定向漏洞场景├── sqli/ # SQL注入漏洞场景├── sqli_blind/ # SQL盲注漏洞场景├── upload/ # 文件上传漏洞场景├── weak_id/ # 弱身份标识漏洞场景├── xss_d/ # DOM型XSS漏洞场景├── xss_r/ # 反射型XSS漏洞场景├── xss_s/ # 存储型XSS漏洞场景├── help.css # 帮助页面样式文件├── help.js # 帮助页面脚本文件├── view_help.php # 帮助页面查看文件├── view_source.php # 单文件源码查看工具└── view_source_all.php # 批量源码查看工具1.每个漏洞类型文件夹(如brute/、sqli/等)内部通常会包含对应难度级别的实现文件(low.php/medium.php 等)
2.底部的view_source.php等文件是 DVWA 的辅助功能模块,用于查看各漏洞关卡的源代码实现
也可以直接在右下角查看
Command Injection(命令执行)
基础命令连接符
1. 顺序执行符 ;
- 作用:无论前一条命令执行成功或失败,均按顺序执行后续命令,不依赖前序结果。
2. 逻辑与符 &&
- 作用:仅当前一条命令执行成功(返回状态码 0)时,才执行后一条命令,前序失败则后续不执行。
3. 逻辑或符 ||
- 作用:仅当前一条命令执行失败(返回非 0 状态码)时,才执行后一条命令,前序成功则后续不执行。
4. 后台执行符 &
- 作用:在 Linux/macOS 中,将命令放入后台运行,不阻塞当前终端操作;Windows CMD 中仅等同于
;
,无后台功能。
5. 管道符 |
- 作用:将前一条命令的输出结果,作为后一条命令的输入内容,实现命令间数据传递与协作。
6. 命令替换符 $()
或 ` `
- 作用:执行括号/反引号内的命令,将其输出结果替换到当前命令行中,作为参数或内容使用。
7. 重定向符 >
>>
<
>
:覆盖式重定向,将命令输出写入指定文件,原有文件内容会被清空。>>
:追加式重定向,将命令输出追加到指定文件末尾,不覆盖原有内容。<
:输入重定向,将指定文件的内容作为命令的输入源。
等等
提前说明
如果ping出来是像下面一样乱码,可以先修改配置文件再做实验
找到该文件
修改编码
返回正常
LOW
记得调低等级
很明显随便输入一个管道符后都可以直接执行命令
查看源码,可知并未做过滤处理
<?php// 检查用户是否通过POST方式提交了表单(点击了名为'Submit'的按钮)
if( isset( $_POST[ 'Submit' ] ) ) {// 获取用户输入的IP地址参数,支持POST和GET两种方式提交// 不足:未对用户输入进行任何过滤和验证,为后续命令注入埋下隐患$target = $_REQUEST[ 'ip' ];// 判断服务器操作系统类型(Windows或类Unix),以执行对应的ping命令if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows系统下执行ping命令// 不足:直接将用户输入的$target拼接到命令字符串中,攻击者可通过特殊构造的输入执行额外系统命令(命令注入)$cmd = shell_exec( 'ping ' . $target );}else {// 类Unix系统(Linux/macOS等)下执行ping命令(-c 4指定发送4个数据包)// 不足:同样直接拼接用户输入,存在与Windows环境相同的命令注入漏洞$cmd = shell_exec( 'ping -c 4 ' . $target );}// 将命令执行结果从GBK编码转换为UTF-8,避免中文乱码$cmd = iconv("GBK", "UTF-8", $cmd);// 将ping命令的结果以预格式化文本形式添加到页面输出中$html .= "<pre>{$cmd}</pre>";
}?>
MEDIUM
换了难度
使用&&发现居然不可以绕过了,查看源码发现刚好把&&给ban掉了
<?php// 检查用户是否通过POST方式提交了表单(点击了名为'Submit'的按钮)
if( isset( $_POST[ 'Submit' ] ) ) {// 获取用户输入的IP地址参数,支持POST和GET两种方式提交$target = $_REQUEST[ 'ip' ];// 定义命令注入过滤的黑名单,包含常见的命令连接符$substitutions = array('&&' => '', // 过滤逻辑与连接符';' => '', // 过滤分号连接符);// 使用str_replace函数将用户输入中匹配黑名单的字符替换为空(移除)// 不足:仅过滤了部分连接符,黑名单规则过于简单,防御不彻底$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// 判断服务器操作系统类型,执行对应的ping命令if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows系统下执行ping命令// 不足:虽然做了简单过滤,但仍存在命令注入风险(如可使用&、|等未过滤的连接符)$cmd = shell_exec( 'ping ' . $target );}else {// 类Unix系统下执行ping命令// 不足:同样存在命令注入风险,攻击者可利用未被过滤的连接符构造恶意命令$cmd = shell_exec( 'ping -c 4 ' . $target );}// 将ping命令的结果以预格式化文本形式输出给用户echo "<pre>{$cmd}</pre>";
}?>
那就换其他没有被禁的就好啦
1. 127.0.0.1&whoami
2. 127.0.0.1|whoami
3. a||whoami
也是非常轻松
HIGH
经过一番尝试依旧无果,但是难度又不是不可能的,只是比较高而已,到底是怎么回事呢?查看源码可知:
<?php// 检查用户是否通过POST方式提交了表单(点击了名为'Submit'的按钮)
if( isset( $_POST[ 'Submit' ] ) ) {// 获取用户输入的IP地址参数,支持POST和GET方式,并去除首尾空白字符$target = trim($_REQUEST[ 'ip' ]);// 定义更严格的命令注入过滤黑名单,包含多种命令连接符和特殊字符$substitutions = array('||' => '', // 过滤逻辑或连接符'&' => '', // 过滤&连接符';' => '', // 过滤分号连接符'| ' => '', // 过滤带空格的管道符***'-' => '', // 过滤连字符(可能用于命令参数)'$' => '', // 过滤美元符号(可能用于变量)'(' => '', // 过滤左括号')' => '', // 过滤右括号'`' => '', // 过滤反引号(命令替换));// 使用str_replace函数移除用户输入中匹配黑名单的字符// 突破点:“| ”其实只过滤了|加空格的组合,并没有过滤|$target = str_replace( array_keys( $substitutions ), $substitutions, $target );// 判断服务器操作系统类型,执行对应的ping命令if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows系统下执行ping命令$cmd = shell_exec( 'ping ' . $target );}else {// 类Unix系统下执行ping命令$cmd = shell_exec( 'ping -c 4 ' . $target );}// 将ping命令的结果以预格式化文本形式输出给用户echo "<pre>{$cmd}</pre>";
}?>
果然输入127.0.0.1|whoami
就可以成功执行(除了whoami还可以输入dir呀啥的查看更加敏感数据):
IMPOSSIBLE
这个难度号称不可能攻破,是代码规范的典型案例,直接进行代码分析:
<?php// 检查用户是否通过POST方式提交了表单(点击了名为'Submit'的按钮)
if( isset( $_POST[ 'Submit' ] ) ) {// 验证Anti-CSRF令牌,防止跨站请求伪造攻击// 对比用户提交的token与会话中存储的token,不匹配则跳转至index.phpcheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// 获取用户输入的IP地址参数,支持POST和GET方式$target = $_REQUEST[ 'ip' ];// 去除用户输入中的反斜杠(用于处理魔术引号开启的情况)$target = stripslashes( $target );// 将输入的IP地址按点号分割为4个部分( octet 意为IP地址的八位组)$octet = explode( ".", $target );// 验证IP地址的合法性:检查分割后的4个部分是否都是数字,且正好分割为4个部分// is_numeric() 确保每个部分都是数字,sizeof($octet) == 4 确保是4段式结构if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {// 如果4个部分都是数字,则重新组合为IP地址格式$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];// 判断服务器操作系统类型,执行对应的ping命令if( stristr( php_uname( 's' ), 'Windows NT' ) ) {// Windows系统下执行ping命令$cmd = shell_exec( 'ping ' . $target );}else {// 类Unix系统下执行ping命令(-c 4指定发送4个数据包)$cmd = shell_exec( 'ping -c 4 ' . $target );}// 将ping命令的结果以预格式化文本形式输出给用户echo "<pre>{$cmd}</pre>";}else {// 如果IP地址验证失败,提示用户输入了无效的IPecho '<pre>ERROR: You have entered an invalid IP.</pre>';}
}// 生成新的Anti-CSRF令牌并存储在会话中,用于下一次请求验证
generateSessionToken();
解读:
- 严格的输入验证:通过分割 IP 地址为 4 个部分,并强制验证每个部分必须为数字,确保输入只能是类似
x
.x
.x
.x
的 IP 格式,彻底阻止了命令连接符等恶意输入。 - 防御机制完善:
- 使用 Anti-CSRF 令牌防止跨站请求伪造攻击
- 采用白名单验证(仅允许数字和点号的合法组合),而非黑名单过滤
- 输入处理逻辑严谨(去除反斜杠、重新组合 IP 地址)
- 命令执行安全:经过严格验证后的
$target
仅能是合法 IP 地址,无法拼接额外命令,因此shell_exec()
的调用是安全的。