标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-3333]   作者: Candy 发表于: [2023-09-05]  [2023-09-05]被用户:Candy 修改过

本文共 [67] 位读者顶过

漏洞信息

漏洞编号:CVE-2023-2317

漏洞范围:Typora,≤1.67

漏洞说明:低于1.67版本的Typora存在代码执行漏洞,通过在标签中加载typora://app/typemark/updater/update.html实现在Typora主窗口的上下文中运行任意JavaScript代码。

问题代码段

整段代码如下,我们可以逐段进行分析:

[出自:jiwo.org]


				


首先看获取输入部分:


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]));


通过正则表达式匹配的方式,获取传入的5个GET参数:curVersion、newVersion、releaseNoteLink、hideAutoUpdates和labels。接收参数releaseNoteLink时会对输入做一次URI解码,接收labels参数时会先做一次URI解码,再做一次json解析。

获取输入后,会使用dom.innerText和din.innerHTML替换原页面中的代码,且没经过任何清洗,也就是这个地方会导致DOM型XSS。


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


代码里有两处替换,第一处将参数labels[4]和labels[5].replace("$1", newVersion).replace("$2", curVersion)做拼接,然后直接替换掉页面中的元素

。第二处遍历页面中拥有data-label属性的元素,然后使用dom.getAttribute("data-label") - 0这个trick获得当前遍历的data-label元素索引值,使用参数labels中对应的索引值进行替换。具体的替换点就在同文件内:


因此,我们分析出传入的参数labels是一个长度至少为5的数组,数组的前3个元素都会未经清洗的替换掉页面中的元素导致DOM型XSS(第4、5个参数使用的时innerText替换,无法利用),我们只需要在labels前4个元素中填入Payload,就可以实现命令执行。

漏洞利用

我们只需要,让Typora界面加载带有我们的payload访问的updater.html文件,就能实现命令执行。



Typora内部实现了typora://协议,可以用于Typora访问特定文件。我们在Typora中按下Shift+F12,可以看到Typora页面中使用了这种协议:

以这个访问为例,lib.asar位于Typora安装目录的resources文件夹下,而updater.html位于Typora安装目录的updater文件下,所以使用typora://协议访问updater.html应该这样写:


typora://app/typemark/updater/updater.html?a=xxx&b=xxx&c=xxx

根据前文分析的结果,我们需要传入curVersion、newVersion、releaseNoteLink、hideAutoUpdates和labels五个参数。对参数releaseNoteLink做一次URI解码,参数labels是一个长度至少为5的数组,也需要做一次URI编码,在labels的前3个元素中任选一个填入payload。

构建payload

根据常规思路,我们应该require库child_process然后调用exec参数,但是typora内没有定义require函数,而是使用reqnode函数代替:


因此,Windows环境下的payload可以这样写:

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

包在svg标签里实现页面加载:


编码前的Poc:

","","","",""]">

最后对releaseNoteLink、lables两个参数做URI编码,最终Poc为:

为了同时在Windows环境和Linux环境生效,我们可以这么写payload:

漏洞复现

  1. 新建一个md文件,贴入payload:

                保存后使用Typore打开,成功弹出calc:


漏洞修复

安装最新的1.6.7版本查看其updater.html文件,可以看到已经把innerHTML改成了innerText:



评论

暂无
发表评论
 返回顶部 
热度(67)
 关注微信