ocx控件 postmessage消息会消失_通过HackerOne漏洞报告学习PostMessage漏洞实战场景中的利用与绕过...

eeaa3d1a8042ee203251754cc1f35530.png

0x00 前言

这是一篇关于postMessage漏洞分析的文章,主要通过hackerone平台披露的Bug Bounty报告,学习和分析postMessage漏洞如何在真实的场景中得到利用的。

0x01 什么是PostMessage

根据Mozilla开发文档描述:

The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.

也就是说,window.postMessage()方法可以安全地实现Window对象之间的跨域通信。例如,一个页面和它所产生的弹出窗口之间,或者一个页面和嵌入其中的iframe之间进行。

这里,我们看一个例子:

假设我们有一个主网站1.html与另一个网站2.html进行通信。在第二个网站中,有一个后退按钮,当第一个网站的导航改变时,这个按钮就会改变。例如,在网站1中,我们导航到 changed.html,那么网站2中的后退按钮就会指向 changed.html。为此,使用postMessage方法将网站1的值发送到网站2。

1.html中的代码如下:

    Website 1 var child;function openChild() {child = window.open('2.html', 'popup', 'height=300px, width=500px');}function sendMessage(){    let msg={url : "changed.html"};    // In production, DO NOT use '*', use toe target domain    child.postMessage(msg,'*')// child is the targetWindow    child.focus();}                                                

网站1中有两个按钮:

  1. 第一个是通过openChild()函数打开一个包含2.html的弹出窗口。

  2. 第二个是通过sendMessage()函数发送消息。要做到这一点,需要设置一个消息,定义msg变量,然后调用postMessage(msg,'*')

2.html中的代码如下:

    Website 2            // Allow window to listen for a postMessage    window.addEventListener("message", (event)=>{        // Normally you would check event.origin        // To verify the targetOrigin matches        // this window's domain         document.getElementById("redirection").href=`${event.data.url}`;        // event.data contains the message sent    });function closeMe() {        try {window.close();        } catch (e) { console.log(e) }        try {self.close();        } catch (e) { console.log(e) }}            

Recipient of postMessage

Go back

网站2中有一个链接和一个按钮:

  1. 链接处理重定向,href字段根据window.addEventListener("message", (event)接收到的数据而变化。接收到消息后,从event.data中读取事件中的数据并将url并传递给href

  2. 按钮调用函数closeMe()关闭窗口。

671bbcc535af8c4ae00a0cc5f5a6b510.png

0x02 一个基础漏洞的简例

XSS漏洞的实现

PostMessages如果执行不当,可能导致信息泄露或跨站脚本漏洞(XSS)。
在这种情况下,2.html在没有验证源的情况下就准备接收一个消息,因此我们可以将网页3.html作为iframe加载2.html,并调用postMessage()函数来操作href值。

    XSS PoC       let msg={url : "javascript:prompt(1)"};    var iFrame = document.getElementById("frame")    iFrame.contentWindow.postMessage(msg, '*');

在这里例子中,恶意的msg变量包含数据{url: "javascript:prompt(1)"};,该数据将被发送到2.html2.html处理后,将中的值更改为msg.url的值。iframe用于在网站中加载攻击。当用户单击返回链接时,将实现一个XSS。

f4b7ab63042f20adc944cf038aa7e558.png

1500e708af9cc9537965446282aa01d9.png

缓解措施

根据Mozilla文档中的说法。

如果不希望收到来自其他网站的消息,不要为任何消息添加事件监听器的。这可以完全避免此类安全问题。

如果希望从其他站点接收消息,需要对源和可能的源验证发送方的身份,因为任何窗口都可以向任何其他窗口发送消息,并且不能保证未知的发送者不会发送恶意消息。但是,在验证了身份之后仍然应该验证接收到的消息的语法,否则,也可能出现跨站点脚本攻击。

当使用postMessage向其他窗口发送数据时,一定要指定一个准确的目标,而不是*。恶意网站可以在不知情的情况下改变窗口的位置,安全的设置可以拦截使用postMessage发送的数据。

根据文档的方案,应当将1.html中的:

child.postMessage(msg,'*')

修改为:

child.postMessage(msg,'2.html')

2.html中的:

window.addEventListener("message", (event)=>{    ...}

修改为:

window.addEventListener("message", (event)=>{    if (event.origin !== "http://safe.com")    return;    ...}

漏洞检测

检测postMessage漏洞的方法是读取JavaScript代码。因为当定义了一个监听器后,需要按照事件数据流来分析代码是否以容易被攻击的函数结束。这里推荐两种方法来检测函数调用:

  • 1 . J2EEScan,从git仓库(https://github.com/ilmila/J2EEScan)可以获得更新版本,而不是从 Burp AppStore。
  • 2 . BurpBounty (https://github.com/wagiro/BurpBounty),定义一组用于搜索关键字的被动响应字符串,如 postMessage 、addEventListener("message 、 .on("message"。

0x03 hackerone 漏洞报告分析

如果你在hackerone平台搜索PostMessage漏洞报告关键字,将看到一些报告,有一些漏洞被发现的时间距离现在并不遥远,并且获得了丰厚的奖励。这里重点分析3篇Hackerone披露的报告,并提供一些利用/绕过postMessage漏洞的技巧。

eafdfd25a51888e5a5eaf80768d4c4a3.png

DOM Based XSS in www.hackerone.com via PostMessage and Bypass (#398054)

在hackeronep披露的 #398054报告中,通过Marketo中的不安全消息事件侦听器,Dom XSS在Hackerone中被成功利用。代码流程如下图所示:

dcb0a82112e6a2fe71a8896e244d5469.png

通过分析报告可以看出,如果响应的设置没有错误,它就会创建一个名为u的变量,并将其设置为findCorrectFollowUpUrl方法的返回值。这将对一个名为followUpUrl的响应对象的属性进行处理,该属性是在表单提交完成后重定向的URL。

但是HackerOne窗体并没有用到这个,攻击者通过将其设置为绝对URL,就可以控制u变量的值。后来这个变量被用来改变窗口的location.href。当向Hackerone窗口发送下图所示的mktoResponse消息时,窗口被重定向到JavaScript URL,并执行代码alert(document.domain)

569254327c3d38e9ee84087ee6a8c0e3.png

这部分代码由三部分组成:

1、 mktoResponsePostMessage 的第一个JSON元素,以调用函数:
else if (d.mktoResponse){    onResponse(d.mktoResponse)}
2、为了能执行这个函数,需要一个JSON结构数据,其元素有 forerrordata 。如果 errorfalse ,则 repuest.success 执行:
var requestId = mktoResponse["for"];  var request = inflight[requestId];  if(request){    if(mktoResponse.error){      request.error(mktoResponse.data);    }else{      request.success(mktoResponse.data);
3、在这个函数中, followUpUrl 值将关联到 u ,并传递给 location.href 。因此,有效payload javascript:alert(document.domain) 触发XSS执行:
var u = findCorrectFollowUpUrl(data);  location.href = u;

这个漏洞提交之后,Hackerone团队修改了OnMessage函数,添加了一个对源的验证:

if (a.originalEvent && a.originalEvent.data && 0 === i.indexOf(a.originalEvent.origin)) {    var b;    try {        b = j.parseJSON(a.originalEvent.data)    } catch (c) {        return    }    b.mktoReady ? f() : b.mktoResponse && e(b.mktoResponse)}

Bypass #398054 (#499030)

@honoki在报告#499030找到了上述#398054漏洞修复后的绕过办法。

在上述的修复代码中,变量i解析为https://app-sj17.marketo.com/indexOf检查字符串中是否包含源。因此注册一个marcarian域名.ma,验证将被绕过:

("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")

如果之前的漏洞攻击代码托管在注册域名https://app-sj17.ma下,XSS依旧会被成功执行。

CVE-2020-8127: XSS by calling arbitrary method via postMessage in reveal.js (#691977)

在报告#691977中,@s_p_q_r提交了一个通过PostMessage成功利用的DOM XSS。代码流程如下图所示:

5fbaa5ff53109643ed93319eb68ea1da.png

首先,使用addKeyBinding方法调用setupPostMessage来定义带有恶意负载的JSON元素。然后,调用函数showHelp()在浏览器中展示出registeredKeyBindings[binding].description中定义的malicios有效payload。要利用此漏洞,使用以下代码:

46879504c2d0765895b92838c3c818ed.png

这个代码片段中有三个部分:

1、将第一个JSON元素作为 "method":"addKeyBinding" ,用于调用方法并应用到 args :
if( data.method && typeof Reveal[data.method] === 'function' ) {    Reveal[data.method].apply( Reveal, data.args );
2、为了到达函数 addKeyBinding 与参数 args ,构造一个JSON对象,包含 callbackkeydescription
function addKeyBinding( binding, callback ) {    if( typeof binding === 'object' && binding.keyCode ) {        registeredKeyBindings[binding.keyCode] = {            callback: callback,            key: binding.key,            description: binding.description        };    }
3、调用 toggleHelp() 函数,在没有验证的情况下展现了包含payload的JSON数据,触发JavaScript执行:
function showHelp() {    ...    for( var binding in registeredKeyBindings ) {        if( registeredKeyBindings[binding].key && registeredKeyBindings[binding].description ) {            html += '' + registeredKeyBindings[binding].key + '' + registeredKeyBindings[binding].description + '';        }    }    ...}
 

0x04 绕过PostMessage漏洞的技巧

1 . 如果indexOf()被用来检查PostMessage的源,如果源包含在字符串中,有可能被绕过,如Bypass #398054 (#499030)中分析的那样。

2 . 如果使用search()来验证源,也有可能是不安全的。根据String.prototype.search()的文档,该方法接收一个常规的压缩对象而不是字符串,如果传递了正则表达式以外的任何东西,也将被隐式转换为正则表达的内容。例如:

"https://www.safedomain.com".search(t.origin)

在正则表达式中,点(.)被视为通配符。换句话说,源的任何字符都可以用一个点来代替。攻击者可以利用这一特点,使用一个特殊的域而不是官方的域来绕过验证,比如www.s.afedomain.com就可以绕过上述语法的验证。

3 . 如果使用了escapeHtml函数,该函数不会创建一个新的已转义的对象,而是重写现有对象的属性。这意味着,如果我们能够创建具有不响应hasOwnProperty的受控属性的对象,则该对象将不会被转义。例如,File对象非常适合这种场景的利用,因为它有只读的name属性,使用这个属性,可以绕过escapeHtml函数:

// Expected to fail:result = u({  message: "'\"\\"});result.message // "'">b// Bypassed:result = u(new Error("'\"\\"));result.message; // "'"\"

0x05 hackerone上PostMessage漏洞报告推荐

Hackerone report #168116(Twitter: Insufficient validation on Digits bridge)

Hackerone report #231053(Shopify: XSS on any Shopify shop via abuse of the HTML5 structured clone algorithm in postMessage listener on “/:id/digital_wallets/dialog”)

Hackerone report #381356(HackerOne: Client-Side Race Condition using Marketo, allows sending user to data-protocol in Safari when form without onSuccess is submitted on www.hackerone.com)

Hackerone report #207042(HackerOne: Stealing contact form data on www.hackerone.com using Marketo Forms XSS with postMessage frame-jumping and jQuery-JSONP)

Hackerone report #603764(Upserve: DOM Based XSS via postMessage at https://inventory.upserve.com/login/)

Hackerone report #217745(Shopify: XSS in $shop$.myshopify.com/admin/ via “Button Objects” in malicious app)

参考文献

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

https://medium.com/javascript-in-plain-english/javascript-and-window-postmessage-a60c8f6adea9

https://hackerone.com/hacktivity?querystring=postmessage

8a21aa577969e7bb0aef803922c92129.png

- End -

精彩推荐

使用无括号的XSS绕过CSP策略研究

攻防演练中防守方的骚姿势

ZeroLogon的利用以及分析

RTL-SDR接收NOAA气象卫星

8a21aa577969e7bb0aef803922c92129.png

b8fd561df8396090b481c2cd4278da46.gif 戳“阅读原文”查看更多内容
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值