Files
.pouch/skills/host-sec-check/SKILL.md
T
2026-09-04 11:54:07 +08:00

131 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: host-sec-check
description: >-
Linux/VPS 主机安全检查与入侵取证:先取证再处置。覆盖矿机、ld.so.preload 进程隐藏、带宽挂机容器、对外端口、SSH/Docker/k8s 入口、cron/systemd 持久化、hugepage/OOM。
Use when: 安全检查, 被黑, 入侵, 矿机, 排查端口, 对公网放开, rpcbind, 挂机赚钱, Portainer, 安全审计, host security, compromise, cryptominer, exposure, /host-sec-check.
---
# host-sec-check
对一台 Linux 主机做安全检查。默认 **只读取证 + 出报告**。清理、关端口、重启、轮换密钥必须用户明确同意后再做。
需要:SSH 目标(`user@host` 或 ssh config 别名)、哪张网卡/IP 算公网。没有公网 IP 就只报「监听面」,并标明未做外部探测。
## 不适用
- Web 应用代码审计、依赖 CVE 扫描(可在报告里列为后续)
- 云厂商安全组控制台(能查就查,查不到就写「未验证」)
- 未获准的破坏性操作(`rm -rf`、整盘 wipe、强制重启)
## 铁律
1. **先取证,后动手。** 重启、删文件、停服务会毁掉证据。
2. **不要把密钥打进对话。** token、密码、authorized_keys、kubeconfig 只写「存在/已轮换/路径」,不贴原文。
3. **sudo 失败不要停。** 用户在 `docker` 组时,用特权容器 `nsenter` 看宿主机(见 [references/access.md](references/access.md))。
4. **怀疑进程隐藏时,不要只信宿主机 `ps`。** 从**不加载宿主机 `ld.so.preload` 的容器**读 `/proc` 和文件。
5. 宿主机 `chattr` 可能被隐藏库挡住;改 immutable 文件用 **Ubuntu/Alpine 自带 chattr** 操作 bind-mount 的 `/host/...`。
收集脚本(可选,先跑再解读):
```bash
bash <skill-dir>/scripts/collect.sh USER@HOST
```
`<skill-dir>` 是本 skill 目录。脚本只采集,不修改系统。
## 流程
按顺序做。每步记下「正常 / 可疑 / 未查到」。完整项见 [references/checklist.md](references/checklist.md)。
### 1. 快照
- 主机名、发行版、uptime、负载、`free -h`、`df -h`、公网/内网/Tailscale IP
- `ss -lntup`(最好 root)
- `docker ps -a`、compose 项目
- 若有 k3s/k8s:agent 是否在跑、能否 `kubectl get pods -A`
### 2. 入口
- sshd:`Port`、`PermitRootLogin`、`PasswordAuthentication`、`authorized_keys`(root 与所有 UID≥1000)
- `last` / `lastb` / `journalctl -u ssh`:异常登录;**无交互登录却出现 docker run 也是入口信号**
- sudoers、`docker` 组(= root)、NOPASSWD
- 对公网的管理面:Portainer / Cockpit / 面板 / k8s apiserver / Docker 端口,尤其 `-p 0.0.0.0:…` 且挂了 `docker.sock` 或 `/:/host`
- 单元文件或 compose 里的明文 token(k3s `--token`、agent secret)
### 3. 持久化
读 [references/persistence.md](references/persistence.md)。至少查:
- crontab(root 与所有用户)、`/etc/cron.*`
- `/etc/systemd/system/*.service`、timers
- `/etc/ld.so.preload`(用**外部** cat/hexdump,宿主机 cat 可能被藏空)
- `chattr +i` 的异常二进制(`lsattr`)
- 隐藏 Docker 数据根(非 `/var/lib/docker` 的 dockerd `--data-root`)
### 4. 进程与隐藏库
- 从特权容器列 `/proc/*/cmdline`(绕过 preload)
- 对照宿主机 `ps`:只在容器视角出现的进程 = 隐藏
- `/proc/*/maps` 是否映射陌生 `.so`(`libgcwrap`、`libprocesshider`、随机名)
- 矿机常见名:`perfcc`、`xmrig`、`kdevtmpfsi`、`javavm64`;同体积多副本(例如都是 11MB)
- hugepage:`grep Huge /proc/meminfo`。`nr_hugepages>0` 且进程列表对不上,多半是矿机预留
### 5. 容器与编排
- `docker ps -a`:镜像名含 earnfm / packetstream / repocket / traffmonetizer / honeygain / proxyrack / bitping / antgain 等挂机池
- inspect:`Privileged`、Binds(`docker.sock`、`/:/host`)、Ports 是否 `0.0.0.0`
- 第二套 dockerd / 异常 `--bridge`
- k8s:节点上是否有与 Git 仓库无关的 workload;控制面不健康时从 kubelet `pods/*/etc-hosts` 读 Pod 名
### 6. 对外暴露
- 本机 `0.0.0.0` / `[::]` 监听
- **从另一台机器探测公网 IP**(含 IPv6)。只看 `ss` 会漏安全组,只看安全组会漏「监听但没防火墙」
- 高危:`rpcbind :111`、明文 HTTP 应用端口、Docker/Portainer、k8s 6443、数据库
- 管理 SSH 若可走 Tailscale,公网 SSH 算多余攻击面
### 7. 资源与日志
- 无 swap + 高 hugepage → 应用易 OOM
- `journalctl` / `auth.log` 在处置时间点附近;日志空也要记
- 出站连接:`ss -tp` 看陌生 IP(不要把结果里的密钥打出来)
### 8. 补漏(本次 vvps2 没做或做得浅的)
见 checklist 后半:补丁、SUID、世界可写、意外用户、IPv6、定时器、内核模块、出站 C2、云安全组、备份是否可用。
## 报告格式
先给结论(是否沦陷、最可能入口、对外还开着什么),再给证据表,最后给 **需用户点头的处置清单**。不要默默清理。
```
结论: 沦陷 / 可疑 / 未见异常
最可能入口: …
对外端口: …
持久化: …
隐藏/矿机: …
容器/编排: …
未查项: …
建议处置: (等确认)
```
## 处置(仅在用户同意后)
原则见 [references/cleanup.md](references/cleanup.md)。
- 停并删除未授权容器;镜像也删
- 矿机二进制:删掉后用 **空文件 + `chattr +i` 占路径**
- 清空并锁定 `/etc/ld.so.preload`
- 关公网绑定:改成 `127.0.0.1` 或 Tailscale IP(若回源走 Tailscale 主机名,必须绑 TS IP,不能只绑 loopback)
- 停无用服务(如 `rpcbind.socket` + `rpcbind.service`,必要时 mask)
- 重启才能卸掉仍映射已删 `.so` 的老进程(sshd/dockerd)。先取证再重启
- 轮换:暴露过的 token、面板、k3s bootstrap。控制面 API 不通就不要假轮换,写阻塞原因
## 验证
- 公网探测:已关端口失败;该留的业务域名仍 200
- `ss`:无 `0.0.0.0:已关端口`
- `grep -l libgcwrap /proc/*/maps`(或同类库)重启后为 0
- 占位文件仍在且 immutable
- 业务容器 `restart: always` 仍在