XSS 已有近二十年的历史了, 但它仍然是 web 上最常见的漏洞之一. 因此, 已经发展了许多机制来减轻漏洞的影响. 我经常会误以为这些机制可以作为针对 XSS 的保护. 今天, 我们将了解为什么情况并非如此. 我们将在代码重用攻击领域探索一种相对较新的技术. Web 的代码重用攻击于 2017 年 https://acmccs.github.io/papers/p1709-lekiesA.pdf 首次描述, 可用于绕过大多数现代浏览器保护, 包括: html sanitizers,WAF 和 CSP.
介绍
让我们使用示例进行演示:
- <?PHP
- /* File: index.PHP */
- // CSP disabled for now, will enable later
- // header("Content-Security-Policy: script-src'self''unsafe-eval'; object-src 'none';");
- ?>
- <!DOCTYPE HTML>
- <HTML lang="en">
- <body>
- <div id="app">
- </div>
- <script src="http://127.0.0.1:8000/main.js">
- </script>
- </body>
- </HTML>
- /** FILE: main.JS **/
- var ref=document.location.href.split("?injectme=")[1];
- document.getElementById("app").innerHTML = decodeURIComponent(ref);
该程序具有基于 DOM 的 XSS 漏洞. Main.JS 获取 GET 参数 injectme 的值, 并将其作为原始 HTML 插入到 DOM 中. 这是一个问题, 因为用户可以控制参数的值. 因此, 用户可以随意操作 DOM. 下面的请求是一个 poc, 证明我们可以注入任意 JavaScript.
http://127.0.0.1:8000/?injectme=<img src="n/a" onerror="alert('XSS')"/>
image 元素将插入到 DOM 中, 并且在加载期间会出错, 从而触发 onerror 事件处理程序. 这会弹出一个警告消息, 提示 "XSS", 证明我们可以使该应用运行任意 JavaScript.
现在, 通过删除 index.PHP 中第 5 行的注释来启用内容安全策略. 然后重新加载页面, 您将看到攻击失败. 如果在浏览器中打开开发者控制台, 则会看到一条说明原因的消息.
凉! 所以发生了什么事? IMG HTML 元素已创建, 浏览器看到了 onerror 事件属性, 但由于 CSP 而拒绝执行 JavaScript.
用一个不切实际的简单小工具绕过 CSP
在我们的示例中, CSP 限制 - 允许来自同一主机的 JavaScript - 阻止危险的功能, 例如 eval(不安全的 eval)- 阻止了所有其他脚本 - 阻止了所有对象 (例如 flash)
但是, 如果我们能以某种方式触发 CSP 白名单中已经存在的 JavaScript 代码怎么办? 如果是这样, 我们也许可以执行任意 JavaScript 而不会违反该政策. 让我们看一个小工具的简单示例, 以了解基本概念.
假设 main.JS 文件看起来像这样:
- /** FILE: main.JS **/
- var ref = document.location.href.split("?injectme=")[1];
- document.getElementById("app").innerHTML = decodeURIComponent(ref);
- document.addEventListener("DOMContentLoaded", function() {
- var expression = document.getElementById("expression").getAttribute("data");
- var parsed = eval(expression);
- document.getElementById("result").innerHTML = '<p>'+parsed+'</p>';
- });
代码基本相同, 但是这次我们的目标也有某种数学计算器. 请注意, 仅 main.JS 被更改, index.PHP 与以前相同. 您可以将数学函数视为一些未真正使用的旧代码.
作为攻击者, 我们可以滥用数学计算器代码来评估并执行 JavaScript, 而不会违反 CSP. 我们不需要注入 JavaScript. 我们只需要注入一个 ID 为 "expression" 和一个名为 "data" 的属性的 HTML 元素. 内部数据将传递给 eval.
我们试一试, 是的! 我们绕过了 CSP!
转向现实的脚本小工具
如今的网站包含许多第三方资源, 而且情况越来越糟. 这些都是合法的列入白名单的资源, 即使强制执行了 CSP. 数百万行的 JavaScript 中也许有有趣的小工具? 嗯, 是! Lekies 等.(2017) 分析了 16 个广泛使用的 JavaScript 库, 发现几乎所有库中都有多个小工具.
小工具有几种类型, 它们可以直接有用, 或者需要与其他小工具链接才能有用.
字符串操作小工具: 用于绕过基于模式的缓解措施很有用. 元素构造小工具:
有助于绕过 XSS 缓解措施, 例如创建脚本元素. 函数创建小工具: 可以创建新的函数对象, 以后可以由第二个小工具执行. JavaScript 执行接收器小工具: 类似于我们刚才看到的示例, 可以独立运行, 也可以作为链中的最后一步
让我们看另一个例子. 我们将使用相同的应用程序, 但现在让我们包括 jQuery mobile.
- <?PHP
- /** FILE: index.PHP **/
- header("Content-Security-Policy: script-src'self'https://code.jquery.com:443'unsafe-eval'; object-src'none';");
- ?>
- <!DOCTYPE HTML>
- <HTML lang="en">
- <body>
- <p id="app">
- </p>
- <script src="http://127.0.0.1:8000/main.js">
- </script>
- <script src="https://code.jquery.com/jquery-1.8.3.min.js">
- </script>
- <script src="https://code.jquery.com/mobile/1.2.1/jquery.mobile-1.2.1.min.js">
- </script>
- </body>
- </HTML>
- /** FILE: main.JS **/
- var ref = document.location.href.split("?injectme=")[1];
- document.getElementById("app").innerHTML = decodeURIComponent(ref);
CSP 进行了少许更改, 以允许来自 code.jQuery.com 的任何内容, 幸运的是, jQuery Mobile 有一个已知的脚本小工具可供我们使用. 该小工具还可以严格动态地绕过 CSP.
让我们首先考虑以下 HTML
<div data-role=popup id='hello world'></div>
此 HTML 将触发 jQuery Mobile 的 Popup Widget 中的 https://api.jquerymobile.com/popup/ 代码. 可能不明显的是, 当您创建弹出窗口时, 库会将 id 属性写入 HTML 注释中.
jQuery 中负责此工作的代码如下所示:
这是一个代码小工具, 我们可以滥用它来运行 JavaScript. 我们只需要绕过注释, 然后我们就可以做我们想做的任何事情.
我们最终的 payload 将如下所示:
<div data-role=popup id='--!><script>alert("XSS")</script>'></div>
执行, 弹框!
来源: http://www.tuicool.com/articles/aAfuyuJ