sercanokur/GhostCatcherEDR

GitHub: sercanokur/GhostCatcherEDR

一款使用 Go 编写的轻量级 Linux 端点检测代理,通过多源传感器和可扩展的规则引擎,专注于发现主机层面的持久化控制、Webshell 及异常进程行为,并无缝对接各类 SIEM 系统。

Stars: 6 | Forks: 0

# GhostCatcher (端点代理) 一个使用 **Go** 编写的 **Linux 端点**检测代理。它可以作为 CLI 或 **systemd** 服务运行,定期扫描主机,从运行时选择的 **eBPF / auditd / /proc** 传感器获取数据流,通过 **fsnotify** 监控敏感路径,并在标准输出以及任何已配置的企业级输出端(UDP/TCP/TLS syslog、Splunk HEC、Elastic `_bulk`、Grafana Loki)上逐行发出 **单个 JSON 对象**。 GhostCatcher 针对的是与常见入侵模式相吻合的 **主机可见** 行为 —— Web shell、`LD_PRELOAD` 劫持、SSH/cron/systemd 持久化、PAM/sudoers 篡改、SUID / 文件能力偏移、反向 shell、反射加载 —— 使用了**基线**、**多信号评分**、**签名规则包** (ed25519)、**时间窗口关联**、**CEL 风格的布尔表达式**、**Sigma-lite** 规则插入、**YARA**(可选的 cgo 构建标签)、**PHP 污点流微型解析器**、**IOC 源**和**容器上下文**。 ## 使命 高级 **APT** 组织越来越将 Linux 视为首要目标:这与在其他平台上*就地取材*的战略思路相同 —— 滥用**内置工具、合法服务和常规管理路径**,从而使活动融入日常操作。Linux 通常支撑着**数据库、Web 前端以及云和平台控制平面**,因此对于这些攻击者来说,反复出现的优先事项是**长期持久化**(在补丁更新和重启后存活的隐蔽立足点)以及**低噪音收集或数据渗漏**,且不依赖于特征明显的恶意软件家族。 GhostCatcher 的存在是为了**缩短**这些行为在主机上未被察觉的**时间窗口**:Web 层后门、基于预加载的规避、对 `authorized_keys` 和作业调度器的信任窃取,以及 **IDS** 或边界工具可能只能间接推断的相关本地信号。它是一个**开放的、可审查的**层,团队可以根据自己的环境进行调整并将其接入 SIEM —— 对 IDS、EDR 类技术栈和狩猎程序起到**补充作用**,而不是取代整个杀伤链中的深度防御。 ## 目录 - [使命](#mission) - [功能](#features) - [检测内容(摘要)](#what-it-detects-summary) - [系统要求](#requirements) - [构建](#build) - [持续集成](#continuous-integration) - [快速开始](#quick-start) - [在服务器上安装(生产环境)](#install-on-a-server-production) - [配置清单](#configuration-checklist) - [SIEM 集成 (syslog / HEC / bulk / Loki)](#siem-integration-syslog--hec--bulk--loki) - [停止或禁用服务](#stop-or-disable-the-service) - [配置](#configuration) - [规则包](#rule-pack) - [输出格式](#output-format) - [权限说明](#privileges) - [项目结构](#project-layout) - [局限性](#limitations) - [贡献指南](#contributing) - [许可证](#license) - [安全说明](#security) ## 功能 ### 检测面 | 区域 | 机制 | |------|-----------| | **Web shell / PHP 风格模式** | 针对PHP / JSP / ASPX / ColdFusion / Perl的 30 多种正则表达式模式,在规范化传递(注释剥离、`"ev"."al"` 拼接折叠、递归内联 base64 解码)之后运行。确证信号:**Shannon 熵**、**魔术字节/多态不匹配**、**SUID/SGID** 以及 `www-data`/`apache` 所有权,微小高信号启发式。 | | **PHP 污点流** | 过程内词法分析器,跟踪从 `$_GET` / `$_POST` / `$_REQUEST` / `$_COOKIE` / `$_SERVER` / `php://input` 到危险汇函数(`eval`、`assert`、`system`、`exec`、`shell_exec`、`proc_open`、`preg_replace`/e、`include` 等)的赋值。 | | **Web worker 下的侦察子进程** | 标记在 `nginx` / `apache2` / `php-fpm` / `tomcat` 下派生的 `whoami`、`ifconfig`、`uname`、`id`、`curl` 等命令。 | | **无文件 / 内存暗示** | `/proc/[pid]/maps`:带有 `/dev/shm`/`/tmp` 路径、`(deleted)` 执行段、`TracerPid` 偏移、`CapEff` 提权的 RWX 支持区域,以及在提交时已建立基线的**每进程共享对象允许列表**。 | | **`LD_PRELOAD` / 预加载文件** | `/etc/ld.so.preload` 和 `/proc/[pid]/environ` 中的 `LD_PRELOAD`;配置中的允许列表。 | | **SSH 持久化** | `~/.ssh/authorized_keys` 指纹增量、无效行异常、`sshd_config` / `sshd_config.d` 增量(`PermitRootLogin`、`AuthorizedKeysCommand`、`ForceCommand`)。 | | **Cron 持久化** | `/etc/crontab`、`/etc/cron.{hourly,daily,weekly,monthly,d}`、`/etc/anacrontab`、`/var/spool/cron/…`、`/var/spool/atjobs`。Token 经规范化处理(剥离引号的 shlex)并在风险匹配(`curl`、`bash -c`、`/dev/tcp/`、`nc`、`base64 -d` 等)前**递归解码 base64 payload**。 | | **systemd 持久化** | 新增或更改的 `*.service` / `*.timer` 单元;标记危险的 `ExecStart*` + `User=root` 组合。 | | **Shell / profile / PAM / sudoers** | `~/.bashrc` / `~/.zshrc` / `/etc/profile` 增量 + 高危 token;`/etc/pam.d/*` 及模块引用(`pam_exec.so`、`pam_python.so`);`/etc/sudoers` + `/etc/sudoers.d/*` 危险指令。 | | **用户** | `/etc/passwd` / `/etc/shadow`:UID 为 0 的非 root 账户、新增账户、空密码哈希。 | | **内核模块** | `/proc/modules` 增量 + `/etc/modules-load.d`、`/etc/modprobe.d` 插入配置更改。 | | **动态链接器** | `ld.so.conf` 和 `ld.so.conf.d` 修改,尤其是全局可写的添加项。 | | **二进制完整性 (Debian/Ubuntu + RHEL/CentOS/Fedora)** | 通过 `/etc/os-release` 自动调度:针对监控的关键路径执行 **dpkg md5sums** 或 **`rpm -Va`**;TOCTOU 安全(fd 锁定的哈希处理)。 | | **SUID / capabilities 偏移** | 遍历类似 `$PATH` 的目录;对新的 SUID/SGID 二进制文件、哈希更改、全局可写路径上的 SUID 以及 `security.capability` xattr 的更改发出警报。 | | **进程祖先 (`PROC_RARE_ANCESTRY`)** | 标记未见过的 `(parent_comm, child_comm)` 对,其中父进程是高价值目标(`nginx`、`sshd`、`mysqld`、`cron` 等)而子进程是 `sh`/`bash`/`nc`/`curl` 等。在提交时建立基线。 | | **网络传感器** | `/proc/net/tcp[6]` + `/proc/net/udp[6]` 与 `/proc/*/fd` inode 相关联,以检测**反向 shell**(类 shell 的到公网 IP 的出站连接)、**意外的监听**以及 **Web worker 出站流量**;由 CIDR 允许列表驱动。 | | **实时监控器** | 在 `authorized_keys`、`ld.so.preload`、crontab + `cron.d`、systemd 单元目录、`sudoers.d`、`pam.d`、`sshd_config.d`、`document_roots`(递归)、`passwd`、`shadow` 上运行 `fsnotify` —— 变更时防抖重新扫描。 | | **Exec 传感器** | 运行时选择后端:**eBPF**(`-tags with_ebpf`,cilium/ebpf;exec/openat/connect/ptrace/init_module/memfd) → **auditd** tail(`/var/log/audit/audit.log`,无 libaudit 依赖) → **/proc poll** 回退。 | | **YARA** | 可选的 `-tags with_yara` 构建(hillu/go-yara/v4):跨文档根目录的磁盘扫描以及针对受监控 comm 的实时进程内存扫描。 | | **IOC 源加权** | 在发出事件时交叉引用平面文件哈希 / IP / CIDR / 域名源;网络 IOC 命中增加 +25 置信度,文件哈希命中增加 +10。 | | **容器上下文** | 从 `/proc/[pid]/cgroup` 分类 Docker / containerd / cri-o / k8s / lxc ID 和 Pod UID。 | ### 引擎 | 区域 | 机制 | |------|-----------| | **规则引擎 v2** | 每个规则可以带有一个布尔 **CEL 风格表达式**(`signal("…") and confidence >= 70`、`comm in ["sh","bash"]`、`matches(entity_path, "^/tmp/.*\\.so$")`、`contains`、`not`、`and/or`)。返回 false 的表达式会将事件降级为 `learning_only`,而不是触发警报。 | | **时间窗口关联** | 规则声明 `correlate:` 对等项 + `correlate_window`;窗口内同一实体的事件获得可配置的置信度提升和 `correlation_boost` 信号。 | | **Sigma-lite 加载器** | 将 `*.yml` Sigma 文件放入 `sigma_lite_dir` 目录下;一个子集(`selection` + `condition: selection`,`contains` / `endswith` / `startswith` / `re`)在加载时被转译为原生表达式。 | | **签名规则包** | 可选的 ed25519 分离签名(`rule_pack_pubkey_file` + `rule_pack_signature_file`);不匹配时加载会闭锁失败。 | | **速率限制器 + 磁盘假脱机** | 每规则滑动窗口上限(`rate_limit_per_rule_per_min`)+ 针对暂时不可达输出端的换行符分隔的 JSON 假脱机;在 `spool_max_bytes` 时自动轮转。 | | **隔离保管库** | 将高置信度文件工件复制到 `//.bin`(模式 0400),并带有一个副档 JSON(规则、信号、原始模式 / mtime / 所有者)。 | | **自我防护** | 定期 sha256 检查代理二进制文件(发生偏移时触发 `AGENT_TAMPERED` 严重事件)+ 使用 `WATCHDOG_USEC` 发送 systemd `WATCHDOG=1` 通知。 | | **基线提交 2FA** | 从 `baseline_commit_token_env` 读取的可选 token;`baseline commit -token ` 必须在覆盖前匹配。 | ### 输出端 | 传输方式 | 备注 | |-----------|-------| | stdout JSONL | 始终启用。 | | **UDP syslog** | RFC5424 或 RFC3164,可配置 facility / PRI。 | | **TCP / TLS syslog** | RFC5425 八位字节帧;可选的 CA 证书 + SNI;传输错误时单次重试。 | | **Splunk HEC** | 带有 `sourcetype` / `index` 的 `POST {"event": …}`。 | | **Elasticsearch `_bulk`** | NDJSON 上传,API key 或基本认证。 | | **Grafana Loki** | 带有静态 + 每事件标签(`rule_id`、`severity`)的 `/loki/api/v1/push`。 | 所有输出端实现了一个通用的 `Sink` 接口;任何失败都会将原始 JSON 行路由到假脱机队列中。 基线存储为 JSON(`baseline commit`)。警报遵循 **`min_confidence_for_alert`** 和 **`learning_mode`**,直到您冻结基线。 ## 检内容(摘要) 规则在 YAML **规则包**中定义;每个发出的事件都包含 `technique_id`(MITRE 风格 ID)和 `rule_id。附带的规则涵盖: - **T1505.003** / **T1059.004** / **T1059.006** —— Web shell、Worker 子进程、侦察参数 (argv)、反向 shell 派生。 - **T1574.006** / **T1014** —— `LD_PRELOAD`、`ld.so.preload`、Rootkit 风格的内核模块。 - **T1098.004** / **T1136.001** —— 新的授权密钥指纹、新的本地用户、UID-0 账户。 - **T1053.003** / **T1053.006** —— cron + systemd 计时器增量,带有已解码的 base64 payload。 - **T1055** / **T1055.001** / **T1620** —— RWX 映射、`(deleted)` 执行段、反射加载。 - **T1036** —— 受监控二进制文件的 md5 / rpm 不匹配。 - **T1556.003** / **T1548.003** —— PAM 模块、sudoers 提权路径。 - **T1562.001** —— 代理二进制文件被篡改(`AGENT_TAMPERED`)。 - **T1571** / **T1041** / **T1071.001** —— 意外监听、Web worker 出站流量、反向 shell 出站。 每个规则的确切评分、`min_signals`、关联窗口和布尔表达式位于 [`configs/rule_pack.example.yaml`](configs/rule_pack.example.yaml) 中。 ## 系统要求 - **Go** 1.22 或更新版本(参见 [`go.mod`](go.mod))。 - **运行环境:** Linux。完整性后端会根据 `/etc/os-release` 在 `dpkg` (Debian/Ubuntu) 和 `rpm` (RHEL/CentOS/Fedora) 之间自动选择。 - **可选 (cgo):** [YARA ≥ 4.3](https://virustotal.github.io/yara/) 头文件和库以启用 `-tags with_yara`。 - **可选 (内核):** Linux ≥ 5.8 且带有 `CONFIG_BPF_SYSCALL=y` 和 `CAP_BPF` / root 权限以启用 `-tags with_ebpf`。不可用时将回退到 `auditd`,然后回退到 `/proc` 轮询。 - **建议:** 以 **root** 身份运行,以获得跨用户和 PID 的完整 `/proc` 可见性(参见 [权限说明](#privileges))。 ## 构建 默认构建(纯 Go,无 cgo,无内核依赖 —— 也可在 macOS 上运行以进行测试): ``` git clone https://github.com//GhostCatcherEntpointDetection.git cd GhostCatcherEntpointDetection go build -o ghostcatcher ./cmd/agent ``` 可选的构建标签(可组合使用): ``` # YARA 磁盘 + 内存扫描器 (需要 libyara 头文件) CGO_ENABLED=1 go build -tags with_yara -o ghostcatcher ./cmd/agent # eBPF exec / openat / connect / ptrace / init_module / memfd 传感器 go build -tags with_ebpf -o ghostcatcher ./cmd/agent # 两者皆是 CGO_ENABLED=1 go build -tags "with_yara with_ebpf" -o ghostcatcher ./cmd/agent ``` 运行测试和检测质量线束: ``` go test ./... go run ./cmd/agent eval -corpus testdata/eval -min-f1 0.85 ``` ## 持续集成 [![CI](https://github.com/OWNER/REPO/actions/workflows/ci.yml/badge.svg)](https://github.com/OWNER/REPO/actions/workflows/ci.yml) 在每次向 `main` / `master` 的 **push** 和 **pull request**(以及用于发布的标签 push)时,[GitHub Actions](.github/workflows/ci.yml) 会运行: - `go mod verify`、`go build`、`go vet ./...`、`go test -race ./...` - 针对配置文件 [`configs/config.example.yaml`](configs/config.example.yaml) 运行 `ghostcatcher check-config` - `ghostcatcher eval -corpus testdata/eval -min-f1 0.85` —— 如果检测精度/召回率降至配置的 F1 阈值以下,则会使构建失败 - 由 [`.golangci.yml`](.golangci.yml) 驱动的 **[golangci-lint](https://golangci-lint.run/)** - **[gosec](https://github.com/securego/gosec)** 静态分析 - **[govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)** 漏洞数据库 - **[syft](https://github.com/anchore/syft)** —— 作为 CI 工件上传的 SPDX SBOM - **[cosign](https://github.com/sigstore/cosign)** 在标签 push 时对发布二进制文件进行 Blob 签名(无密钥 OIDC) 将上面徽章 URL 中的 **`OWNER/REPO`** 替换为您的 GitHub 组织和仓库名称,以便在第一次工作流运行后状态图像能够正确解析。 ## 快速开始 1. 复制并编辑配置: cp configs/config.example.yaml configs/config.yaml # 根据您的主机设置 document_roots、baseline_path、rule_pack_path。 2. 验证配置和规则包: ./ghostcatcher check-config -config configs/config.yaml 3. **首次基线**(在您信任当前主机状态之后): sudo ./ghostcatcher baseline commit -config configs/config.yaml 4. 运行单次扫描: sudo ./ghostcatcher run -config configs/config.yaml -once 5. 持续运行(根据 `scan_interval` 设置间隔;同时启动实时传感器和 fsnotify 监控器): sudo ./ghostcatcher run -config configs/config.yaml 6. 根据附带(或您自己的)标记语料库对您的规则包进行回归测试: ./ghostcatcher eval -corpus testdata/eval -min-f1 0.85 **systemd** 单元示例:[`systemd/ghostcatcher.service`](systemd/ghostcatcher.service)。如果您希望 `selfguard` 看门狗循环保持服务存活,请在单元上设置 `Type=notify` 和 `WatchdogSec=`。 ## 在服务器上安装(生产环境) Ubuntu/Debian 上的典型布局: | 路径 | 用途 | |------|---------| | `/usr/local/bin/ghostcatcher` | 二进制文件 | | `/etc/ghostcatcher/config.yaml` | 主 YAML 配置 | | `/etc/ghostcatcher/rule_pack.yaml` | 规则包(从 `configs/rule_pack.example.yaml` 复制并根据需要进行调整) | | `/var/lib/ghostcatcher/` | 状态目录(通过 `baseline_path` 指定的 `baseline.json`) | **步骤** 1. 在构建主机上**构建**(或为 `linux/amd64` 交叉编译),然后安装二进制文件: sudo install -m 0755 ghostcatcher /usr/local/bin/ghostcatcher 2. **创建目录并复制配置:** sudo mkdir -p /etc/ghostcatcher /var/lib/ghostcatcher sudo cp configs/config.example.yaml /etc/ghostcatcher/config.yaml sudo cp configs/rule_pack.example.yaml /etc/ghostcatcher/rule_pack.yaml sudo chmod 0640 /etc/ghostcatcher/config.yaml /etc/ghostcatcher/rule_pack.yaml 3. **编辑** `/etc/ghostcatcher/config.yaml`(参见 [配置清单](#configuration-checklist))。至少设置: - `baseline_path` → 例如 `/var/lib/ghostcatcher/baseline.json` - `rule_pack_path` → `/etc/ghostcatcher/rule_pack.yaml` - `document_roots` → 此主机上真实的 Web 根目录 - 如果您通过 SIEM 接收日志,请配置 `syslog_udp` 4. **验证:** sudo ghostcatcher check-config -config /etc/ghostcatcher/config.yaml 5. 当主机处于已知良好状态时建立**基线**: sudo ghostcatcher baseline commit -config /etc/ghostcatcher/config.yaml 6. **systemd** —— 如果您的路径不同,请调整 [`systemd/ghostcatcher.service`](systemd/ghostcatcher.service),然后执行: sudo cp systemd/ghostcatcher.service /etc/systemd/system/ghostcatcher.service sudo systemctl daemon-reload sudo systemctl enable ghostcatcher.service sudo systemctl start ghostcatcher.service sudo systemctl status ghostcatcher.service 7. **日志** —— 默认情况下,JSON 事件会输出到 **stdout**(由 journald 捕获)。使用 `journalctl -u ghostcatcher -f` 进行查看。来自代理的操作消息会输出到 **stderr**。 ## 配置清单 针对**您的**服务器和 SOC 工作流自定义这些内容: ### 必须设置(几乎所有的部署) | 设置项 | 原因 | |---------|-----| | `document_roots` | 列出您希望扫描 PHP/JSP 的每个 Web 根目录(nginx/Apache `root` / `DocumentRoot`)。错误或为空的路径 = 遗漏 Web shell 覆盖范围。 | | `baseline_path` | 持久化路径(例如在 `/var/lib/ghostcatcher/` 下)。`baseline commit` 后进行稳定增量检测所必需。 | | `rule_pack_path` | 指向您发布的 YAML(例如 `/etc/ghostcatcher/rule_pack.yaml`)。 | ### 强烈建议设置 | 设置项 | 原因 | |---------|-----| | `scan_interval` | 平衡 CPU/负载与检测延迟(例如生产环境 `5m`,激进点设为 `1m`)。 | | `min_confidence_for_alert` | 通过您的规则包调整噪音与信号(默认 `70`;如果太吵杂则调高)。 | | `path_allowlist_prefixes` | 排除会触发 PHP 启发式扫描的 vendor/CMS 目录树(`vendor/`、框架缓存)。 | | `ld_preload_allowlist` | 如果您使用了性能分析或安全封装,请添加合法的 `LD_PRELOAD` 片段。 | | `syslog_udp` / `syslog_tcp` / `splunk_hec` / `elastic_bulk` / `loki_push` | 启用一个或多个输出端块,以便事件到达您的 SIEM。 | | `require_root: true` | 强制以 root 身份运行,如果未获得完整的 `/proc` 覆盖范围,代理会快速启动失败。 | | `rule_pack_pubkey_file` + `rule_pack_signature_file` | 在生产环境中拒绝加载未签名/被篡改的规则包。 | | `selfguard.binary_path` + `selfguard.expected_sha256` | 开启代理自我完整性检查;与单元文件中的 `Type=notify` + `WatchdogSec=` 配合使用。 | ### 可选 / 特定环境设置 | 设置项 | 何时使用 | |---------|------| | `maps_scan_enabled` | Linux Web 服务器;预可能会出现误报 —— 测试后请使用 `maps_path_allowlist_prefixes`。 | | `integrity_verify_enabled` | 从 `/etc/os-release` 自动调度至 `dpkg` 或 `rpm`;在其他发行版上会被静默跳过。 | | `watch_authorized_keys`` | 对 `authorized_keys` 的编辑反应更快;需要可读的 `.ssh` 目录。 | | `learning_mode` | 试用期间设为 `true`;在信任基线和阈值后设为 `false`。 | | `first_run_allow_alerts` | 通常为 `false`;仅当您在首次 `baseline commit` 之前明确需要高严重性警报时才开启。 | | `sigma_lite_dir` | 将用于外部检测的 Sigma YAML 文件与原生规则包一起放入该目录。 | | `yara_rules_dir` + `yara_memory_enabled` | 仅在使用 `-tags with_yara` 构建时生效。 | | `ancestry_scan_enabled` | 启用针对已建立基线的进程图的 `PROC_RARE_ANCESTRY` 检测。 | | `ioc_feed_dir` | 平面文件形式的哈希 / IP / CIDR / 域名列表,用于在匹配时加权置信度。 | | `quarantine_dir` + `quarantine_min_confidence` | 存储带有元数据副件的高置信度文件工件副本。 | | `rate_limit_per_rule_per_min` + `spool_dir` + `spool_max_bytes` | 限制每规则的发出速率,并在输出端不可用时缓冲事件。 | | `baseline_commit_token_env` | 为 `baseline commit` 开启双重验证 (2FA);CLI 要求提供 `-token $VAR`。 | 在任何更改之后:运行 `sudo ghostcatcher check-config -config /etc/ghostcatcher/config.yaml`,然后执行 `sudo systemctl restart ghostcatcher`(如果使用 systemd)。 ## SIEM 集成 (syslog / HEC / bulk / Loki) 代理可以将**相同的 JSON 事件**发送到 **stdout** 以及任何企业级输出端的组合。所有的输出端都是按需启用且相互独立的;如果某个输出端失败,原始 JSON 行将被追加到磁盘上的假脱机队列中,并在下一次成功写入时重试。 ### 输出端摘要 | 输出端 | 配置块 | 传输方式 | Payload | |------|--------------|-----------|---------| | UDP syslog | `syslog_udp` | UDP | RFC5424 / RFC3164 头 + MSG 中的 JSON | | TCP / syslog | `syslog_tcp` | TCP,可选 TLS | RFC5425 八位字节计数帧 | | Splunk HEC | `splunk_hec` | HTTPS | `POST /services/collector`,`{"event": …, "sourcetype", "index"}` | | Elasticsearch | `elastic_bulk` | HTTPS | `POST /_bulk` NDJSON,可配置的 `index` | | Grafana Loki | `loki_push` | HTTPS | 带有静态 + 每事件标签(`rule_id`、`severity`)的 `POST /loki/api/v1/push` | ### UDP syslog 配置块示例 ``` syslog_udp: enabled: true host: siem-collector.internal port: 5514 format: rfc5424 facility: local0 app_name: ghostcatcher hostname: web-prod-01 max_msg_bytes: 8192 ``` ### TCP/TLS syslog 配置块示例 ``` syslog_tcp: enabled: true address: siem-collector.internal:6514 tls: true ca_file: /etc/ghostcatcher/ca.pem server_name: siem-collector.internal app_name: ghostcatcher ``` ### Splunk HEC / Elastic / Loki 配置块示例 ``` splunk_hec: enabled: true url: https://splunk.internal:8088/services/collector token: "${SPLUNK_HEC_TOKEN}" sourcetype: ghostcatcher:event index: security elastic_bulk: enabled: true url: https://es.internal:9200 index: ghostcatcher-events api_key: "${ES_API_KEY}" loki_push: enabled: true url: https://loki.internal/loki/api/v1/push tenant_id: security static_labels: job: ghostcatcher env: prod ``` ### 收集端清单 1. 选择上面的一个或多个输出端,并在您的 SIEM / 中继服务器上开放相应的入口。 2. 对于 syslog,请将 **MSG** 字段解析为 JSON(在 RFC5424/5425 头部之后)。 3. 对于 HEC / Elastic / Loki,正文已经是 JSON;不需要额外的解析器。 4. 如果事件被截断,请提高 **`max_msg_bytes`**;UDP 受 MTU 限制,对于大型事件请首选 TCP/TLS 或 HTTPS 输出端。 ### 如果您不使用任何输出端 将 **journald** 或日志传输器指向服务标准输出(JSON 行)并在那里解析 JSON —— payload 结构与每个输出端正文中的相同。 ## 停止或禁用服务 ### systemd(推荐) ``` # 立即停止 (不会禁用开机启动) sudo systemctl stop ghostcatcher.service # 停止并禁用后续启动 sudo systemctl disable --now ghostcatcher.service # 可选:在 unmask 前阻止任何启动 sudo systemctl mask ghostcatcher.service # 稍后取消 mask: # sudo systemctl unmask ghostcatcher.service ``` 检查其是否处于非活动状态: ``` sudo systemctl status ghostcatcher.service ``` ### 前台 / 手动 `run` 如果您是在终端中手动启动的代理: - 按下 **Ctrl+C** (SIGINT) 退出循环。 - 或者从另一个 shell 中运行:`sudo pkill -f 'ghostcatcher run'`(在共享主机上请谨慎使用;建议匹配完整的命令行)。 ### 停止后 - 配置和**基线**文件将保留在磁盘上;只是不再运行扫描。 - 要卸载该软件:停止/禁用该单元,删除 `/usr/local/bin/ghostcatcher`,并移除 `/etc/ghostcatcher/` 以及(可选)移除 `/var/lib/ghostcatcher/`(如果您不再需要基线)。 ## 配置 主要选项位于 YAML 中。有关所有键,请参见 [`configs/config.example.yaml`](configs/config.example.yaml),包括: | 键名 | 用途 | |-----|---------| | `scan_interval` | `run`(非 `-once`)的定时周期。 | | `document_roots` | 用于遍历查找 `.php` / `.jsp` / `.jspx` / `.aspx` / `.ashx` / `.phar` / `.cfm` / `.inc` 的 Web 根目录。 | | `baseline_path` | JSON 快照路径。 | | `rule_pack_path` | YAML 规则 + 表达式 + 关联元数据。 | | `rule_pack_pubkey_file` / `rule_pack_signature_file` | ed25519 分离签名验证。 | | `sigma_lite_dir` | 合并到规则包中的 Sigma-lite `*.yml` 插入文件目录。 | | `min_confidence_for_alert` | 视为生产警报的最低 `confidence`(仍以 JSON 形式发出;可能会应用 `learning_only`)。 | | `learning_mode` / `first_run_allow_alerts` | 学习工作流开关。 | | `require_root` | 为 true 时,如果不是 UID 0 则退出。 | | `maps_scan_enabled` / `maps_watch_processes` / `maps_path_allowlist_prefixes` | `/proc/maps` 启发式配置。 | | `integrity_verify_enabled` / `integrity_paths` | 带有自动调度的 `dpkg` / `rpm` 验证。 | | `web_recon_child_scan_enabled` | Web worker 下的侦察 argv。 | | `watch_authorized_keys` | 启用针对敏感路径的 fsnotify 监控器。 | | `ancestry_scan_enabled` | 发出 `PROC_RARE_ANCESTRY` 事件。 | | `yara_rules_dir` / `yara_memory_enabled` | 仅在使用 `-tags with_yara` 时生效。 | | `ioc_feed_dir` | 包含哈希 / IP / CIDR / 域名指标的平面文件。 | | `quarantine_dir` / `quarantine_min_confidence` | 基于文件的高置信度检测的证据保管库。 | | `rate_limit_per_rule_per_min` / `spool_dir` / `spool_max_bytes` | 每规则的速率限制和磁盘支持的假脱机。 | | `selfguard.binary_path` / `selfguard.expected_sha256` / `selfguard.check_interval` | 代理自我完整性 + systemd 看门狗。 | | `baseline_commit_token_env` | 包含 `baseline commit` 双重验证 (2FA) token 的环境变量名。 | | `syslog_udp`、`syslog_tcp`、`splunk_hec`、`elastic_bulk`、`loki_push` | 嵌套的输出端块(参见 SIEM 部分)。 | | `ld_preload_allowlist`、`path_allowlist_prefixes`、`network_allow_cidrs` | 减少误报。 | ## 规则包 规则包是版本化的(`version` 字段),并定义了每个规则的 `id`、MITRE `techniques`、`min_signals`、评分权重、可选的布尔 `expr` 表达式,以及带有 `correlate_window` / `correlate_boost` 的可选 `correlate` 对等项。将其放置在二进制文件旁边或 `/etc/ghostcatcher/` 下,并用 `rule_pack_path` 指向它。 表达式微型语言: ``` signal("WEB_SHELL_PATTERN") and confidence >= 70 comm in ["sh","bash","nc"] and not parent_comm in ["systemd","init"] matches(entity_path, "^/tmp/.*\\.so$") contains(evidence.cmdline, "base64 -d") ``` 签名规则包 (ed25519): ``` # 一次性操作:生成你将分发的密钥对 openssl genpkey -algorithm Ed25519 -out rulepack.key openssl pkey -in rulepack.key -pubout -outform DER \ | tail -c 32 | base64 > /etc/ghostcatcher/rulepack.pub # 在每次更改 /etc/ghostcatcher/rule_pack.yaml 时 openssl pkeyutl -sign -inkey rulepack.key \ -in /etc/ghostcatcher/rule_pack.yaml \ -out /etc/ghostcatcher/rule_pack.yaml.sig ``` 然后在代理配置中设置 `rule_pack_pubkey_file` + `rule_pack_signature_file`;不匹配时加载闭锁失败。 ## 输出格式 每个发出的检测都会作为单个 JSON 对象写入 **stdout**,并(除了传输层级的帧处理外,不加修改地)转发到每个已启用的输出端。稳定的字段(Schema **1.1**): - 身份信息:`schema_version`、`agent_version`、`rule_pack_version`、`timestamp`、`rule_id`、`technique_id`、`tactic`、`severity`、`confidence`、`correlation_id`、`learning_only`、`dedup_key`。 - 实体信息:`entity`(类型 + 路径 / comm / pid / network 元组)。 - 上下文对象:`process`(pid、ppid、comm、exe、args、uid、euid、caps、ancestors)、`file`(hash、size、mode、owner、mtime)、`network`(本地/远程 IP + 端口、family、state、inode)、`container`(runtime、id、pod_uid、image、namespace)。 - 匹配信息:`signals[]`、`evidence{}`、`ioc_matches[]`。 通过管道传输到您的日志技术栈或 `jq`: ``` sudo ./ghostcatcher run -config configs/config.yaml -once | jq . ``` 来自 CLI 的操作消息使用 **stderr**(例如 `check-config`、基线提交日志、传感器后端选择)。 ## 权限说明 - **Root:** 完整覆盖其他用户的 `authorized_keys`、所有 PID 的 `environ` / `maps` / `fd`、`/proc/net/*` ↔ inode 映射、内核模块枚举以及系统级 cron / systemd 路径。eBPF 和 `CAP_BPF` 挂载所必需。 - **非 root:** 部分可见(自己的进程、自己的主目录);许多检查会降级或丢失数据。 - **完整性模块:** 需要 `/var/lib/dpkg` 或 `rpm` CLI;在两者都不存在的发行版上会被静默跳过。 ## 项目结构 ``` . ├── cmd/agent/ # CLI entrypoint (run | -once | baseline | check-config | eval) ├── configs/ # Example config + rule pack ├── .github/workflows/ # CI (build, vet, test, eval, golangci-lint, gosec, govulncheck, syft, cosign) ├── internal/ │ ├── baseline/ # JSON snapshot load/save (web files, keys, cron, ancestry, SUID, xattrs, kmods, .so inventory, …) │ ├── config/ # YAML configuration with all sink + self-guard blocks │ ├── detect/ │ │ ├── web/ # Regex + normalization + entropy + magic + PHP taint flow (php_ast.go) │ │ ├── ldpreload/ # ld.so.preload + /proc/*/environ │ │ ├── persistence/ # ssh, cron, systemd timers/services, pam, sudoers, shellrc, users, kmods, ld.so.conf │ │ ├── memorymaps/ # /proc/*/maps: RWX / (deleted) / TracerPid / CapEff / .so allowlist │ │ ├── integrity/ # dpkg (Debian) + rpm (RHEL) + SUID/SGID delta + security.capability xattr │ │ ├── network/ # /proc/net/{tcp,tcp6,udp,udp6} × /proc/*/fd reverse-shell + listen delta │ │ ├── ancestry/ # PROC_RARE_ANCESTRY │ │ └── yara/ # Stub by default; cgo build with -tags with_yara │ ├── event/ # Event schema 1.1 (process / file / network / container / correlation_id) │ ├── ioc/ # Hash / IP / CIDR / domain feed loader + enrichment │ ├── procfs/ # /proc helpers (ancestry, cgroup, env, fds, net, maps) │ ├── rules/ # Rule pack load, expression evaluator, sigma-lite loader, ed25519 verify │ ├── runner/ # Scan orchestration, dedup, correlation, sensor glue, emit/spool │ ├── sensor/ # Auto() → eBPF (with_ebpf) | auditd tail | /proc poll │ ├── quarantine/ # Evidence vault (file + JSON sidecar) │ ├── selfguard/ # Binary sha256 + systemd watchdog │ ├── eval/ # Precision / recall / F1 harness │ ├── watch/ # fsnotify (keys, ld.so.preload, cron, systemd, sudoers, pam, sshd, docroots, passwd/shadow) │ └── export/ │ ├── syslog/ # UDP RFC5424 / RFC3164 │ ├── syslogtcp/ # RFC5425 TCP / TLS │ ├── splunk/ # HEC │ ├── elastic/ # _bulk │ └── loki/ # push API ├── systemd/ # Example unit file └── testdata/ ├── web/ # Sample web files for tests └── eval/ # Labeled malicious + benign corpus for ghostcatcher eval ``` ## 局限性 - **不能**替代企业级 EDR、托管威胁狩猎或内核级别的强制执行。 - **eBPF 传感器**需要内核版本 ≥ 5.8 且带有 `CAP_BPF`;较旧的主机会自动回退到 `auditd`,然后回退到 `/proc` 轮询,这会丢失部分精细度。 - **YARA** 需要带有 libyara 头文件的 cgo 构建(`-tags with_yara`);默认的 stub 将不会返回任何匹配项。 - **网络侧关联:** 主机外的流量分析仍然依赖于 **IDS** 或 netflow 收集器;代理仅观察在 `/proc/net/*` 中可见的套接字。 - **启发式规则**可能会产生误报(特别是 `maps` RWX 和宽泛的 PHP 模式) —— 请使用**基线**、**允许列表**以及 **`min_confidence_for_alert`**。 - **规则包签名**保护静态存储和加载时的安全;如果攻击者已经获得了 root 权限并且可以更改进程内存,`selfguard` 仍然可以翻转为 `AGENT_TAMPERED`,但无法进行自我修复。 ## 贡献指南 欢迎提交 Issue 和 PR:包括文档、测试、调优指南以及可选的后端(例如 RPM 验证、eBPF 事件摄取)。 **在提交 PR 之前:** 请运行 `go test ./...`、`go vet ./...`,并使用您的示例 YAML 运行 `check-config`。 ## 许可证 在发布前请向仓库添加一个 `LICENSE` 文件(例如 **MIT**、**Apache-2.0** 或 **GPL-3.0**)。本 README 本身并不强加任何许可证。 ## 安全说明 对于漏洞报告,请添加一个 [`SECURITY.md`](SECURITY.md) 并附上联系方式(例如 GitHub Security Advisories 或专用电子邮件)。在完成协调披露之前,请勿为未公开的可利用漏洞开启公开的 Issue。
标签:AMSI绕过, APT防御, auditd, Docker镜像, EDR, Elasticsearch, EVTX分析, fsnotify, Go语言, Grafana Loki, IOC, IP 地址批量处理, JSON, syslog, systemd, Web Shell检测, Web截图, x64dbg, YARA, 主机入侵检测, 主机检测, 云计算, 云资产可视化, 关系图谱, 关联分析, 反弹Shell, 基线检查, 威胁检测, 安全代理, 容器安全, 持久化检测, 文件监控, 日志审计, 日志采集, 程序破解, 端点安全, 网络安全, 脆弱性评估, 补丁管理, 规则引擎, 请求响应过滤, 隐私保护