如何在 Evernote 上实现 RCE 【部分】

admin 2024年7月17日10:32:54评论20 views字数 5112阅读17分2秒阅读模式

前言

就在本周,国外安全研究人员在 Evernote  应用程序中发现了一个关键的 JavaScript 注入 -> RCE 漏洞。只需点击共享的带有嵌入字体注入恶意PDF的‘糖衣’笔记,攻击者就可以通过利用预加载和暴露的 ipcRenderer API 与 Evernote 的内置 IPC 事件监听器 *BrokerBridge*在主进程无形中任意执行命令和文件。

虽然安全研究人员在这个完全隐蔽的大型 应用程序中从头开始创建了一个 4 步 IPC Payloads 利用链,并为此奋斗了6个小时,但这将是值得分享和研究的绝好材料。

本文将探索 Evernote 从 XSS->RCE 的旅程,其中包含:

  • 了解 Electron 的 Multi-Process 模型、 IPC 处理程序和 preload.js 的功能
  • 了解 PDF.js 中字体注入的 JavaScript 注入是如何工作的
  • 逆向工程和调试来自2.5亿用户 Evernote 的 asar-packed模糊源
  • 深入研究构建的现实实例中的 Electron -> IPC 事件通信,以及如何通过两个 Inter-process 桥利用 RCE 向量复杂的设计

PDF.js 字体注入

Evernote 作为一款很棒的笔记集成应用程序,允许用户将 PDF 文件嵌入笔记中以供查看和标记,这确实是 Evernote 一个很棒的功能,尽管如此,它也是漏洞利用链的起点,将一个有用的功能变成了一个严重的漏洞。

对于集成的 PDF 交互, Evernote 使用了最常用的 PDF 插件 – PDF.js ,它允许交互并解析 PDFs 二进制文件;只需导入使用 Javascript 构建的 pdfjs-dist 包即可轻松访问 PDFs ;

为了使 PDF.js 在生产环境中运行,维护团队必须为 extracting 和 rendering PDF metadata 开发自己的逻辑和代码,那么就容易发生意想不到的问题。

可爱的字体

PDF格式的好处是可以在不同的渲染环境下保存文件,比如有人发给你的 .docx 文件总是在你的电脑上出现奇怪的情况;但作为 PDFs则可以在元数据中嵌入字体,以便在渲染过程中进一步使用,这实际上是将字形变成了像图像一样的曲线(也称为矢量化)。为了迅速实现这一目标,PDF.js的优化团队引入了字形的pre-compiled path generator function(预编译路径生成器功能):

// If we can, compile cmds into JS for MAXIMUM SPEED...
if (this.isEvalSupported && FeatureTest.isEvalSupported) {
  const jsBuf = [];
  for (const current of cmds) {
    const args = current.args !== undefined ? current.args.join(",") : "";
    jsBuf.push("c.", current.cmd, "(", args, ");n");
  }
  // eslint-disable-next-line no-new-func
  console.log(jsBuf.join(""));
  return (this.compiledGlyphs[character] = new Function(
    "c",
    "size",
    jsBuf.join("")  // Kaboom!
  ));
}

COPY

其方法是创建一个 JavaScript Function对象,该对象的主体 (jsBuf) 包含构成路径的指令

然而假如我们可以控制由 new Function( 解析的 cmds ;那么就可以控制 PDFs 的执行流程,因为Payloads也将被new Function(解析,因此让我们从头到尾来探讨如何解析cmds命令;

  compileGlyph(code, glyphId) {
    if (!code || code.length === 0 || code[0] === 14) {
      return NOOP;
    }

    let fontMatrix = this.fontMatrix;
    ...

    const cmds = [
      { cmd: "save" },
      { cmd: "transform", args: fontMatrix.slice() },
      { cmd: "scale", args: ["size", "-size"] },
    ];
    this.compileGlyphImpl(code, cmds, glyphId);

    cmds.push({ cmd: "restore" });

    return cmds;
  }

COPY

跳转到 compileGlyph ,该函数初始化 vectorization(矢量化) 的命令,处理并传递监视列表中的 cmds 。一个关键的关注点是使用从 this.fontMatrix 派生的参数 fontMatrix.slice() 构造 cmdtransform 。

其中 PDF.js 生成 vectorization 命令,例如 save 、 transform 和 scale ;然后将其解析为之前的 new Function( 评估;

但这里最重要的问题是如何解析 this.fontMatrix,默认情况下, FontMatrix 设置为 [0.001, 0, 0, 0.001, 0, 0] ,由此可以推测它可能来自元数据中的数字数组。

extractFontHeader(properties) {
    let token;
    while ((token = this.getToken()) !== null) {
      if (token !== "/") {
        continue;
      }
      token = this.getToken();
      switch (token) {
        case "FontMatrix":
          const matrix = this.readNumberArray();
          properties.fontMatrix = matrix;
          break;

COPY

extractFontHeader 方法似乎从 metadata 中提取 FontMatrix 标记值,在本例中是 readNumberArray ,这意味着我们将完全停留在数字输入中,使得 Javascript 注入变为不可能!

尽管如此,在这种情况下,FontMatrix 也可能源自加载大量与字体关联的 PDF 属性的 PartialEvaluator.translateFont(...) :

    const properties = {
      type,
      name: fontName.name,
      subtype,
      file: fontFile,
      ...
      fontMatrix: dict.getArray("FontMatrix") || FONT_IDENTITY_MATRIX,
      ...
      bbox: descriptor.getArray("FontBBox") || dict.getArray("FontBBox"),
      ascent: descriptor.get("Ascent"),
      descent: descriptor.get("Descent"),
      xHeight: descriptor.get("XHeight") || 0,
      capHeight: descriptor.get("CapHeight") || 0,
      flags: descriptor.get("Flags"),
      italicAngle: descriptor.get("ItalicAngle") || 0,
      ...
    };

COPY

Cool~PartialEvaluator.translateFont(...) 中定义的 fontMatrix 的来源似乎不受数字限制!允许我们将 javascript Payloads 注入为 fontMatrix -> compileGlyph -> new Function( 。

尽管如此,要利用这一点,必须了解 fonts 在 PDFs 中的工作原理,其中 font 实际上由 /Font 、 /FontDescriptor 和 /FontFile 组成,结构如下:

1 0 obj
<<
  /Type /Font
  /Subtype /Type1
  /FontDescriptor 2 0 R
  /BaseFont /FooBarFont
>>
endobj

COPY

但是,该Payload不会直接起作用,因为 /FontMatrix 将引用嵌入在 Type1 font 内部的 default matrix ,我们可以尝试首先导入一个没有内部FontMatrix定义的Type1字体,因为PDF.js定义的PartialEvaluator.translateFont(...)将取代权威的默认矩阵,允许我们获得对可疑FontMatrix的完全控制 。

结合这一点,我们可以尝试将 /FontMatrix [1 2 3 4 5] 转换为类似 /FontMatrix [1 2 3 4 5 (0); alert('PDF')] 的内容,其中 c.transform 转换将被字面解释为 /FontMatrix [1 2 3 4 5] ,并遵循 alert('foobar'),允许我们向 PDF 中注入任意 Javascript,然后当 glyphs 穿过 pre-compiled path generator function 时,它将被解释为求值,从而允许任意 Javascript 注入 !

IPC 和 RCE

当检查 Evernote 的 PDF 集成功能时,研究人员发现 Evernote 很容易受到 PDF.js 的灾难性供应链攻击,因为当.pdf 文件被嵌入到 Evernote -> supernote 时,PDF 将通过一种重新打包的自定义版本 pdfjs-dist 预加载,以便预览!这使得我们能够向任何 supernote 中注入任意 JavaScript,只要加载 PDF,JavaScript 就会被执行;

对于正常的渗透或漏洞赏金之旅,通过该漏洞即可轻松触发存储型XSS可能被认为非常强大和有影响力,因为我们可以实现帐户接管、蠕虫感染其它个人帐户以及查看他人的私人笔记,甚至将它们连接到远程监听地址…

然而,当研究人员进一步探索时,发现 Evernote 客户端中的渲染接收器(XSS)实际上发生在document.location.origin -> app://evernote而不是iframe 或 webpack !

这一方面禁止了我们直接访问登录凭据(如ducument.cookie 和其他evernote.com 资源),另一方面又允许我们访问本地特权 API 和本地域中的暴露对象!这使得 XSS 一经扩展就有可能实现 RCE!

在如何升级远程代码执行之前,我们还需要了解一些非常重要的事情: Electron 的 Multi-Process 和 IPC

Electron 与 Multi-Process model

大多数时候,人们下载客户端版本的 应用程序以获得更多功能,例如,本地文件管理、引用硬盘上的资源、屏幕截图和访问剪贴板等;

以上这一切都能够快速、轻松、安全地发生,依赖于 Electron 引入了基于 Node.js 和 Chromium 的开源软件框架,并用于90%的桌面客户端开发,例如 1Password 、 Notion 、 draw.io …. 当然还有今天的主角 Evernote 。

然而,为了防止 JavaScript 注入等情况很容易升级为远程代码执行, electron 的开发人员引入了一些非常聪明的东西 – Multi-Process Model ,它也在 Chromium中 。

如何在 Evernote 上实现 RCE 【部分】

Multi-Process Model 与 renderer process (可以直接访问硬件,能够通过 require() 展示 Node.js 功能)为每个标签页生成的呈现器进程隔离开来,在这种情况下,你的 Youtube 选项卡是无法访问银行网站上的 DOM 树、敏感信息的,同时还禁止你访问:

  • 在渲染器中执行任意 JavaScript(XSS 或导航到外部站点)
  • 将 preload 或 Electron 内部代码中使用的内置方法重写为自己的函数
  • 触发使用 overwritten function(覆盖函数)

另外,electron 引入了 nodeIntegrations 功能,将 nodeIntegrations 设置为false,我们无法利用 require('child_process') 功能, Evernote 也是如此,这种机制禁止通过受损的 PDF.js 集成组件直接执行代码,但是仍然可以用这个 XSS 做一些有趣的事情......

原文始发于微信公众号(骨哥说事):如何在 Evernote 上实现 RCE 【部分】

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月17日10:32:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   如何在 Evernote 上实现 RCE 【部分】https://cn-sec.com/archives/2961438.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息