这是一个已记录(已知)的问题,但我在研究过程中发现了它,而且它对红队/渗透测试非常有用。
摘要: .git/config 中的 filter.<name>.clean 指令指向一个脚本,而 .gitattributes 将该过滤器绑定到一个被跟踪的文件。每当 git 渲染该文件的真实 git diff 时,它都会先通过 clean 命令处理工作区内容,因此 git 会盲目启动我们在此处指定的任何路径。
现在有趣的地方来了。我们的编辑器会在你点击已更改文件的瞬间自动运行 git diff,以填充其 SCM(源代码管理)面板和行内注释。仅仅打开文件夹是不够的,但查看更改就足够了,而当你进入一个仓库时,这是非常自然的操作。
这与 core.fsmonitor 的思路相同,只是使用了不同的指令,而且它不是 fsmonitor,所以任何盯着 fsmonitor 的人都不会发现它。这种技术手法适用于红队演练和假设已被入侵的场景,可搭配任意 C2 或我们的 XRayC2 获取能绕过传统网络防御的回连。(当然,需要钓鱼邮件来欺骗最终用户,但在 IDE 中打开文件夹并点击文件似乎是一个公平的操作。)
工作证明。 git clone 不会携带 .git/config,因此请保留 .git/ 完整地分发整个文件夹。.git/config 中的配置:
[filter "poc"]
clean = ./icons/clean.sh
smudge = cat
.gitattributes:
sample.txt filter=poc
sample.txt 已被提交,但以修改状态分发在工作区中。当 git 对其执行 diff 时,clean 过滤器就会触发。clean.sh 会弹出计算器,并原样传递内容,从而不会破坏工作区:
#!/bin/sh
pgrep -x Calculator >/dev/null 2>&1 || open -a Calculator 2>/dev/null
exec cat
在编辑器中打开该文件夹,点击 sample.txt 查看其更改,计算器就会弹出。(退出计算器可重新触发。)此 POC 是 macOS 特有的,请根据你的环境进行修改。
已在 Cursor(git CLI)和 Sublime Text(libgit2)上测试。
clean 过滤器只在完整的 git diff 时运行,而不是在 git status 时运行,因此它会在编辑器渲染更改时触发,而不仅仅是在打开文件夹时触发。有趣的是,Sublime 通过 libgit2 在进程内触发它,payload 的父进程是 sublime_text 本身,链路中没有 git 二进制文件,所以这不仅限于那些 shell 调用 git 的工具。
https://github.com/user-attachments/assets/31ea495f-1ed8-44f8-bef3-8c6366a0eece
与 fsmonitor 一样,这会受到编辑器“信任此文件夹?”提示的限制。大多数开发人员会保持 ~/Downloads 及类似的顶层文件夹为受信任状态,而 Cursor 默认关闭工作区信任,因此 PoC 会静默运行。如果仓库位于这些受信任路径之外,IDE 会在读取 .git/config 之前询问“是否信任此发布者?”。
Git 文档:core.fsmonitor 和 filter.* 参见 https://git-scm.com/docs/gitattributes。