一款尝试检测漏洞利用行为的进程监控工具
[!IMPORTANT] 新兴威胁:2026 年 10 月 21 日 14:00 UTC 发布关键 PHP 安全版本。 PHP 项目于 10 月 20 日发布了公告(公告):两个关键漏洞,均 被评为 CVSS v4.0 9.2。详细信息、受影响版本和修复程序将随该版本一同发布;如果细节 被公开或漏洞利用开始,该版本可能会提前发布。请立即准备更新 PHP。
公告未说明这些缺陷属于何种类型。如果攻击使 PHP 启动程序,process-watcher 会显示每个程序的命令行,并可选地终止你指定的程序。它并不查找这些缺陷:它 无法阻止任何攻击,也会漏掉在 PHP 内部运行而不启动进程的代码,因此它增加了一层检测, 而不能替代补丁。
从这里开始:使用 process-watcher 监控 PHP,或阅读 完整 PHP 指南。
看清服务启动了哪些程序。 process-watcher 实时跟踪一个服务(Web 服务器、应用服务器等)及其创建的
每一个进程,并将每次启动、程序变更和退出记录为 JSON,可选地包含命令行。当你的 Web 服务器突然运行 shell 或 curl 时,
你能看到启动了什么、由哪个进程启动、来自哪个服务。它是一个适用于 Linux(amd64、arm64)的单一静态二进制文件:下载、解压、运行。
它让活动变得可见;它不做判断。建立基线或判定何为攻击,由你
或接收事件的系统(日志文件、SIEM、webhook)决定。它还可以选择性地针对特定的子进程
执行定向 SIGKILL(终止规则)。
1. 下载并解压最新的 release(amd64 或
arm64,根据你的机器自动检测;归档文件名包含版本号,因此第二行会查找最新的 tag):
ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')
VERSION=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/Neo23x0/process-watcher/releases/latest | sed 's#.*/##')
curl -fsSLO https://github.com/Neo23x0/process-watcher/releases/download/$VERSION/process-watcher_${VERSION}_linux_${ARCH}.tar.gz
tar xzf process-watcher_${VERSION}_linux_${ARCH}.tar.gz && cd process-watcher_${VERSION}_linux_${ARCH}
2. 运行它,针对你想要监视的服务。它需要 root 权限以及支持 BTF 的 Linux 5.15 或更新版本;
sudo ./process-watcher doctor 会告诉你你的主机是否符合条件。
sudo ./process-watcher --watch-image-contains nginx --capture-argv=true
nginx 是服务可执行文件名称的子串(apache2、php-fpm、java 等)。使用
Ctrl-C 停止代理;它会将事件写入 ./process-watcher.jsonl。--capture-argv=true 会记录命令行,其中可能
包含机密信息(参数捕获)。更喜欢使用文件?编辑二进制文件旁边的 process-watcher.yaml
(它会被自动找到)并运行 sudo ./process-watcher。
3. 监视服务启动了什么(第二个终端,同一目录;jq 使 JSON 更易读):
sudo tail -f process-watcher.jsonl | jq -r '
select(.event_type=="process.exec" and .lineage.role=="descendant")
| "\(.timestamp[:19])Z \(.root.image) > \(.process.image) \(.process.argv // [] | join(" "))" | gsub("[[:cntrl:]]"; "?")'
示例:一个名为 nginx 的服务被设置为运行一个 shell 和几个程序(使用一个替代程序进行模拟):
2026-10-17T19:15:16Z nginx > dash sh -c id; uname -s
2026-10-17T19:15:16Z nginx > id id
2026-10-17T19:15:16Z nginx > uname uname -s
2026-10-17T19:15:16Z nginx > curl curl --version
2026-10-17T19:15:16Z nginx > sleep sleep 1
启动 shell、下载工具或解释器(sh、curl、wget、nc、python 等)的 Web 服务器或应用服务器,是 Web shell 或远程代码执行的典型痕迹。所有代际都会被跟踪,即使父进程已经结束。(jq 仅为了显示而拼接参数;事件仍将它们保留为数组。sh 显示为 dash,因为实际运行的程序是镜像。)
下一步: 将其作为 systemd 服务 持续运行 · 通过 --tcp-address、--udp-address 或 --webhook-url 将事件发送到你的 SIEM 或日志管道(输出) · 自动终止可疑的子进程(终止规则)。
| 要求 | 值 |
|---|---|
| 操作系统 | Linux,amd64 或 arm64 |
| 内核 | 5.15 或更新版本,且支持 BTF(/sys/kernel/btf/vmlinux)。仅凭版本号并不能保证:启动时代理会检查其所需的函数和内核结构字段。 |
| 权限 | root,或 CAP_BPF + CAP_PERFMON(对于其他用户进程的 /proc/<pid>/exe 需要 CAP_SYS_PTRACE,终止功能需要 CAP_KILL,内核 5.11 之前需要 CAP_SYS_RESOURCE)。内核锁定 confidentiality 会阻止运行。 |
| PID 命名空间 | 主机的初始 PID 命名空间(所有 PID 都是主机 PID);在容器内运行会被拒绝。 |
如果缺少某项要求,代理会以具体的诊断信息和退出码 3 停止;它绝不会回退到轮询 /proc,因为那样会漏掉短生命周期进程。sudo ./process-watcher doctor 会检查所有内容、加载程序并运行自己的探测进程。已测试的内核:docs/compatibility.md。
# in the directory the archive was downloaded to, with $VERSION and $ARCH from step 1
curl -fsSLO https://github.com/Neo23x0/process-watcher/releases/download/$VERSION/SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMS
gh attestation verify process-watcher_${VERSION}_linux_${ARCH}.tar.gz --repo Neo23x0/process-watcher # build provenance
每个归档都包含单个静态二进制文件(eBPF 程序已嵌入;运行时无需其他任何东西)、带注释的示例配置 process-watcher.yaml、LICENSE,在 php/ 下包含 emerging-threats/ 中 PHP kit 的两个配置,可直接使用(process-watcher --config php/php-observe.yaml),以及在 packaging/ 中包含 systemd unit 及其安装脚本。仅提供 amd64 和 arm64:eBPF 采集器假定使用 64 位内核指针,因此不支持 32 位内核(x86、ARM)。
从解压后的归档中:
sudo ./packaging/install.sh ./process-watcher # binary, configuration and unit; starts nothing
sudoedit /etc/process-watcher/config.yaml # adjust the watch list
sudo process-watcher doctor
sudo systemctl enable --now process-watcher
详情、从仓库克隆安装以及该单元设置的原因: packaging/INSTALL.md。在没有 systemd 的情况下,复制二进制文件并以 root 权限启动它。
# Log file elsewhere, remote outputs and an exclusion
sudo ./process-watcher --watch-image-contains nginx --exclude-image-contains legitimate-helper \
--log-file /var/log/process-watcher/events.jsonl \
--tcp-address collector.example.net:9000 --udp-address 192.0.2.20:9001 \
--webhook-url https://collector.example.net/hooks/processes
# YAML plus overriding single values
sudo ./process-watcher --config /etc/process-watcher/config.yaml \
--watch-image-contains nginx --watch-image-contains apache2 --capture-argv=true
# Without root, without observation or network access
./process-watcher check-config --config ./process-watcher.yaml
./process-watcher print-config --config ./process-watcher.yaml
# React to child processes (see Kill rules)
sudo ./process-watcher --watch-image-contains nginx --capture-argv=true --kill-enabled=true \
--kill-field image --kill-field argv --kill-string demo-long-running-helper \
--kill-regex '^(useradd|usermod)$'
示例配置位于 examples/;每个配置都由测试中的严格加载器进行检查。用于试验的简单接收器(仅使用 Python 3 标准库)位于 examples/receivers/;nc -lk 9000(TCP)和 nc -lu 9001(UDP)足以进行初步尝试。
| 命令 | 作用 |
|---|---|
run(默认) | 开始观测。即使当前没有匹配的进程在运行也会等待。 |
check-config | 校验配置。不附加任何 BPF 程序、不创建文件、不联系任何端点,并且从不发送信号,即使存在活动的 kill 规则也是如此。 |
print-config | 输出解析后的配置(YAML)及其源文件。不含机密:对于 bearer token 仅显示变量名,对于 webhook URL 仅显示 scheme 和 host。 |
doctor | 检查要求和权限(见上文)。 |
--help、--version | 显示所有标志、默认值和 YAML 键的帮助;显示版本。 |
| 退出码 | 含义 |
|---|---|
0 | 成功,收到 SIGINT/SIGTERM 时同样如此 |
1 | 运行时错误,包括本地日志不可写 |
2 | 配置或用法错误 |
3 | 不支持的平台或缺少采集器要求 |
运行诊断信息输出到 stderr;对于 run,stdout 保持为空。
只加载一个 YAML 文件(文件从不合并)。搜索顺序:--config <path>(必须存在且可读)、工作目录中的 process-watcher.yaml、真实二进制文件旁边的 process-watcher.yaml(会解析符号链接)、内置默认值。找到但无效的文件属于错误,绝不会被跳过。优先级:默认值 < YAML < 显式设置的标志;环境变量不是配置层(只读取 token_env 指定的变量)。相对文件路径相对于调用的工作目录,即使它们来自 YAML 也是如此。加载是严格的:未知或重复的键、错误的类型、空值、别名和多个文档都会被拒绝,config_version: 1 是必需的,错误信息会指明文件、行号和键路径(例如 kill.regex[2])。