Skip to content

修补当前漏洞的建议 #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
KawaiiZapic opened this issue Apr 29, 2025 · 4 comments
Open

修补当前漏洞的建议 #10

KawaiiZapic opened this issue Apr 29, 2025 · 4 comments

Comments

@KawaiiZapic
Copy link

KawaiiZapic commented Apr 29, 2025

发表一些拙见,考虑不周请多担待。

问题

  1. 启动时未检查启动的目标是否为正确的核心 (可以启动任何恶意程序)
  2. 不知道请求是否确实由GUI发出,缺少鉴权手段 (通过连接暴露到局域网的Clash代理访问daemon)
  3. HTTP API有从网页调用的可能,不带参数的简单POST请求不受CORS限制造成DoS攻击(网页可以直接停止核心)

威胁

  1. 权限提升
  2. 拒绝服务

目标

  1. 检查核心是否正确
  2. 拒绝不具有Local Access的程序访问daemon (阻止局域网访问、网页简单请求访问)

手段

  1. 对核心做校验和(阻止其他路径的程序启动,阻止核心被替换为恶意程序)
  2. 鉴权;限制UA;限制代理访问daemon

实现思路

校验和

  1. 尝试启动核心前,先对核心做SHA256校验和
  2. 校验和由GUI生成,写入到本地磁盘上的文件
  3. GUI需要请求用户以管理员权限执行写入校验和到磁盘的操作,并正确设置校验和文件的权限,阻止非管理员修改校验和文件内容
  4. daemon收到启动核心请求,首先检查校验和文件是否存在,再检查校验和文件是否设置了正确的权限。校验和文件通过检查后,再对将要启动的核心计算校验和,并比对文件内容。校验和文件权限检查通过(必须检查权限防止校验和被伪造)且核心的校验和与文件中的相同,才允许启动核心。

阻止不合适的人访问daemon

  1. 考虑直接上一套鉴权,最容易想到但是最麻烦(如何在daemon与GUI之间同步secret)
  2. 检查来源UA,阻止浏览器访问daemon,启动核心时强行添加一条规则拒绝连接到本地的daemon。(Direct模式绕过规则仍然可以访问)

未能解决的问题

  1. 攻击者仍可以通过指定启动核心时使用的配置,利用核心的本身的一些功能,以使用核心附带的高权限来进行任意文件的覆写(Linux可以设置Capabilities限制实际权限范围,其他平台?)
  2. 攻击者通过替换核心程序文件,用户发现无法启动核心,误打误撞重新生成校验和,使攻击者得逞,达到绕过校验的目的(也设置核心文件的权限为仅限管理员写入?当核心文件校验和不对时强制重新下载核心?在GUI对用户发出极其严重的警告?)
@BreezeWontFlinch
Copy link

最稳妥的办法只能是仅允许高特权用户调用,所以每次要打开关闭代理都得过uac

@xmcp
Copy link

xmcp commented Apr 30, 2025

如何在daemon与GUI之间同步secret

我觉得可以存到配置文件里。事实上,目前clash api的鉴权token就是存到配置文件里的,攻击者如果能读本地文件,他已经可以去通过clash api去操纵代理的开关了(甚至能做到更危险的事情,比如把所有流量都代理到自己手里)。在此基础上能额外控制service的启停并不构成更大的安全风险。

为了阻止提权风险,这个配置文件需要设置成管理员可写、普通用户只读,配置文件内容包括鉴权token和/start_clash的所有配置项。即:

  • 安装服务前创建配置文件,设置好权限,写入一个随机生成的token和初始的/start_clash参数
  • service暴露的API仅支持启停核心,用配置文件中的token鉴权,/start_clash参数不从请求读取而是从配置文件读取
  • 在GUI修改核心配置时,走UAC更新配置文件,然后调用/start_clash让service重新读取参数

这个方案不管怎么说都比简单检查UA要靠谱,这样也不再需要专门阻止透过代理连接到service api了(因为远程的攻击者不知道token),甚至checksum都不需要算(因为所有参数都固化到配置文件里)。

@KawaiiZapic
Copy link
Author

需要重新思考一下,Clash自带的TUN模式到底是不是必须的,因为Clash的功能特别丰富,如果必须将其以高权限执行,将来可能还会存在更大的风险。
如果并非必须,考虑使用TUN2Socks之类的方式去实现这一功能,或者作为一个安全的下位替代品,允许用户手动以管理员启动来使用Clash自带的TUN模式。

@JZYFC
Copy link

JZYFC commented May 1, 2025

阻止不合适的人访问daemon

关于这个问题,也可以用系统提供的IPC方式解决。目前代码中用warp开了http服务器,warp完全支持使用tcp以外的方式传输数据,只要是个异步读写流就行。Windows下面可以使用Named Pipe,Linux/MacOS可以用 Unix Domain Socket,这两种方式还都有对应系统提供的额外的访问控制。

目前的问题是GUI那边使用的reqwest库目前还不支持Named Pipe和Unix Domain Socket,这个方案的实际可行度也不高。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants