DVWA靶场通关笔记-Insecure CAPTCHA (Impossible级别)

目录

一、reCAPTCHA

1、配置security为Impossible级别。

2、配置RECAPTCHA参数

3、再次打开靶场

二、源码分析

1、index.php

2、impossible.php

3、功能函数

[三、reCAPTCHA 防范分析](#三、reCAPTCHA 防范分析)

1、严格的参数验证与处理

2、预处理防止SQL注入

[3、CAPTCHA 验证通过](#3、CAPTCHA 验证通过)

4、验证当前密码


本系列为通过《DVWA靶场通关笔记》的Insecure CAPTCHA关卡(low,medium,high,impossible共4关)渗透集合,通过对相应关卡源码的代码审计找到讲解渗透原理并进行渗透实践。本文为Insecure CAPTCHA impossible关卡的原理分析部分,讲解相对于low、medium和high级别,为何对其进行渗透测试是Impossible的。

一、reCAPTCHA

reCAPTCHA关卡模拟了网站验证码系统的实现,在通过绕过验证码的安全验证来实现密码修改等操作,不同安全等级存在不同的安全风险和绕过方法。

1、配置security为Impossible级别。

进入到reCAPTCHA关卡High页面,完整URL地址具体如下所示。

复制代码
http://127.0.0.1/DVWA/vulnerabilities/captcha/

如果出现下图红框的报错信息,那么需要配置captcha参数。

2、配置RECAPTCHA参数

进入到DVWA的config目录,如下所示找到config.inc.php文件。

修改config.inc.php文件中如下内容,虽然在RECAPTCHA关卡的页面提示api-key需要通过https://www.google.com/recaptcha/admin/create生成,但是实际上这部分可以填充为自己的内容,如下所示。

复制代码
$_DVWA[ 'recaptcha_public_key' ]  = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMOOYUAN';
$_DVWA[ 'recaptcha_private_key' ] = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMOOYUAN';

修改后效果如下所示,记得修改后保存文件。

3、再次打开靶场

如下所示,更新config.inc.php文件后,靶场可以正常打开,这是一个具有修改密码功能的页面。

二、源码分析

1、index.php

进入DVWA靶场Insecure CAPTCHA源目录,找到index.php源码。

这段代码实现了`` DVWA (Damn Vulnerable Web Application) ``中的Insecure CAPTCHA关卡的演示页面,主要功能包括:DVWA的Insecure CAPTCHA模块通过四个安全等级(低、中、高、不可能)演示验证码系统的安全演进,该模块核心展示密码修改场景下的验证码实现,包含密钥检查、表单动态生成(根据等级显示不同字段)和安全警告提示,如客户端验证绕过、验证码重复使用等问题,并通过对比不同等级的实现差异,直观呈现从脆弱到安全的演进过程,最终强调应使用专业验证服务配合多因素验证的整体防护思路。

  • 初始化与安全级别处理
    • 设置页面路径和安全依赖。
    • 根据用户安全级别(低、中、高、不可能)加载不同的验证码实现。
  • 验证码配置检查
    • 验证是否配置了 reCAPTCHA API 密钥。
    • 若未配置则显示警告并隐藏表单。
  • 表单构建
    • 生成密码修改表单,包含当前密码(仅 "不可能" 级别)、新密码和确认密码字段。
    • 根据安全级别不同,集成不同的验证码机制(低级、中级、高级和不可能四个级别)。
  • 安全措施
    • "高" 和 "不可能" 级别包含 CSRF 令牌保护。
    • "不可能" 级别增加了当前密码验证。

经过注释后的详细代码如下所示。

复制代码
<?php
/**
 * DVWA Insecure CAPTCHA 演示页面
 * 演示不同安全等级下的验证码实现方式及潜在安全风险
 */

// 定义网站根目录路径
define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );

// 引入必要的库文件
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';          // DVWA核心页面库
require_once DVWA_WEB_PAGE_TO_ROOT . "external/recaptcha/recaptchalib.php";    // reCAPTCHA库

// 初始化页面,要求认证并启用PHPIDS防护
dvwaPageStartup( array( 'authenticated', 'phpids' ) );

// 创建新页面对象
$page = dvwaPageNewGrab();
// 设置页面标题
$page[ 'title' ]   = 'Vulnerability: Insecure CAPTCHA' . $page[ 'title_separator' ].$page[ 'title' ];
// 设置页面ID
$page[ 'page_id' ] = 'captcha';
// 设置帮助按钮
$page[ 'help_button' ]   = 'captcha';
// 设置源代码查看按钮
$page[ 'source_button' ] = 'captcha';

// 连接数据库
dvwaDatabaseConnect();

// 根据安全等级选择对应的实现文件
$vulnerabilityFile = '';
switch( $_COOKIE[ 'security' ] ) {
    case 'low':      // 低安全等级
        $vulnerabilityFile = 'low.php';
        break;
    case 'medium':   // 中安全等级
        $vulnerabilityFile = 'medium.php';
        break;
    case 'high':     // 高安全等级
        $vulnerabilityFile = 'high.php';
        break;
    default:        // 默认(不可能等级)
        $vulnerabilityFile = 'impossible.php';
        break;
}

// 控制表单是否显示
$hide_form = false;
// 引入对应级别的实现文件
require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/captcha/source/{$vulnerabilityFile}";

// 检查reCAPTCHA密钥配置
$WarningHtml = '';
if( $_DVWA[ 'recaptcha_public_key' ] == "" ) {
    $WarningHtml = "<div class=\"warning\"><em>reCAPTCHA API key missing</em> from config file: " . 
                  realpath( getcwd() . DIRECTORY_SEPARATOR . DVWA_WEB_PAGE_TO_ROOT . "config" . DIRECTORY_SEPARATOR . "config.inc.php" ) . "</div>";
    $html = "<em>Please register for a key</em> from reCAPTCHA: " . dvwaExternalLinkUrlGet( 'https://www.google.com/recaptcha/admin/create' );
    $hide_form = true;  // 密钥缺失时隐藏表单
}

// 构建页面主体HTML
$page[ 'body' ] .= "
<div class=\"body_padded\">
    <h1>Vulnerability: Insecure CAPTCHA</h1>

    {$WarningHtml}

    <div class=\"vulnerable_code_area\">
        <form action=\"#\" method=\"POST\" ";

// 密钥缺失时隐藏表单
if( $hide_form )
    $page[ 'body' ] .= "style=\"display:none;\"";

$page[ 'body' ] .= ">
            <h3>Change your password:</h3>
            <br />

            <input type=\"hidden\" name=\"step\" value=\"1\" />\n";

// 不可能等级需要验证当前密码
if( $vulnerabilityFile == 'impossible.php' ) {
    $page[ 'body' ] .= "
            Current password:<br />
            <input type=\"password\" AUTOCOMPLETE=\"off\" name=\"password_current\"><br />";
}

$page[ 'body' ] .= "            New password:<br />
            <input type=\"password\" AUTOCOMPLETE=\"off\" name=\"password_new\"><br />
            Confirm new password:<br />
            <input type=\"password\" AUTOCOMPLETE=\"off\" name=\"password_conf\"><br />

            " . recaptcha_get_html( $_DVWA[ 'recaptcha_public_key' ] );  // 插入reCAPTCHA组件

// 高安全等级下的开发者注释提示
if( $vulnerabilityFile == 'high.php' )
    $page[ 'body' ] .= "\n\n            <!-- **DEV NOTE**   Response: 'hidd3n_valu3'   &&   User-Agent: 'reCAPTCHA'   **/DEV NOTE** -->\n";

// 高和不可能等级添加CSRF令牌
if( $vulnerabilityFile == 'high.php' || $vulnerabilityFile == 'impossible.php' )
    $page[ 'body' ] .= "\n            " . tokenField();

$page[ 'body' ] .= "
            <br />

            <input type=\"submit\" value=\"Change\" name=\"Change\">
        </form>
        {$html}  <!-- 显示操作结果 -->
    </div>

    <h2>More Information</h2>
    <ul>
        <li>" . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA' ) . "</li>
        <li>" . dvwaExternalLinkUrlGet( 'https://www.google.com/recaptcha/' ) . "</li>
        <li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/Testing_for_Captcha_(OWASP-AT-012)' ) . "</li>
    </ul>
</div>\n";

// 输出完整HTML页面
dvwaHtmlEcho( $page );

?>

2、impossible.php

进入DVWA靶场reCAPTCHA 的source源码目录,找到impossible.php源码,分析其为何能让这一关卡名为不可能实现验证码渗透。

打开impossible.php文件,对其进行代码审计,impossible.php实现带严格安全验证的密码修改功能。接收请求后先验证 Anti-CSRF token,处理输入密码(去反斜杠、转义、MD5 哈希),默认通过 CAPTCHA 验证。用 PDO 预处理语句校验当前密码,仅当新密码与确认密码一致且当前密码正确时,通过预处理语句更新密码,最后生成新 token,多重验证保障安全。

  • 安全验证
    • 验证 CSRF 令牌防止跨站请求伪造
    • 验证 Google reCAPTCHA 验证码防止机器人攻击
  • 密码处理
    • 获取并处理当前密码和新密码输入
    • 使用 MD5 哈希所有密码(存在安全风险)
  • 密码验证
    • 检查当前密码是否与数据库中存储的一致
    • 验证两次输入的新密码是否匹配
  • 数据库更新
    • 如果验证通过,更新用户密码
    • 提供相应的成功或失败反馈

详细注释后的impossible.php源码如下所示,主要实现严格白名单控制的文件包含功能。

复制代码
<?php

if( isset( $_POST[ 'Change' ] ) ) {
    // 验证CSRF令牌,防止跨站请求伪造攻击
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // 验证通过后隐藏验证码表单
    $hide_form = true;

    // 获取新密码输入
    // 注意:使用stripslashes和mysqli_real_escape_string处理输入
    // 这种方式在现代PHP中已不推荐,应直接使用预处理语句
    $pass_new  = $_POST[ 'password_new' ];
    $pass_new  = stripslashes( $pass_new );
    $pass_new  = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass_new  = md5( $pass_new ); // 使用MD5哈希密码(严重安全风险)

    // 获取确认密码输入,处理方式同上
    $pass_conf = $_POST[ 'password_conf' ];
    $pass_conf = stripslashes( $pass_conf );
    $pass_conf = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_conf ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass_conf = md5( $pass_conf );

    // 获取当前密码输入,处理方式同上
    $pass_curr = $_POST[ 'password_current' ];
    $pass_curr = stripslashes( $pass_curr );
    $pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
    $pass_curr = md5( $pass_curr );

    // 验证Google reCAPTCHA验证码
    $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 {
        // 查询数据库验证当前密码
        $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
        $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
        $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
        $data->execute();

        // 验证新密码是否匹配且当前密码正确
        if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) {
            // 更新数据库中的密码
            $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
            $data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
            $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
            $data->execute();

            // 成功反馈
            $html .= "<pre>Password Changed.</pre>";
        }
        else {
            // 失败反馈
            $html .= "<pre>Either your current password is incorrect or the new passwords did not match.<br />Please try again.</pre>";
            $hide_form = false;
        }
    }
}

// 生成新的CSRF令牌
generateSessionToken();

?>

impossible.php 主要实现带严格安全验证的密码修改功能,流程如下:

  • 接收用户提交的密码修改请求,先通过 checkToken() 验证 Anti-CSRF token,确保请求合法性,防止跨站请求伪造。

  • 处理用户输入的当前密码、新密码和确认密码:使用 stripslashes() 去除反斜杠,通过 mysqli_real_escape_string() 进行数据库转义,再用 md5 哈希处理,避免明文存储和 SQL 注入风险。

  • 进行 CAPTCHA 验证(代码中默认设为通过),若验证失败则提示错误并重新显示表单。

  • 验证当前密码正确性:通过 PDO 预处理语句查询数据库,绑定用户名和哈希后的当前密码参数,避免 SQL 注入。

  • 仅当新密码与确认密码一致且当前密码验证通过时,才执行密码更新操作,同样使用预处理语句更新数据库中的密码。

  • 操作完成后生成新的 Anti-CSRF token,为下次请求做准备。整体通过多重验证机制保障密码修改过程的安全性。impossible.php 主要实现带严格安全验证的密码修改功能,流程如下:

  • 接收用户提交的密码修改请求,先通过 checkToken() 验证 Anti-CSRF token,确保请求合法性,防止跨站请求伪造。

3、功能函数

根据如下代码可知,CheckCaptcha函数会像谷歌https://www.google.com/recaptcha/api/siteverify进行请求,CheckCaptcha和recaptcha_get_html函数的定义如下所示。

复制代码
<?php

/**
 * 验证码验证函数(兼容旧版API)
 * 
 * @param string $key 私钥
 * @param string $response 用户提交的验证码响应
 * @return bool|NULL 验证成功返回true,失败返回false,异常返回NULL
 */
function recaptcha_check_answer($key, $response){
    return CheckCaptcha($key, $response);
}

/**
 * 发送HTTP请求验证验证码
 * 
 * @param string $key 私钥
 * @param string $response 用户提交的验证码响应
 * @return bool|NULL 验证成功返回true,失败返回false,异常返回NULL
 */
function CheckCaptcha($key, $response) {

    try {
        // Google reCAPTCHA验证API地址
        $url = 'https://www.google.com/recaptcha/api/siteverify';
        
        // 准备POST数据
        $dat = array(
            'secret'   => $key,                 // 网站私钥
            'response' => urlencode($response), // 用户响应(由前端生成)
            'remoteip' => urlencode($_SERVER['REMOTE_ADDR']) // 用户IP地址
        );

        // 配置HTTP请求选项
        $opt = array(
            'http' => array(
                'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
                'method'  => 'POST',
                'content' => http_build_query($dat) // 生成POST数据
            )
        );

        // 创建HTTP上下文并发送请求
        $context = stream_context_create($opt);
        $result  = file_get_contents($url, false, $context);

        // 解析JSON响应并返回验证结果
        return json_decode($result)->success;

    } catch (Exception $e) {
        // 发生异常时返回NULL
        return null;
    }
}

/**
 * 生成前端验证码HTML代码
 * 
 * @param string $pubKey 公钥
 * @return string HTML代码片段
 */
function recaptcha_get_html($pubKey){
    return "
        <script src='https://www.google.com/recaptcha/api.js'></script>
        <br /> <div class='g-recaptcha' data-theme='dark' data-sitekey='" . $pubKey . "'></div>
    ";
}

?>

三个函数功能详解,如下所示。

  • recaptcha_check_answer
    • 功能:验证用户提交的验证码是否有效(兼容旧版 API)。
    • 流程 :直接调用CheckCaptcha函数进行验证。
    • 安全作用:作为入口函数提供向后兼容性。
  • CheckCaptcha
    • 功能:向 Google 服务器发送验证请求并处理响应。
    • 流程
      • 构建 POST 请求参数(私钥、用户响应、IP 地址)。
      • 配置 HTTP 请求上下文(设置请求头、方法和内容)。
      • 发送请求到 Google 验证 API。
      • 解析 JSON 响应并提取验证结果。
    • 安全作用:核心验证逻辑,防止 CSRF 攻击和机器人自动化操作。
  • recaptcha_get_html
    • 功能:生成前端验证码 UI 组件。
    • 流程

引入 Google reCAPTCHA JavaScript 库。

  • 创建带有公钥的验证码容器(暗色主题)。
  • 安全作用:在页面中正确渲染验证码组件,确保用户交互。

三、reCAPTCHA 防范分析

DVWA的Impossible级别通过采用深度防御策略 ,构建了一个多层次、互补的安全体系。它从认证、授权、输入处理、会话安全等多个角度出发,确保了密码修改功能在整个生命周期内的安全性。

安全措施 Low/Medium/High 级别 Impossible 级别 防护方法
SQL注入防护 无或弱(转义) 强(参数化查询) SQL注入
密码哈希 弱(MD5) 强(应使用bcrypt) 密码破解、彩虹表
当前密码验证 错误(在SQL中验证) 正确(先查询,后在代码中验证) 权限绕过
CSRF防护 有(Anti-CSRF Token) 跨站请求伪造
自动化防护 有(reCAPTCHA) 暴力破解、自动化攻击

impossible.php代码将密码修改作为一个完整流程进行校验,同时满足以下条件才允许修改:

  • CAPTCHA 验证通过
  • 新密码与确认密码一致
  • 当前密码验证正确

1、严格的参数验证与处理

对所有用户输入的密码(当前密码、新密码、确认密码)进行了严格处理:

  • 使用 stripslashes() 去除反斜杠,避免反斜杠注入

  • 通过 mysqli_real_escape_string() 进行数据库转义,防止 SQL 注入

  • 对密码进行 md5 哈希处理后再存入数据库,避免明文存储

    // 密码处理示例
    pass_new = stripslashes( pass_new );
    pass_new = mysqli_real_escape_string(GLOBALS["___mysqli_ston"], pass_new ); pass_new = md5( $pass_new );

2、预处理防止SQL注入

数据库操作采用 PDO 预处理语句和参数绑定,彻底避免 SQL 注入安全风险:

复制代码
// 预处理更新语句
$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->execute();

3、CAPTCHA 验证通过

通过 checkToken() 函数验证 Anti-CSRF token,确保请求来自合法的表单提交,防止跨站请求伪造:

复制代码
// 验证 CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// 生成新的 token
generateSessionToken();

**4、**验证当前密码

要求用户输入当前密码并验证正确性,只有当前密码正确时才能修改密码,防止未授权用户修改密码:

复制代码
// 验证当前密码
$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();
// 检查查询结果是否存在(当前密码正确)
if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) { ... }
相关推荐
mooyuan天天10 小时前
DVWA靶场通关笔记-DOM型XSS(Impossible级别)
xss·dom型xss·xss漏洞·dvwa靶场
mooyuan天天10 小时前
DVWA靶场通关笔记-反射型XSS(Impossible级别)
xss·反射型xss·xss漏洞·dvwa靶场
mooyuan天天1 天前
DVWA靶场通关笔记-Weak Session IDs (Impossible级别)
dvwa·弱会话·dvwa靶场
qq_3325394522 天前
Python自动化测试实战:reCAPTCHA V3绕过技术深度解析
自动化测试·python·web安全·验证码破解·recaptcha
mooyuan天天2 个月前
DVWA靶场通关笔记-存储型XSS(Stored Medium级别)
xss·xss漏洞·存储型xss·dvwa靶场
mooyuan天天2 个月前
DVWA靶场通关笔记-XSS DOM(Medium级别)
xss·dom型xss·xss漏洞·dvwa靶场
mooyuan天天2 个月前
DVWA靶场通关笔记-弱会话IDs(Weak Session IDs High级别)
web安全·dvwa靶场·弱会话id