Chukwuemekamusic/assessment-sandbox
GitHub: Chukwuemekamusic/assessment-sandbox
一个基于 Docker 的安全沙箱环境,用于安全地审查和运行不受信任的招聘评估代码仓库,防范凭据窃取和加密货币挖矿恶意软件。
Stars: 0 | Forks: 0
# 评估沙箱
安全的、基于 Docker 的环境,用于评估不受信任的代码仓库 —— 尤其是那些旨在窃取凭据或在你机器上挖掘加密货币的虚假招聘者评估任务。
## 为什么你需要这个
虚假招聘者评估正成为一种日益严重的攻击媒介。其典型模式为:
1. “招聘者”在 LinkedIn 上联系你,提供一个令人心动的机会
2. 他们发送一个 GitHub 仓库作为“技术评估”
3. 你克隆它,运行 `npm install && npm start`,并审查代码
4. 一个恶意包会悄悄安装加密货币矿机、窃取凭据,或者开启一个反弹 shell —— 它以**你**的身份运行,并拥有对你的 SSH 密钥、AWS 凭据、浏览器会话以及整个主目录的访问权限
这些攻击非常复杂。源代码看起来很干净。静态分析什么也发现不了。恶意软件隐藏在深层嵌套的 npm 依赖项中,仅在运行时触发 —— 也就是在你已经放松警惕之后。**切勿在宿主机上直接运行未经请求的评估仓库。**
## 结构
```
assessment-sandbox/
├── docker/
│ ├── Dockerfile # Ubuntu 24.04 + Node 22 + Python 3 + audit tools
│ └── docker-compose.yml # Safe (no-net) and net-enabled profiles
├── scripts/
│ └── sandbox.sh # Main launcher — wraps all Docker complexity
└── claude-prompts/
└── investigate-repo.md # Paste into Claude Code for AI-assisted codebase audit
```
## 前置条件
- 已安装并正在运行 [Docker Desktop](https://www.docker.com/products/docker-desktop/)
- 宿主机上已安装 `jq`(macOS 上使用 `brew install jq`)
- 将 `sandbox.sh` 脚本设置为可执行(仅需一次):
```
chmod +x assessment-sandbox/scripts/sandbox.sh
```
## 安全工作流(每次都必须遵循)
共分为**四个阶段**。不要跳过任何步骤。这些阶段按从最低成本到最安全的顺序排列:先进行静态工作,最后进行执行。
```
Phase 1 — Clone safely
Phase 2 — AI-assisted static audit (no code runs)
Phase 3 — Sandboxed dependency audit (no app code runs)
Phase 4 — Run the app inside the sandbox (contained execution)
```
### 阶段 1 — 安全克隆
切勿直接使用 `git clone `。务必禁用钩子并阻止子模块:
```
git -c core.hooksPath=/dev/null clone --no-recurse-submodules assessments/
```
**原因:**
- `core.hooksPath=/dev/null` —— 防止任何 `.git/hooks/` 脚本在克隆或检出时运行。恶意仓库有时会自带激活的钩子。
- `--no-recurse-submodules` —— 防止子模块(它们本身可能就是独立的恶意仓库)被自动拉取。
### 阶段 2 — AI 辅助静态审计(只读,不执行任何内容)
打开 Claude Code 指向已克隆的仓库,并将 `claude-prompts/investigate-repo.md` 的内容粘贴到提示词中。
Claude 将在不执行任何内容的情况下,经历五个阶段:
| 阶段 | 检查内容 |
|---|---|
| 信息侦察 | 目录树、技术栈、所有依赖项、安装钩子、二进制文件、`.env` 文件 |
| 静态安全扫描 | `eval`、`exec`、`child_process`、base64 混淆、网络调用、凭据访问 |
| 架构总结 | 数据流、入口点、外部服务 |
| Docker 设置 | 如有需要,为特定项目生成安全的 Dockerfile |
| 最终裁决 | 低 / 中 / 高风险及具体发现 |
**在继续之前,请务必阅读阶段 5 的裁决结果。**
### 阶段 3 — 沙箱内依赖审计
运行沙箱启动器。它将:
- 扫描仓库以查找可疑模式(宿主机侧预检)
- 如果尚未构建,则构建 Docker 镜像
- 将仓库以**只读**方式挂载到隔离的容器中
- 根据需要运行 `npm audit` / `pip-audit` / `bandit`(网络仅用于访问漏洞咨询数据库,绝不执行仓库自身的代码)
```
./assessment-sandbox/scripts/sandbox.sh
```
示例:
```
./assessment-sandbox/scripts/sandbox.sh assessments/Lake_Crypto_Card_MVP
```
审查输出结果。对于较旧的代码库,出现大量 CVE 是正常的 —— 重点需关注:
- 没有可用修复程序的严重 CVE(可能表明依赖版本被故意投毒)
- 包含安装脚本且不太知名的包(像 `bufferutil`、`keccak`、`core-js` 等是没有问题的 —— 但随机的包名就很可疑)
- 任何看起来像是通过域名抢注或拼写抢注热门库的包
### 阶段 4 — 运行应用(受限执行)
只有在完成阶段 2 和 3 之后才能进行到这里。沙箱可确保:
- 所有内容均以非特权用户(`sandbox`,UID 1001)身份运行 —— 而不是 root
- 所有的 Linux capabilities 均已被舍弃(`--cap-drop ALL`)
- 你的主目录、SSH 密钥和凭据永远不会被挂载
- 仓库以只读方式挂载 —— 恶意软件无法修改克隆的源代码
- `/tmp` 是一个独立的内存级 tmpfs —— 容器退出时丢弃的文件会随之消失
- 终止容器会立即销毁其中的所有进程和痕迹
**选项 A — 交互式 shell(手动安装和探索):**
```
# 执行 npm install 需要网络;请在该步骤使用 --net
./assessment-sandbox/scripts/sandbox.sh --net assessments/
# 在容器内 — 你将启动于 ~/work/repo 的一个可写副本中
npm install
npm test
npm start # or whatever the start command is
```
**选项 B — 非交互式运行特定命令:**
```
./assessment-sandbox/scripts/sandbox.sh --cmd "npm test" assessments/
```
**选项 C — 在浏览器中查看 Web 应用(使用端口映射手动运行 Docker):**
`sandbox.sh` 启动器默认不暴露端口。要查看 Web 应用,请使用相同的安全标志并附加 `-p` 直接运行 Docker:
```
docker run --rm \
--security-opt no-new-privileges:true \
--cap-drop ALL --cap-add CHOWN --cap-add SETUID --cap-add SETGID \
--tmpfs /tmp:size=256m,mode=1777 \
-v "$(pwd)/assessments/:/sandbox/repo:ro" \
--user sandbox \
--network bridge \
-p 3000:3000 \
-e BROWSER=none \
-e CI=false \
assessment-sandbox:latest bash -c '
mkdir -p ~/work/repo
cp -a /sandbox/repo/. ~/work/repo/
cd ~/work/repo
npm install
npm start
'
```
然后在浏览器中打开 `http://localhost:3000`。完成后,按 `Ctrl+C` 停止服务器,`--rm` 会自动删除容器及其所有内容。
## 在运行时进行主动监控
不要仅仅运行应用后就走开。在容器运行期间,请在第二个终端中检查是否有意外进程 —— 这正是抓获上文所述真实恶意软件的方法:
```
# 在第二个终端中 — 检查正在运行的容器内的进程列表
docker exec ps aux
# 监控 /tmp 以防范意外的文件生成
docker exec ls -la /tmp/
# 检查打开的网络连接
docker exec cat /proc/net/tcp
```
**需警惕的危险信号:**
| 信号 | 含义 |
|---|---|
| 以日志文件命名的进程(`npm-compiler.log`、`node-build.log`) | 伪装自身的恶意软件 |
| 在 `/tmp` 中运行的 `node .dat` | 从临时存储区执行的混淆 payload |
| `/tmp` 中出现了以前不存在的文件 | 正在释放的恶意软件 |
| 所有文件描述符(FD)均指向 `/dev/null` 的进程 | 守护进程化的隐藏进程 |
| stdin/stdout 连接到 socket(而非管道)的进程 | C2 通道或反弹 shell |
| `/tmp` 中出现意外的 `node_modules/` 目录 | 正在安装自身依赖项的恶意软件 |
| 意外进程导致 CPU 占用率极高 | 加密货币矿机 |
如果你发现任何这些情况:
```
# 立即终止容器
docker kill
docker rm
# 验证主机上没有任何内容残留
ps aux | grep -E 'npm-compiler|0001\.dat'
ls /tmp/ | grep -v apple # macOS
```
## 沙箱可防范的威胁
| 威胁 | 是否防护? | 如何防护 |
|---|---|---|
| 恶意的 `postinstall` / `preinstall` 脚本 | ✓ | 容器隔离,非特权用户 |
| `require()` 引入的包中包含运行时恶意软件 | ✓ | 所有进程均被限制,并随容器一并终止 |
| 代码读取 `~/.ssh`、`~/.aws`、`~/.npmrc` | ✓ | 从不挂载主目录 |
| 通过网络窃取凭据 | ✓ | 默认 `--network none`;仅在需要时使用 `bridge` |
| 代码写入你的主目录 | ✓ | 仓库以只读方式挂载,不挂载主目录 |
| 在你的 CPU 上运行的加密货币矿机 | ✓ | 被限制且易于通过 `ps aux` 发现 |
| 进行外部联机的反弹 shell | ✓ | 默认阻止网络通信 |
| 关闭终端后依然驻留的恶意软件 | ✓ | 退出时 `--rm` 会删除容器及所有进程 |
| 容器逃逸漏洞利用 | ⚠ | 有可能 —— 对于高风险裁决,请使用完整的虚拟机 |
## 所有 `sandbox.sh` 选项
```
sandbox.sh [OPTIONS]
Options:
-n, --net Allow network access (needed for npm install)
-q, --no-audit Skip the pre-run dependency audit
-c, --cmd Run a specific command instead of an interactive shell
-b, --build Force rebuild the Docker image
-h, --help Show help
```
## 重新构建 Docker 镜像
如果 Dockerfile 发生更改,或者你想要一个包含更新工具版本的新镜像:
```
./assessment-sandbox/scripts/sandbox.sh --build assessments/
```
或者直接操作:
```
docker build -t assessment-sandbox:latest assessment-sandbox/docker/
```
## 已安装的审计工具(容器内)
| 工具 | 用途 |
|---|---|
| `npm audit` | 针对 npm 漏洞咨询数据库进行 Node 依赖项漏洞扫描 |
| `better-npm-audit` | 具有更佳格式化的增强版 npm audit |
| `pip-audit` | Python 依赖项漏洞扫描 |
| `safety` | Python 包安全检查 |
| `bandit` | Python 静态安全分析器 |
| `semgrep` | 多语言静态分析(支持 `--config=auto` 以实现广泛覆盖) |
| `snyk` | 依赖项 + 代码安全扫描 |
| `strace` | Syscall 跟踪 —— 用于观察进程实际执行操作非常有用 |
| `file`、`binutils` | 二进制检查工具 |
## 已知局限性
- **运行时恶意软件可以逃避 postinstall 扫描。** 真实的事件表明,一个包在 `npm install` 期间可能完全干净,只有在 `npm start` 通过 `require()` 加载它时才会释放恶意软件。务必在运行时(阶段 4)密切关注进程列表。
- **`semgrep` 和静态分析仅扫描仓库自身的代码,而非深层的依赖项内部。** semgrep 结果干净并不意味着依赖树是安全的。
- **`npm audit` 报告 CVE,但无法检测到新型或零日供应链攻击。** 0 漏洞的审计并不意味着仓库运行起来是安全的。
- **存在容器逃逸的可能。** 沙箱使用了 `--cap-drop ALL` 和 `no-new-privileges`,这涵盖了所有已知的常见逃逸向量,但复杂的内核漏洞利用仍有可能逃逸。对于来自未知或不受信任来源且被判定为高风险的仓库,请使用一次性的虚拟机(例如, afterwards 可以销毁的免费层级云实例)。
## 快速参考卡片
```
Received a suspicious repo?
│
├─ 1. Clone safely
│ git -c core.hooksPath=/dev/null clone --no-recurse-submodules assessments/
│
├─ 2. Static audit (no execution)
│ Open Claude Code → paste claude-prompts/investigate-repo.md → read verdict
│
├─ 3. Dependency audit (no app code runs)
│ ./assessment-sandbox/scripts/sandbox.sh assessments/
│
├─ 4. Run in sandbox (contained)
│ ./assessment-sandbox/scripts/sandbox.sh --net assessments/
│ → npm install && npm start
│ → in second terminal: docker exec ps aux (watch for malware)
│
└─ If you see unexpected processes → docker kill immediately
```
标签:Cutter, Docker沙箱, MITM代理, TLS, 代码执行环境, 恶意代码分析, 版权保护, 请求拦截, 逆向工具, 配置文件, 防御工具