内容简介:这一系列的博客文章将向你展示如何在单页或富JavaScript的应用程序上识别DOM XSS的问题。作为示例,我们将在DOM XSS playground(这篇文章的内容涵盖了前两个练习的设置说明和解决方案。剩余的练习将在我们发布的其他文章中提到。我们还将发布一个gitbook,其中包含了Appsecco书籍门户网站上所有练习的解决方案。更新:gitbook会挂在我们的图书门户网站上——
这一系列的博客文章将向你展示如何在单页或富JavaScript的应用程序上识别DOM XSS的问题。作为示例,我们将在DOM XSS playground( https://domgo.at )上解决10个练习题目,并为检测到的问题创建了简单的概念证明漏洞。
这篇文章的内容涵盖了前两个练习的设置说明和解决方案。剩余的练习将在我们发布的其他文章中提到。我们还将发布一个gitbook,其中包含了Appsecco书籍门户网站上所有练习的解决方案。
更新:gitbook会挂在我们的图书门户网站上—— https://appsecco.com/books/automating-discovery-and-exploiting-dom-client-xss/
什么是DOM XSS / Client XSS?
纵观Cross Site Scripting漏洞的历史,在测试人员和开发人员的心中都占有特殊的地位。使用标准检的测技术很难检测到这种XSS的变体,并且相对的来说,这种漏洞的变体很容易出现在大型的JS应用程序中。
OWASP 将其定义为XSS的漏洞类型,其中的原因是由于这种漏洞是在受害者浏览器中通过原始客户端脚本修改DOM环境而执行攻击有效载荷,因此客户端代码以一种 “意外” 的方式运行。也就是说,页面本身(即HTTP响应)不会改变,但由于DOM环境中发生了恶意的修改,页面中包含的客户端代码执行方式发生了改变。
简而言之,当来自DOM源(如location.hash)的用户输入发现它赋值到了DOM接收器(如HTMLElement.innerHTML)时,就会发生客户端XSS漏洞。 DOM中有多个源,也可以有多个接收器,具体取决于JS的复杂程度和其所实现的功能。
通过手动的方式或代码审查来检测DOM XSS可能会花费大量的时间。一种可行的技术是通过一个 工具 从服务器发送流量,该工具可以注入自己的JS来监控DOM变化,只需浏览网站即可枚举所有源和接收器。
进入Sboxr
Sboxr 是一个测试和调试Web应用程序的工具,尤其是大型的JavaScript应用程序。 Sboxr通过在浏览器和服务器之间的流量中注入它自己的JS代码(称为DOM传感器)来工作,该代码在使用站点时监视JS的使用情况,源,接收器,变量分配,函数调用等。然后,它通过其Web控制台显示用户控制的数据在数据最终出现在执行接收器中时所采用的各种流的视图。
设置Sboxr和Chrome
我们使用Ubuntu 18.04来设置我们的攻击工具链以及Chrome 72。以下步骤将帮助你进行设置:
1、从供应商网站获取Sboxr的许可副本 – https://sboxr.com/
2、运行Sboxr需要.NET 核心 SDK,可以按照这里的( https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current )说明在 Linux 上进行安装。对于Windows系统,请按照这个( https://dotnet.microsoft.com/download )说明进行操作即可。
3、安装完成后,通过运行dotnet Sboxr.dll启动Sboxr
4、程序启动后会在端口3333 http://localhost:3333/console 上访问到Sboxr Web界面(用于管理和分析发现的问题),端口3331是一个代理端口。
5、如果你希望链接Burp或其他拦截代理,请浏览并单击HTTP Sensor以设置上游代理(例如Burp或OWASP ZAP)的IP地址和端口。
设置完成后,我们需要配置浏览器向Sboxr发送流量(然后可以转发到Burp或OWASP ZAP)。
Sboxr目前还不支持SOCKS代理,因此你需要使用Burp或OWASP ZAP进行链接以阻止流量。
ED_:D_=>HTTPS站点可能无法与Sboxr一起正常工作,因为我们没有应该要导入的证书。因此,我们使用–ignore-certificate-errors参数启动Chrome(我们注意到Firefox的about:config中的禁用HSTS检查的network.stricttransportsecurity.preloadlist选项有一些问题,因此我们暂时会一直使用Chrome)。
在Linux上,使用以下命令启动Chrome:
mkdir -p ~/.chrome;/opt/google/chrome/chrome -incognito --ignore-certificate-errors --proxy-server=http=http://localhost:3331\;https=http://localhost:3331 --user-data-dir=~/.chrome
在Windows系统上,可以执行以下操作(假设你的安装路径也是标准的安装路径)
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -incognito --ignore-certificate-errors --proxy-server=http=http://localhost:3331;https=http://localhost:3331 --user-data-dir="C:\Users\%Username%\AppData\Local\Temp\TestChromeProxy" \Program Files(x86)\Google \Chrome \Application \chrome.exe”-incognito --ignore-certificate-errors --proxy-server = http = http:// localhost:3331; https = http://localhost:3331 --user-data-dir =“C:\Users \%Username%\AppData \Local \Temp \TestChromeProxy”
检测并利用DOM XSS
在本文的这一部分,我们将使用Sboxr的创建者设置的客户端XSS playground来练习我们对客户端XSS漏洞的检测和利用技能。
概念验证漏洞Demo。这些漏洞可用于在提交错误报告时创建你自己的PoC,因为它们允许读者查看正在执行的用户控制的数据。
练习1
1、浏览到 https://domgo.at/ 并单击左侧窗格中的练习1,就可以使用命令行选项启动Chrome中的第一个练习。
2、切换到Sboxr控制台并单击Sboxr侧栏中的代码执行
3、从HTML上下文可以看出,数据源是location.hashproperty,导致执行的接收器是HTMLElement.innerHTML
4、点击“代码执行”图标将打开代码执行详细信息的窗口。
5、通过单击View事件位置详细信息的那个狙击图标,我们可以清楚地看到JS中我们的数据在哪里被接收器HTMLElement.innerHTML使用。
6、为了显示location.hash属性是可利用的,我们通过源传递JS并让它到达接收器以查看它是否已执行。
7、题目的解决方案是通过location.hash属性传递<svg onload=alert(document.domain)>。最终的漏洞利用PoC是 – https://domgo.at/cxss/example/1?payload=abcd&sp=x# <svg%20onload= alert(document.domain)>
练习2
1、单击侧栏上的练习1来加载练习题目1
2、单击侧栏上的练习 – 2以加载第二个练习题目。必须通过点击操作进入题目,而不是直接浏览到题目的URL,因为本练习中的源是document.referrer属性。
3、我们按照与上一个练习相同的步骤开始,然后单击Sboxr侧栏中的“代码执行”
4、我们从易受攻击的代码中看到,如果referrer的URL中有一个名为payload的参数,则将其提取并传递给接收器。
5、我们可以使用以下简单的HTML页面构建我们的漏洞。将其另存为exercise2.html并在本地托管(nginx/Apache/python/node/anything),然后通过http://127.0.0.1/exercise2.html?payload=<svg%20onload=alert(document.domain)>进行访问。
<html> <body> <h2>PoC for Exercise 2 of https://domgo.at</h2> <script> window.location="https://domgo.at/cxss/example/2" </script> </body> </html>
6、该页面将加载并立即重定向到练习页面,因为referrer属性是用户控制的代码执行是可能的。
接下来我们来说说其他4个练习的解决方案。剩余的练习将在我们将发布的其他文章中提到。
练习3
在许多Web应用程序中,来自外部的第三方应用程序的数据可以使用接收器,并将其作为目标应用程序的一部分,而无需清理收到的响应。在这种情况下,第三方应用程序的XHR端点可以将恶意代码注入到目标应用程序中。即使在XHR响应来自同一站点的情况下,你也需要验证数据在服务器上的结果。在现代应用程序中,应用程序从不同的源收集不受信任的数据并将它们存储在服务器端数据库中,最终这些不受信任的数据会进入目标应用程序,从而导致持久性的DOM XSS。
此练习涉及对JSON端点的XHR请求,该请求会将数据反射到客户端。然后将反射的数据添加到接收器HTMLElement.innerHTML,从而执行任意代码。
1、在“练习”页面的文本框中输入随机字符串,然后单击“执行有效载荷”的按钮。
2、数据将由JSON端点反射到 https://domgo.at/data.json?payload=thanos
3、在代码执行窗口下使用Sboxr查看从源到接收器的数据流
4、我们可以准确地看到来自JSON响应的内容在接收器中使用并创建了一个漏洞。
5、要利用漏洞,请在文本框中传递字符串<img src=1 onerror=alert(document.domain)>
练习4
与XHR响应类似,受信任的websocket数据是良性的,无论它来自何处都可能导致DOM XSS问题。
此练习涉及对安全websocket端点的websocket请求,该请求将数据反射到客户端。然后将反射的数据添加到接收器HTMLElement.innerHTML,从而执行任意代码。
1、在“练习”页面的文本框中输入随机字符串,然后单击“执行有效载荷”的按钮。
2、数据由wss://domgo.at/ws上的Websocket端点反射出来
3、在代码执行窗口下使用Sboxr查看从源到接收器的数据流
4、我们可以准确地看到响应在接收器中使用的内容并创建了一个漏洞。
5、要利用漏洞,请在文本框中传递字符串<img src=1 onerror=alert(document.domain)>
练习5
XHR,fetch API,websockets或postMessage等通信信道经常被忽视,但最终可能会成为DOM XSS漏洞的源。特别是,如果数据来自不同的源。在响应中信任数据并通过接收器呈现/评估它可能导致DOM XSS问题,作为分析师,你必须留意这些源。
本练习涉及一个postMessage,它将用户控制的有效载荷发送到window.onmessage事件处理程序,并将数据下沉到HTMLElement.innerHTML,执行任意代码。
1、在“练习”页面的文本框中输入随机字符串,然后单击“执行有效载荷”的按钮。
2、在这种情况下,数据源是来自https://domgo.at(同源)的窗口消息。
3、在代码执行窗口下使用Sboxr查看从源到接收器的数据流
4、我们可以准确地看到响应在接收器中使用的内容并创建了一个漏洞。
5、要利用漏洞,请在文本框中传递字符串<img src=1 onerror=alert(document.domain)>
练习6
另一个有趣的不受信任的数据来源是浏览器的存储源,包括localStorage,sessionStorage和IndexedDB。虽然攻击者无法直接控制DOM存储(除非应用程序中已存在XSS),但攻击者可能能够通过其他HTML元素或JS源将恶意数据引入存储源。此数据最终可能会从存储源的接收器中生成,并导致DOM XSS。
一个很好的例子就是Twitter子域上的DOM XSS – https://hackerone.com/reports/297968
在本练习中,数据源是HTML LocalStorage。页面中的JS从localStorage读取数据并将其传送到HTMLElement.innerHTML,从而执行任意代码。
1、在“练习”页面的文本框中输入随机字符串,然后单击“执行有效载荷”的按钮。
2、在这种情况下,数据源是HTML localStorage。
3、在代码窗口下使用Sboxr查看从源到接收器的数据流
4、我们可以准确地看到响应在接收器中使用的内容并创建了一个漏洞。
5. 要利用漏洞,请在文本框中传递字符串<img src=1 onerror=alert(document.domain)>
练习7
在本练习中,数据源是location.hash。但是,数据在添加到接收器HTMLElement.innerHTML之前进行处理。
1、单击练习7并注意URL中的哈希值。
2、在代码执行窗口下使用Sboxr查看从源到接收器的数据流
3、我们可以确切地看到location.hash数据是如何北处理的,并从那里构建了一个漏洞。
4、从location.hash获取值,并将HTML标记替换为其HTML实体等价物(<替换为&lt; 以及> 替换为&gt;)。然后将数据附加到<a href ='#user =并创建锚了标签。
5、最后,数据被发送到接收器以写入页面,实际上是使用了我们的(假定的)构造的数据创建了锚标签。
6、这是数据反射的HTML属性值上下文的一个很好的例子。你可以
7、要利用这个漏洞,我们需要注入HTML属性值的上下文并关闭悬空的单引号。可以使用对锚标签有效的HTML事件(例如onmouseover或onclick等)触发JS。
8、利用漏洞的URL 是 https://domgo.at/cxss/example/7#abcd'%20onmouseover=alert(document.domain)%20a='
练习8
这个练习与练习7完全相同,唯一的区别是JS期望location.hash包含一个名称值的字符串键值对(任何包含=字符的字符串)。
1、如果我们通过Sboxr查看JS,我们注意到通过location.hash传递的字符串在第一个=处被拆分,而字符串的其余部分用于构造转到接收器的数据(锚标签,如上一个练习)
2、在这种情况下的漏洞利用URL是 https://domgo.at/cxss/example/8#anyrandomstring=hawkeye'%20onmouseover=alert(document.domain)%20a='
练习9
本练习使用两个源location.hash和window.name处理来自这些源的数据,然后将其发送到HTMLElement.innerHTML 接收器。
1、单击练习9并注意包含哈希值user=12345的URL
2、在这种情况下有两个来源。最终发送到接收器HTMLElement.innerHTML的数据是从两个源获得的。
3、查看代码执行细节,很明显,来自location.hash的数据在=符号处被分割,然后只选择前10个字符并将其附加到window.name中的数据。此外,在被附加到window.name中的数据之前,通过使用等效的HTML实体来清理出现的双引号。
4. 为此写一个漏洞EXP就意味着
·通过location.hash传递10个字符但不能出现双引号(我们显然不能使用元素属性注入,因为我们无法突破href属性)
· 通过window.name传递JS的其余部分,并让易受攻击的JS将它们都附加到一起,最后就产生出我们想要的漏洞EXP
· 我们不能突破href属性,因为我们已经在href中,我们可以使用javascript:protocol handler来点击锚标签来触发我们的代码
· 本质上,我们是利用了javascript:alert(document.domain)作为我们的PoC。
5. 创建包含以下代码的HTML页面,将其托管在本地服务器上并在浏览器中打开它。
<html> <body onload=exploit()> <h2>PoC for Exercise 9 of https://domgo.at</h2> <script> function exploit() { var win = window.open("https://domgo.at/cxss/example/9#a=javascript", ":alert(document.domain)", ""); } </script> </body> </html>
6.大多数现代浏览器可能会使用内置的弹出窗口阻止程序启动阻止新窗口,但你必须允许这样做。如果你想摆脱弹出警告,你可以修改HTML PoC以触发用户驱动事件(如鼠标点击等)上的window.open。
<html> <body> <h2>PoC for Exercise 9 of https://domgo.at</h2> <label onclick="exploit()">Click me for solution to Exercise 9</label> <script> function exploit() { var win = window.open("https://domgo.at/cxss/example/9#a=javascript", ":alert(document.domain)", ""); } </script> </body> </html>
7. 一旦你启动新窗口后,单击Welcome消息就会执行我们的有效载荷。
练习10
这与练习9类似,但JavaScript除外,其中的代码路径是基于条件分支执行的。使用手动测试很容易遗漏这一点,因为仅当满足JS中的某些代码条件时,接收器才会填充我们的恶意数据。
在本练习中,我们通过两个来源location.href和window.name传入数据,在满足分支条件和一些简单的处理之后就可以将其传递到HTMLElement.innerHTML 接收器。
客户端JS中可能存在条件分支代码,这可能会使创建有效的漏洞EXP变得有点困难。此练习显示了如何检测条件分支并传递正确的字符串,以便可以访问接收器并执行攻击者的代码。
1、如果我们查看来自源的数据流,我们会看到来自location.href和window.name的数据被附加在一起。
2、可以使用window.open()使用我们的数据设置window.name中的数据。在本地服务器上托管以下内容并在浏览器中打开它。在浏览器提示时启用浏览器的弹出窗口。
<html> <body onload=exploit()> <h2>PoC for Exercise 10 of https://domgo.at</h2> <script> function exploit() { var win = window.open("https://domgo.at/cxss/example/10?lang=en&user=ID-12345&returnurl=/", ":alert(document.domain)", ""); } </script> </body> </html>
3、在代码执行详情窗口中,我们看到来自location.href属性的数据在ID-之后被拆分,剩下的字符串被处理为双引号并附加到了window.name的值里面。
4、我们可以查看源进行检查条件分支。在这个例子中不是很明显,因为我们在URL中的用户参数已经以ID-开头,但情况可能并非总是如此。单击目标符号会显示JS的源代码,如果用户参数以ID-开头,很明显会到达接收器。
5、根据我们现在的情况,我们的漏洞利用只需通过导航到https://domgo.at/cxss/example/10?lang=en&user=ID-javascript&returnurl=/,在同一个窗口中生成 HTML代码,然后单击welcome href锚标签即可成功利用漏洞。
结论
Sboxr是一个非常强大的工具,可以与其他Web应用程序攻击工具(如Burp和ZAP)结合使用,尤其是在使用富JavaScript的应用程序时。源和接收器之间的数据流以及准确显示数据传输和修改方式的能力使得此工具在你的工具库中非常有用。
使用该工具,我们完成了10个练习的解决方案。对于尝试学习客户端XSS的挖掘和利用的人,建议使用本文所描述的这些东西。
参考文献:
1、Sboxr — https://sboxr.com
2、客户端XSS漏洞 – https://www.owasp.org/index.php/Types_of_Cross-Site_Scripting#DOM_Based_XSS_.28AKA_Type-0.29
3、命令行开关 – https://dev.chromium.org/developers/how-tos/run-chromium-with-flags
4、XMLHttpRequest(XHR)MDN – https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
5、window.postMessage()MDN – https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
6、 https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
7、 https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
8、 https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
9、HTML 实体字符- https://dev.w3.org/html5/html-author/charref
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 开源邮箱客户端Thunderbird 60.3修复多个高危漏洞
- MySQL客户端jdbc反序列化漏洞payload
- 渗透测试及漏洞挖掘技巧干货分享——客户端JavaScript静态分析
- CVE-2019-0726:Win10 DHCP客户端RCE漏洞
- 挖洞经验 | 从存储型XSS到RCE的Steam客户端漏洞
- Razer Synapse 3 Windows客户端本地提权漏洞分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。