【靶场练习】--DVWA第二关Command Injection(命令执行)全难度分析

发布于:2025-09-13 ⋅ 阅读:(13) ⋅ 点赞:(0)

本来我是打算写细化的小知识点,但是我发现去找那种细小的知识点很难。哪怕我知道这个知识点,但是面对一片空白,真到要你去创造的时候,还是很难一个一个地总结出来。所以暂时打算通过复习巩固靶场来慢慢梳理。

简介

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.php
    checkToken( $_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地址验证失败,提示用户输入了无效的IP
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
}

// 生成新的Anti-CSRF令牌并存储在会话中,用于下一次请求验证
generateSessionToken();

解读:

  1. 严格的输入验证:通过分割 IP 地址为 4 个部分,并强制验证每个部分必须为数字,确保输入只能是类似x.x.x.x的 IP 格式,彻底阻止了命令连接符等恶意输入。
  2. 防御机制完善
    • 使用 Anti-CSRF 令牌防止跨站请求伪造攻击
    • 采用白名单验证(仅允许数字和点号的合法组合),而非黑名单过滤
    • 输入处理逻辑严谨(去除反斜杠、重新组合 IP 地址)
  3. 命令执行安全:经过严格验证后的$target仅能是合法 IP 地址,无法拼接额外命令,因此shell_exec()的调用是安全的。

网站公告

今日签到

点亮在社区的每一天
去签到