欢迎光临
我们一直在努力

DVWA不安全验证码(Insecure CAPTCHA)漏洞实战教学指南(Low → Medium → High → Impossible 全级别)(源码分析+实操步骤+防御方案)

⚠️ 重要声明
本文所述所有技术 仅限 用于网络安全研究、CTF 等合法授权的靶场以及个人的学习环境。根据《网络安全法》,未经授权对任何系统进行渗透测试均是违法行为。请务必坚守职业道德,仅在法律允许的范围内实践。

前言:什么是 Insecure CAPTCHA?

Insecure CAPTCHA(不安全的验证码) 并非指谷歌 reCAPTCHA 等验证码服务本身存在漏洞,而是指在应用验证码的过程中,由于验证流程设计不当,导致攻击者能够绕过验证码校验,从而威胁到系统安全。

CAPTCHA(全自动区分计算机和人类的图灵测试)的核心作用是识别操作者是人类还是机器,以防止暴力破解、刷单等自动化攻击。然而,当验证码的验证流程被拆分、前后步骤之间缺乏绑定时,攻击者就可以利用其中的逻辑漏洞,通过篡改请求参数来绕过验证码,直接完成敏感操作。

在 DVWA 的 Insecure CAPTCHA 模块中,系统调用谷歌 reCAPTCHA 验证码服务,演示了在不同安全级别下,如何因验证流程设计缺陷而让验证码形同虚设。以下将从 Low 到 Impossible 四个级别,逐一剖析源码、演示绕过手法,并给出完整的防御方案。

第一部分:前置准备

1.1 靶场环境搭建

# Low 级别
docker run –name dvwa-low -d -p 8080:80 vulnerables/web-dvwa

# Medium 级别
docker run –name dvwa-medium -d -p 8081:80 -e DVWA_SECURITY_LEVEL=medium vulnerables/web-dvwa

# High 级别
docker run –name dvwa-high -d -p 8082:80 -e DVWA_SECURITY_LEVEL=high vulnerables/web-dvwa

# Impossible 级别
docker run –name dvwa-impossible -d -p 8083:80 -e DVWA_SECURITY_LEVEL=impossible vulnerables/web-dvwa

 补充说明:登录 DVWA(默认账号 admin / password),在 DVWA Security 页面选择安全级别后,进入 Insecure CAPTCHA 模块进行实验。

1.2 必备工具

  • Burp Suite:抓包、篡改参数,核心攻击工具。
  • 浏览器:Chrome / Firefox。
  • 编辑器:用于查看和修改 DVWA 配置文件。

1.3 reCAPTCHA 配置说明(重要)

DVWA 的 Insecure CAPTCHA 模块使用谷歌 reCAPTCHA 服务,需要先配置 API 密钥。如未配置,页面会显示警告且功能不可用。

修改 DVWA/config/config.inc.php,添加 reCAPTCHA 密钥配置。以下是两种配置方式:

方式一:使用 DVWA 官方提供的静态测试密钥

根据 DVWA 官方文档,可以使用以下测试密钥。密钥会自动匹配任何域名(包括 127.0.0.1 和 localhost):

$_DVWA[ 'recaptcha_public_key' ]  = '6LdK7xITAAzzAAJQTfL7fu6I-0aPl8KHHieAT_yJg';
$_DVWA[ 'recaptcha_private_key' ] = '6LdK7xITAzzAAL_uw9YXVUOPoIHPZLfw2K1n5NVQ';

⚠️ 关于密钥的有效性:以上为 DVWA 官方提供的静态测试密钥。由于谷歌更新了策略,这些测试密钥可能已失效。若无法使用,请采用方式二或直接使用下文附录中的社区可用测试密钥。

方式二:自行注册 reCAPTCHA 密钥

也可以自行注册 reCAPTCHA v2 密钥,域名填写 127.0.0.1 或 localhost 即可。
注册地址:https://www.google.com/recaptcha/admin/create

注:该页面为境外网页,当前网络环境下可能无法访问,推荐优先使用方式一的测试密钥完成实验;如需注册请通过合规网络环境访问。(国内网络可能需要合规 VPN 访问)。

注册后可获取以下形式的密钥(以实际生成结果为准):

$_DVWA[ 'recaptcha_public_key' ]  = '6LdJJlUUAAAAAH1Q6cTpZRQ2Ah8VpyzhnffD0mBb';
$_DVWA[ 'recaptcha_private_key' ] = '6LdJJlUUAAAAAM2a3HrgzLczqdYp4g05EqDs-W4K';

 说明:以上密钥是社区中实际可用的测试密钥,对任意域名均返回验证成功,可以作为本文实验的参考配置。

配置完成后,重新加载 DVWA 页面即可正常使用验证码功能。如仍显示验证码无法加载,可能是谷歌服务在大陆地区访问受限所致,但这不影响漏洞演示——本文的绕过手法不依赖验证码是否真正显示。

1.4 基础知识储备

  • reCAPTCHA 正常验证流程:
  • 页面加载 reCAPTCHA 组件,用户完成验证。
  • 前端生成 g-recaptcha-response 令牌(token),提交给后端。
  • 后端调用谷歌 API 验证该令牌,返回 true/false
    • 核心漏洞原理:验证码验证流程与最终敏感操作分离(分为 step=1 和 step=2),后端仅凭客户端提交的 step 参数或其他自定义标志判断是否已通过验证,攻击者通过篡改参数直接跳过验证。

    第二部分:Low 级别(两步流程分离)

    2.1 核心特点

    • 两步流程:第一步验证验证码,验证通过后返回包含 step=2 的确认表单;第二步由用户提交确认表单完成密码修改。
    • 后端仅靠 step 参数判断用户是否已通过验证码,无任何状态记录。

    2.2 源码分析

    第一步:验证验证码(step == 1

    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
        $pass_new = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
        // 调用谷歌 API 验证验证码
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ], $_POST['g-recaptcha-response'] );
        
        if( !$resp ) {
            // 验证码错误
            $html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        } else {
            // 验证码正确,生成确认表单
            echo "<form action=\\"#\\" method=\\"POST\\">
                     <input type=\\"hidden\\" name=\\"step\\" value=\\"2\\" />
                     <input type=\\"hidden\\" name=\\"password_new\\" value=\\"{$pass_new}\\" />
                     <input type=\\"hidden\\" name=\\"password_conf\\" value=\\"{$pass_conf}\\" />
                     <input type=\\"submit\\" name=\\"Change\\" value=\\"Change\\" />
                  </form>";
        }
    }

    第二步:完成密码修改(step == 2

    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
        $pass_new = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
        
        if( $pass_new == $pass_conf ) {
            $pass_new = md5( $pass_new );
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            $result = mysqli_query(…);
            echo "<pre>Password Changed.</pre>";
        }
    }

    关键缺陷:后端不验证 step == 2 的请求是否真的通过了第一步验证,仅凭客户端提交的 step 参数作为判断依据。攻击者只需直接发送 step=2 的 POST 请求,即可绕过验证码,直接完成密码修改。

    2.3 攻击原理

  • 用户填写新密码并提交时,系统发送 step=1 请求验证验证码。
  • 如果验证码正确,服务器返回一个包含 step=2 隐藏字段的确认表单。
  • 攻击者直接抓取任意修改密码请求,将 step=1 篡改为 step=2,发送给服务器。
  • 服务器收到 step=2 请求,不校验验证码状态,直接执行密码修改操作。
  • 2.4 实操步骤

  • 在 DVWA 页面输入新密码和确认密码。
  • 打开 Burp Suite,开启拦截。
  • 点击 Change 按钮,拦截请求如下:
  • Plaintext
    step=1&password_new=123456&password_conf=123456&Change=Change

    说明:即使验证码组件未显示或未加载,原始请求中可能包含 g-recaptcha-response= 空字段。本绕过方法不需要填写验证码,也不需要保留该字段。

  • step=1 修改为 step=2,可以删除 g-recaptcha-response 字段(保留也不影响)。
  • 放行修改后的请求,页面显示“Password Changed”,密码修改成功。
  •  配合 CSRF 利用:由于无任何 Token 防护,攻击者可构造恶意页面诱使用户点击,自动提交 step=2 请求,完成 CSRF 攻击。

    ⚠️ 实验完成提醒:修改密码后,建议将密码改回 password,以免后续其他模块(如 Brute Force)使用默认密码 password 时失败。

    2.5 典型 Payload

    类型

    Payload

    说明

    直接绕过

    step=2&password_new=123&password_conf=123&Change=Change

    不经过验证码验证,直接修改密码

    CSRF 利用

    构造包含上述参数的 POST 表单,诱导用户提交

    跨站请求伪造修改用户密码

    第三部分:Medium 级别(passed_captcha 标志)

    3.1 核心特点

    • 在 Low 级别的基础上,增加了 passed_captcha 参数校验。
    • 第二步需要 step == 2 且 passed_captcha == true 才能修改密码。
    • passed_captcha 同样由前端控制,攻击者可以手动添加。

    3.2 源码分析

    // 第一步:验证验证码(与 Low 级别基本相同)
    if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '1' ) ) {
        // 验证验证码…
        if( !$resp ) {
            // 验证码错误
        } else {
            // 生成包含 step=2 和 passed_captcha=true 的确认表单
            echo "<form>
                    <input type=\\"hidden\\" name=\\"step\\" value=\\"2\\" />
                    <input type=\\"hidden\\" name=\\"passed_captcha\\" value=\\"true\\" />
                    …
                  </form>";
        }
    }

    // 第二步:完成密码修改
    else if( $step == 2 && $_POST[ 'passed_captcha' ] == 'true' ) {
        // 校验两次密码是否一致
        if( $pass_new == $pass_conf ) {
            // 更新数据库密码
            $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
            echo "<pre>密码修改成功!</pre>";
        }
    }

     说明passed_captcha 是 DVWA 自定义的字段名,并非 reCAPTCHA 标准参数。

    关键缺陷:passed_captcha 参数仍然来自前端隐藏表单,攻击者可在 POST 请求中手动添加该参数并设置为 true,绕过验证。

    3.3 攻击原理

  • 抓取任意修改密码请求,修改 step=2
  • 添加 &passed_captcha=true 参数。
  • 发送修改后的请求,服务器认为前端已标记验证码通过,直接执行密码修改。
  • 3.4 实操步骤

  • 开启 Burp Suite 拦截。
  • 在 DVWA 页面点击 Change 按钮,拦截请求。
  • 修改参数(可删除 g-recaptcha-response):
  • Plaintext
    step=2&password_new=123456&password_conf=123456&Change=Change&passed_captcha=true

  • 放行请求,页面提示密码修改成功。
  •  本质无区别:Medium 级别仅仅增加了一个前端可控的标志位,绕过的原理与 Low 级别完全一致,并无实际防御效果。

    ⚠️ 实验完成提醒:修改密码后,建议将密码改回 password,以免影响后续其他模块的实验。

    3.5 典型 Payload

    类型

    Payload

    说明

    直接绕过

    step=2&password_new=123&password_conf=123&Change=Change&passed_captcha=true

    无验证码修改密码

    第四部分:High 级别(后台硬编码后门)

    4.1 核心特点

    • 流程改为单步:不再区分 step=1 和 step=2,直接在一步内完成验证码校验和密码修改。
    • 存在开发后门:代码中埋设了一个故意留的后门——只需满足特定条件即可绕过 reCAPTCHA 的正常校验。
    • User-Agent 和 g-recaptcha-response 均由前端提交。

    4.2 源码分析

    // 不再依赖 step 参数,单步完成验证
    if( isset( $_POST[ 'Change' ] ) ) {
        $pass_new = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
        
        // 调用谷歌 API 验证验证码
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ], $_POST['g-recaptcha-response'] );
        
        // 关键后门:满足以下条件之一即认为验证码正确
        if( $resp || ( $_POST[ 'g-recaptcha-response' ] == 'hidd3n_valu3' && $_SERVER[ 'HTTP_USER_AGENT' ] == 'reCAPTCHA' ) ) {
            // 验证码正确,更新密码
            if( $pass_new == $pass_conf ) {
                // 更新数据库
            }
        } else {
            // 验证码错误
        }
    }

    关键缺陷:条件判断为

    if( $resp || ( $_POST['g-recaptcha-response'] == 'hidd3n_valu3' && $_SERVER['HTTP_USER_AGENT'] == 'reCAPTCHA' ) )

    这意味着除了正常的 reCAPTCHA 校验通过外,只要满足以下两个条件,同样可以绕过:

    • POST 参数 g-recaptcha-response 等于 hidd3n_valu3
    • 请求头 User-Agent 等于 reCAPTCHA

    这是开发者留下的 硬编码后门(可能用于自动化测试脚本)。攻击者可通过抓包手动添加这两个条件直接绕过验证码。

    4.3 攻击原理

    抓取任意修改密码请求,在 POST 请求中添加 g-recaptcha-response=hidd3n_valu3 参数,并将 HTTP 请求头中的 User-Agent 修改为 reCAPTCHA,即可完全绕过验证码。

    4.4 实操步骤

  • 开启 Burp Suite 拦截。
  • 在 DVWA 页面点击 Change 按钮,拦截请求。
  • 修改 HTTP 请求头:找到 User-Agent 字段,删除原有值,填入 reCAPTCHA
  • Plaintext
    User-Agent: reCAPTCHA

  • 修改 POST 参数:在请求 Body 中增加 g-recaptcha-response=hidd3n_valu3(可保留原有参数,直接添加即可)。
  • 修改后的请求示例:
  • Plaintext
    POST /vulnerabilities/captcha/ HTTP/1.1
    User-Agent: reCAPTCHA

    password_new=123456&password_conf=123456&Change=Change&g-recaptcha-response=hidd3n_valu3

  • 放行请求,密码修改成功。
  •  开发后门隐患:此级别的设计暴露了一个现实问题——开发人员在代码中留“测试后门”并忘记删除,将成为严重安全隐患。同理,如果使用了谷歌 reCAPTCHA 的测试密钥(公开密钥),任何人都能绕过验证。

    ⚠️ 实验完成提醒:修改密码后,建议将密码改回 password,以免影响后续其他模块的实验。

    4.5 典型 Payload

    类型

    Payload

    说明

    后门绕过

    POST Body 加 g-recaptcha-response=hidd3n_valu3,Header 加 User-Agent: reCAPTCHA

    利用硬编码后门绕过验证码

    第五部分:Impossible 级别(严格防御)

    5.1 核心特点

    • 合并验证步骤:验证码验证与密码修改在同一个请求中完成,不存在中间状态被篡改的可能。
    • 要求输入原密码:增加身份二次验证,防止 CSRF 攻击。
    • Anti-CSRF Token:加入动态 Token 防止跨站请求伪造。
    • PDO 预编译:彻底防御 SQL 注入。
    • 验证码无法绕过:所有防护层层叠加,攻击手段全部失效。

    �� 注:原密码校验使用了 md5($pass_curr) 与数据库中的哈希比较,MD5 本身不安全(生产环境应使用 bcrypt 或 Argon2),但本漏洞重点在于验证码绕过逻辑,此处仅为演示。

    5.2 源码分析

    if( isset( $_POST[ 'Change' ] ) ) {
        // Anti-CSRF Token 校验
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
        
        // 获取原密码、新密码、确认密码
        $pass_curr = $_POST[ 'password_current' ];
        $pass_new  = $_POST[ 'password_new' ];
        $pass_conf = $_POST[ 'password_conf' ];
        
        // 校验验证码(调用谷歌 API)
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ], $_POST['g-recaptcha-response'] );
        
        if( !$resp ) {
            // 验证码错误,直接退出
            echo "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
            $hide_form = false;
            return;
        }
        
        // 校验原密码是否正确
        $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR );
        $data->execute();
        $row = $data->fetch();
        
        if( $row['password'] != md5( $pass_curr ) ) {
            // 原密码错误
            echo "<pre><br />Your current password is incorrect.</pre>";
        } else if( $pass_new != $pass_conf ) {
            // 新密码两次输入不一致
            echo "<pre>Passwords did not match.</pre>";
        } else {
            // 所有校验通过,更新密码(使用 PDO 预编译)
            $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':password', $new_pass_md5, PDO::PARAM_STR );
            $data->bindParam( ':user', $user, PDO::PARAM_STR );
            $data->execute();
            echo "<pre>Password Changed.</pre>";
        }
    }

    5.3 为什么无法攻击?

    • 无中间状态:验证码验证和密码修改在单次请求内同步完成,不存在可供篡改的中间步骤。
    • Anti-CSRF Token:Token 与会话绑定,一次性使用,攻击者无法伪造或重用。
    • 原密码验证:即使用户被诱导提交恶意请求,攻击者不知道原密码也无法更改。
    • PDO 预编译:杜绝 SQL 注入,无法通过注入绕过。
    • 验证码无法绕过:唯一通过方式是通过谷歌 reCAPTCHA 的真实校验,无法伪造。

    第六部分:四级别核心对比

    对比项

    Low 级别

    Medium 级别

    High 级别

    Impossible 级别

    漏洞核心

    step 参数验证

    step + passed_captcha 均前端可控

    硬编码后门(hidd3n_valu3 + User-Agent

    多层验证

    绕过方式

    直接修改 step=2

    添加 &passed_captcha=true

    修改 POST 参数 + HTTP 头部

    无法绕过

    Anti-CSRF Token

    ❌ 无

    ❌ 无

    ❌ 无

    ✅ 有

    原密码验证

    ❌ 无

    ❌ 无

    ❌ 无

    ✅ 有

    SQL 注入防御

    ❌ 无(直接拼接)

    ⚠️ 有转义(但本漏洞未涉及)

    ⚠️ 有转义(但本漏洞未涉及)

    ✅ PDO 预编译

    验证码是否可绕过

    ✅ 是

    ✅ 是

    ✅ 是

    ❌ 否

    �� SQL 注入防御说明:Low 级别无任何防御;Medium/High 级别使用了 mysqli_real_escape_string 等转义函数,但本漏洞的核心是验证码绕过,因此不作为重点。表中标注“有转义”仅供参考。

    演进启示:

    • Low/Medium:缺陷在于前后端状态分离且状态参数可篡改。开发人员错误地将前端传回的布尔标志(passed_captcha)当作可信来源。
    • High:暴露了“开发测试后门未清除”的高危实践问题,与“测试密钥泄露”同属隐蔽但严重的安全隐患。
    • Impossible:组合防御(合并步骤 + CSRF Token + 原密码验证 + PDO 预编译)才是解决问题的正确方向。

    一句话总结:安全设计不能依赖客户端参数,必须将关键操作步骤合并,并使用多重服务端验证构建纵深防御。

    第七部分:防御方案与最佳实践

    7.1 合并敏感操作的验证与执行步骤(最推荐)

    敏感操作(如密码修改、支付等)中的验证码验证与最终执行应在单次请求内同步完成,避免拆分为多个步骤。如果因业务逻辑必须分步,应在服务端记录完成状态(存入 Session),而非依赖前端传回标志。

    // 推荐模式:单步完成
    if( isset( $_POST['Change'] ) ) {
        // 1. 验证验证码
        $resp = recaptcha_check_answer( $_DVWA[ 'recaptcha_private_key' ], $_POST['g-recaptcha-response'] );
        if( !$resp ) {
            die("验证码错误,请重新验证");
        }
        // 2. 验证通过,修改密码
        $pass_new = $_POST['password_new'];
        $pass_conf = $_POST['password_conf'];
        if( $pass_new == $pass_conf ) {
            update_password( $pass_new );
            echo "密码修改成功";
        } else {
            die("两次输入密码不一致");
        }
    }

    7.2 服务端状态验证(分步时的备选)

    如果必须分步,应在验证码验证通过后,将状态存入 Session,并在后续步骤中验证该 Session 标志。

    // 第一步:验证码通过后
    $_SESSION['captcha_passed'] = true;
    $_SESSION['captcha_expire'] = time() + 300; // 5分钟过期

    // 第二步:修改密码前
    if( !isset($_SESSION['captcha_passed']) || $_SESSION['captcha_expire'] < time() ) {
        die("未通过验证码或已过期");
    }

    7.3 CSRF Token 防护

    所有状态变更操作应加入随机的 CSRF Token,并与用户会话绑定。

    // 生成 Token
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    // 表单中输出
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    // 验证 Token
    if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) die("CSRF token 验证失败");

    7.4 身份二次确认

    在修改密码等敏感操作中,要求用户输入原密码,这是抵御 CSRF 和会话劫持的有效措施。

    7.5 清理测试代码与禁用测试密钥

    • 禁止在生产环境使用测试密钥。谷歌 reCAPTCHA 的公开测试密钥可被任何人用于绕过验证码。
    • 所有开发过程中的后门、测试代码在上线前必须彻底移除。
    • 使用版本控制系统和代码审查机制,防止遗留代码流入生产。

    7.6 PDO 预编译 + 参数绑定(防 SQL 注入)

    $stmt = $db->prepare("SELECT * FROM users WHERE user = :user");
    $stmt->bindParam(':user', $username, PDO::PARAM_STR);
    $stmt->execute();

    7.7 禁用敏感 HTTP 方法

    敏感操作应使用 POST 而非 GET,但需配合 CSRF Token(仅 POST 不能防御 CSRF)。

    7.8 防御方案优先级总结

    优先级

    防御措施

    作用

    最高

    合并验证步骤(单步完成)

    从根本上杜绝中间状态被篡改

    CSRF Token

    防止跨站请求伪造

    原密码验证

    增强身份确认,抵御 CSRF

    服务端 Session 状态

    分步时的备选方案

    PDO 预编译

    防止 SQL 注入

    清除测试后门 / 禁用测试密钥

    防止隐蔽的绕过途径

    第八部分:常见问题与解答

    Q1:为什么会显示“reCAPTCHA API key missing”报错?
    A:Insecure CAPTCHA 模块依赖谷歌 reCAPTCHA 服务,必须在 config/config.inc.php 中配置公私钥。使用 DVWA 提供的测试密钥或自行注册的密钥即可解决。

    Q2:配置密钥后还是无法显示验证码,怎么办?
    A:谷歌服务在大陆地区访问受限,可能无法正常加载。这并不影响漏洞演示——验证码虽不显示,但其验证逻辑和参数绕过流程依然完整可测。Low/Medium 级别的绕过根本不需要填写验证码。

    Q3:为什么 passed_captcha=true 可以绕过?
    A:Medium 级别将验证码“已通过”状态以隐藏表单字段的形式发送给客户端,再由客户端随第二次请求发回服务器。攻击者直接在 POST 请求中添加该参数并设为 true,即可欺骗服务器。

    Q4:测试密钥和后门的危害有多大?
    A:使用测试密钥的验证码形同虚设,任何人都能绕过。High 级别的 hidd3n_valu3 后门同样属于隐蔽但极其危险的漏洞——开发人员可能为调试方便留下后门,一旦忘记删除,攻击者可轻易利用。

    Q5:攻击者无法输入原密码时,如何防御 CSRF?
    A:CSRF Token 是首道防线(验证请求来源),原密码验证是第二道防线(验证操作者是本人)。两者结合,即使 CSRF Token 泄露,攻击者仍无法通过原密码校验。

    Q6:Impossible 级别的 Anti-CSRF Token 在哪里获取?
    A:Token 通常以隐藏表单字段(user_token)的形式存在于 HTML 中。服务端通过 checkToken() 函数比对请求中的 Token 与会话中的 Token 是否一致。由于 Token 与会话绑定,无法像 passed_captcha 那样通过抓包随意添加。

    第九部分:核心总结与下一步学习

    核心总结

    级别

    缺陷类型

    绕过方法

    能否防御

    Low

    step 参数完全由前端控制,无状态记录

    直接将 step=1 修改为 step=2

    ❌ 否

    Medium

    新增 passed_captcha 仍由前端控制

    添加 &passed_captcha=true

    ❌ 否

    High

    硬编码后门

    添加 g-recaptcha-response=hidd3n_valu3 + User-Agent: reCAPTCHA

    ❌ 否

    Impossible

    多层验证(Token + 原密码 + PDO + 合并步骤)

    无法绕过

    ✅ 是

    防御核心:合并验证与执行步骤 + CSRF Token + 原密码验证 + 服务端状态存储 的组合方案是防御验证码绕过的最优实践。

    下一步学习建议

    • 状态存储实践:在项目中尝试实现安全的验证码验证流程——验证码通过后,将状态存入 Session,而不是依赖前端传回标志。
    • CSRF Token 实现:研究 Anti-CSRF Token 的生成、存储和验证机制,理解其与 Session 绑定的必要性。
    • 代码审计练习:检查自己或开源项目中有无“开发后门”或“测试密钥”残留。
    • PDO 预编译:在练习中全面使用 PDO 预处理代替字符串拼接 SQL,结合本次漏洞理解其安全价值。
    • 多因素认证(MFA):尝试在实际项目中集成短信验证码或 TOTP(如 Google Authenticator),作为密码修改等高危操作的二次验证。
    • CTF 实战:在 DVWA、HTB 或 CTF 平台上练习验证码绕过相关挑战题,深化对逻辑漏洞的理解。

    附录:DVWA 各模块测试密钥与默认凭据汇总

    为了方便读者查阅和配置,以下汇总 DVWA 中常用的测试密钥、默认凭据和内部 Token 说明。

    A1. reCAPTCHA 密钥

    类型

    Public Key

    Private Key

    说明

    DVWA 官方测试密钥

    6LdK7xITAAzzAAJQTfL7fu6I-0aPl8KHHieAT_yJg

    6LdK7xITAzzAAL_uw9YXVUOPoIHPZLfw2K1n5NVQ

    可能与最新策略不兼容

    社区可用测试密钥

    6LdJJlUUAAAAAH1Q6cTpZRQ2Ah8VpyzhnffD0mBb

    6LdJJlUUAAAAAM2a3HrgzLczqdYp4g05EqDs-W4K

    实际可用的备用密钥

    自行注册

    从 Google reCAPTCHA 官网获取

    从 Google reCAPTCHA 官网获取

    注册时域名填写 127.0.0.1 或 localhost

     提示:如果上述密钥均无效,请自行注册(域名填 127.0.0.1),将获取的密钥填入 config/config.inc.php 即可。

    ⚠️ 国内网络访问说明:由于谷歌相关服务在国内网络环境下可能受限,直接访问注册链接 https://www.google.com/recaptcha/admin/create 可能无法打开(当前已确认该境外网页无法访问)。对于国内用户,有以下替代方案:

  • 使用已配置好的测试密钥:直接使用上表中“社区可用测试密钥”或“DVWA 官方测试密钥”进行漏洞学习,无需自行注册。密钥对任意域名均返回验证成功,完全满足实验需求。
  • 通过 VPN 或代理访问:如有条件,可通过合规的 VPN 或代理工具访问谷歌服务进行注册。注意遵守当地法律法规及平台服务条款。
  • 使用国内验证码服务替代:在生产环境中,可考虑使用阿里云 CAPTCHA、极验验证等国内验证码服务,它们在国内有更稳定的访问速度和网络支持。
  • 绕过验证码进行学习:本漏洞的核心在于验证流程的逻辑缺陷。即使验证码不显示或密钥无效,你仍然可以跟随文档在 Burp Suite 中抓包、篡改 step 参数或 passed_captcha 标志,直接完成密码修改,完全不受密钥配置影响。
  • A2. 数据库默认连接凭据

    配置项

    默认值

    说明

    db_server

    localhost

    数据库服务器地址

    db_user

    root

    数据库用户名(如未修改)

    db_password

    p@ssw0rd(或空)

    默认安装后需根据实际环境修改

    db_database

    dvwa

    数据库名称

    配置位于 config/config.inc.php 文件的数据库相关部分。

    A3. Anti-CSRF Token

    Token 名称

    说明

    user_token

    前端表单中传递的 Token 参数名

    session_token

    服务端 Session 中存储的 Token 变量名

    checkToken()

    DVWA 内置的 Token 校验函数,生成方式为 bin2hex(random_bytes(32))

    Impossible 级别及各模块的 High/Impossible 级别中会使用 CSRF Token 进行防护。Token 在前端以隐藏表单字段的形式存在,每次页面加载时生成新的 Token,旧 Token 失效。攻击者必须从响应中提取新 Token 才能发起有效请求。

    A4. 其他模块默认凭据

    模块

    参数/凭据

    默认值/说明

    登录(所有模块)

    username / password

    admin / password

    SQL Injection 盲注

    id 参数

    使用经典注入 Payload

    File Inclusion

    page 参数

    路径遍历 Payload

    Command Injection

    ip 参数

    命令拼接 Payload

     安全警示重申:本文所有技术仅限用于授权的 DVWA 本地靶场及个人学习环境,严禁用于非法攻击。理解漏洞的目的是为了编写更安全的代码,保护用户数据与系统安全。

    赞(0)
    未经允许不得转载:171主机测评 » DVWA不安全验证码(Insecure CAPTCHA)漏洞实战教学指南(Low → Medium → High → Impossible 全级别)(源码分析+实操步骤+防御方案)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址