masterwok/sohps

GitHub: masterwok/sohps

通过模拟 Linux 动态链接器行为,扫描 ELF 二进制文件中的不安全共享库搜索路径以发现劫持漏洞。

Stars: 1 | Forks: 0

# sohps:共享对象劫持路径扫描器 `sohps` 是一款安全审计工具,旨在识别 Linux ELF 二进制文件和 AppImage 容器中的共享对象劫持漏洞。通过模拟 Linux 动态链接器(`ld.so`)的行为,sohps 映射了二进制文件如何解析其共享对象依赖关系,并揭示了由不安全的搜索路径、可写目录或配置错误的环境所引入的漏洞。 ## 漏洞类别 `sohps` 将扫描结果分类为几种不同的攻击向量,为研究人员提供直接的漏洞利用上下文: | 类别 | 描述 | | :--- | :--- | | **隐式 CWD** | 由 `RPATH` 或 `RUNPATH` 中的空条目(例如末尾冒号)触发。链接器会回退到当前工作目录(CWD),允许攻击者投放恶意库。 | | **环境变量污染** | 由不安全的脚本包装器(例如在 AppImage 中)盲目追加到 `LD_LIBRARY_PATH` 触发。如果取消设置该环境变量,末尾的冒号将回退到 CWD。 | | **$ORIGIN 劫持** | 通过 `$ORIGIN` 宏解析的目录内的漏洞。如果二进制文件所在目录或其相对邻近目录可写,则依赖树可能会被劫持。 | | **可写路径** | 当前用户可写的绝对搜索路径(系统定义或用户定义),允许直接替换或重建依赖树。 | | **相对路径** | 硬编码的相对路径(例如 `lib/`),这些路径是相对于 CWD 而不是二进制文件的位置进行解析的。 | | **绝对路径** | 当 `DT_NEEDED` 条目包含 `/`(例如 `/tmp/lib.so`)时发生。链接器会绕过所有搜索路径并直接从指定位置加载文件。 | | **系统预加载** | 检查可写或缺失的 `/etc/ld.so.preload` 文件,这可能导致对每个执行进程的系统级劫持。 | ## 功能特性 `sohps` 模拟了以下 `ld.so` 逻辑: - **原生 AppImage 支持**:原生提取并分析 Type-2 AppImage(使用纯 Go 的 SquashFS 实现),以检测易受攻击的 `AppRun` 包装器和不安全的内部二进制文件。 - **链接器宏展开**:全面支持基于目标二进制文件架构的 `$ORIGIN`、`$LIB` 和 `$PLATFORM` 展开。 - **搜索路径优先级**:正确处理 `DT_RPATH` 与 `DT_RUNPATH` 的优先级及其与 `LD_LIBRARY_PATH` 的交互。 - **递归配置解析**:解析 `/etc/ld.so.conf` 及所有嵌套的 `include` 指令,以构建准确的系统搜索路径映射。 - **HWCAP 解析**:模拟硬件功能搜索(例如 `tls/aarch64/aarch64`),以识别“隐藏的”搜索目录。 - **AT_SECURE 感知**:自动检测 SUID/SGID 位并忽略不受信任的路径(相对路径、`$ORIGIN`),就像内核所做的那样。 - **符号链接去重**:通过解析符号链接并仅对每个唯一的二进制文件分析一次,高效扫描大型目录。 - **传递性分析**:完整映射传递依赖树,以揭示深层依赖库中的漏洞。 ## 缺陷与限制 虽然 `sohps` 是一款功能强大的工具,但用户应了解其技术边界: - **静态与运行时**:`sohps` 对 ELF 结构和文件系统权限执行高级静态分析。它不考虑在运行时通过 `dlopen()` 动态加载的库。 - **用户空间视角**:权限检查是以运行该工具的用户的身份执行的。以低权限用户与 root 身份运行时,扫描结果可能会有所不同。 - **内核与链接器差异**:尽管 `sohps` 模拟了标准 `glibc` 的行为,但自定义或高度专用的链接器(例如嵌入式系统或 `musl` 中的链接器)可能存在细微的行为差异。 - **环境变量**:除了像 `--ld-path` 这样的模拟标志外,`sohps` 不会自动考虑可能影响 `ld.so` 的各种环境变量。 ## 安装与构建 `sohps` 使用 Go 语言编写,需要 1.21 或更高版本。 ### 本地构建 ``` go build -o sohps ./cmd/sohps/main.go ``` ### 交叉编译 您可以使用 Go 内置的交叉编译支持为不同的架构编译 `sohps`。 **为 x86_64 Linux 构建:** ``` GOOS=linux GOARCH=amd64 go build -o sohps_amd64 ./cmd/sohps/main.go ``` **为 AArch64 (ARM64) Linux 构建:** ``` GOOS=linux GOARCH=arm64 go build -o sohps_arm64 ./cmd/sohps/main.go ``` ## 测试与验证 ### 运行单元测试 该项目包含针对所有内部包的全面单元测试套件: ``` go test ./internal/... -v ``` ### `testenv` 沙盒 `testenv/` 目录包含一个专门的研究环境,用于生成故意包含漏洞的二进制文件。这允许研究人员针对真实场景验证该工具的检测逻辑。 1. **构建沙盒**: cd testenv make all 2. **扫描沙盒**: ./sohps --root /tmp/sohps_test testenv/bin 这将枚举所有 6 种主要漏洞类别,包括 **系统预加载**,为该工具的功能提供清晰的基准。 ## 使用方法 ``` # 扫描单个 binary ./sohps /usr/bin/clang-query # 递归扫描目录 ./sohps /usr/local/bin # 指定自定义 system root(例如用于 firmware 或 rootfs 分析) ./sohps --root /mnt/rootfs /mnt/rootfs/bin # 模拟受攻击者控制的 LD_LIBRARY_PATH ./sohps --ld-path /tmp/evil /usr/bin/sudo # 无颜色日志的详细扫描(显示安全目标) ./sohps -v -nc / > scan_report.txt ``` ## 示例 ``` $ ./sohps testenv/bin [*] Scanning testenv/bin... [*] Found 14 ELF binaries. Starting analysis... [*] testenv/bin/test_implicit_cwd [!] Implicit CWD Vulnerable Path : Empty Path (Implicit CWD) Resolved Dir : Runtime Current Working Directory Action : CWD HIJACK: Execute binary from an attacker-controlled writable directory containing a malicious payload. Libraries (4) : libcustom.so, libcustom.so, libc.so.6, libc.so.6 [*] testenv/bin/test_colon_split [!] Writable Path Vulnerable Path : /tmp/sohps_test/one Resolved Dir : /tmp/sohps_test/one/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/one/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/two Resolved Dir : /tmp/sohps_test/two/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/two/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/one Resolved Dir : /tmp/sohps_test/one/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/one/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [!] Writable Path Vulnerable Path : /tmp/sohps_test/two Resolved Dir : /tmp/sohps_test/two/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/two/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_nodeflib [!] Writable Path Vulnerable Path : /tmp/sohps_test/nodeflib Resolved Dir : /tmp/sohps_test/nodeflib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/nodeflib/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/nodeflib Resolved Dir : /tmp/sohps_test/nodeflib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/nodeflib/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_needed_abs [!] Absolute Path Vulnerable Path : Hardcoded Absolute Path Resolved Dir : /tmp/sohps_test Action : OVERWRITE: Delete existing library and replace with payload: rm /tmp/sohps_test/libcustom.so && mv payload.so /tmp/sohps_test/libcustom.so Libraries (1) : /tmp/sohps_test/libcustom.so [*] testenv/bin/test_missing_writable [!] Writable Path Vulnerable Path : /tmp/sohps_test/missing Resolved Dir : /tmp/sohps_test/missing/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test/missing). Recreate full path and drop payload at: /tmp/sohps_test/missing/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/missing Resolved Dir : /tmp/sohps_test/missing/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test/missing). Recreate full path and drop payload at: /tmp/sohps_test/missing/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_relative [!] Relative Path Vulnerable Path : ./lib Resolved Dir : /home/foo/dev/sohps/lib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/home/foo/dev/sohps). Recreate full path and drop payload at: /home/foo/dev/sohps/lib/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Relative Path Vulnerable Path : ./lib Resolved Dir : /home/foo/dev/sohps/lib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/home/foo/dev/sohps). Recreate full path and drop payload at: /home/foo/dev/sohps/lib/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_origin [!] $ORIGIN Hijack Vulnerable Path : $ORIGIN/../lib Resolved Dir : /home/foo/dev/sohps/testenv/lib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/home/foo/dev/sohps/testenv). Recreate full path and drop payload at: /home/foo/dev/sohps/testenv/lib/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] $ORIGIN Hijack Vulnerable Path : $ORIGIN/../lib Resolved Dir : /home/foo/dev/sohps/testenv/lib/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/home/foo/dev/sohps/testenv). Recreate full path and drop payload at: /home/foo/dev/sohps/testenv/lib/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_rpath [!] Writable Path Vulnerable Path : /tmp/sohps_test/rpath Resolved Dir : /tmp/sohps_test/rpath/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/rpath/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/rpath Resolved Dir : /tmp/sohps_test/rpath/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/rpath/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_appimage.AppImage [!] Environment Poisoning Vulnerable Path : Internal AppRun:1 Resolved Dir : Runtime Environment Action : CWD HIJACK: Script poisons LD_LIBRARY_PATH when empty. Ensure it is unset, drop malicious library in CWD, and execute. Libraries (2) : ld-linux-aarch64.so.1 (Proxy Required) libc.so.6 [*] testenv/bin/test_trailing_colon [!] Writable Path Vulnerable Path : /tmp Resolved Dir : /tmp/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp). Recreate full path and drop payload at: /tmp/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [!] Implicit CWD Vulnerable Path : Empty Path (Implicit CWD) Resolved Dir : Runtime Current Working Directory Action : CWD HIJACK: Execute binary from an attacker-controlled writable directory containing a malicious payload. Libraries (1) : libc.so.6 [*] testenv/bin/test_writable_file [!] Writable Path Vulnerable Path : /tmp/sohps_writable_file Resolved Dir : /tmp/sohps_writable_file Action : RECREATE: Rename writable parent (/tmp) and recreate path to drop payload: mv /tmp/sohps_writable_file && mkdir -p /tmp/sohps_writable_file Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_writable_file Resolved Dir : /tmp/sohps_writable_file/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp). Recreate full path and drop payload at: /tmp/sohps_writable_file/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] testenv/bin/test_writable_path [!] Writable Path Vulnerable Path : /tmp/sohps_test Resolved Dir : /tmp/sohps_test/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [!] Writable Path Vulnerable Path : /tmp/sohps_test Resolved Dir : /tmp/sohps_test Action : OVERWRITE: Delete existing library and replace with payload: rm /tmp/sohps_test/libcustom.so && mv payload.so /tmp/sohps_test/libcustom.so Libraries (1) : libcustom.so [*] testenv/bin/test_runpath [!] Writable Path Vulnerable Path : /tmp/sohps_test/runpath Resolved Dir : /tmp/sohps_test/runpath/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/runpath/tls/aarch64/aarch64/libcustom.so Libraries (1) : libcustom.so [!] Writable Path Vulnerable Path : /tmp/sohps_test/runpath Resolved Dir : /tmp/sohps_test/runpath/tls/aarch64/aarch64 Action : RECREATE: Writable parent (/tmp/sohps_test). Recreate full path and drop payload at: /tmp/sohps_test/runpath/tls/aarch64/aarch64/libc.so.6 Libraries (1) : libc.so.6 [*] Progress: [14/14] 100.0% [*] Scan complete. ```
标签:ELF分析, EVTX分析, 动态链接库, 日志审计, 路径劫持