利用SUID逻辑漏洞:Readline信息泄露攻击解析
漏洞概述
我在readline依赖库中发现了一个逻辑漏洞,当解析INPUTRC
环境变量指定的文件时,会部分泄露文件信息。攻击者可在运行sshd、用户可登录且私钥存储在已知位置(如/home/user/.ssh/id_rsa
)的主机上横向移动。
该漏洞已于2022年2月报告并修复,且chfn通常不由util-linux提供,因此您的系统可能不受影响。我撰写本文是因为利用过程很有趣,得益于readline配置文件解析函数与SSH密钥格式的巧合匹配。
TL;DR:
|
|
发现漏洞
在深入研究Qualys sudo漏洞后,我对SUID漏洞产生了兴趣。在浏览《软件安全评估艺术》时,我受到启发研究环境变量作为攻击面。花费几小时时间,我在/etc/ld.so.preload
中插入了一个拦截库来记录getenv调用:
|
|
注意: 我们假设这就是我从一开始的做法,没有浪费时间在gdb下启动SUID进程。
安装日志库后,我运行find / -perm /4000
(是的,我搜索了参数)来查找系统上的所有SUID二进制文件。
如果您跟着操作,请注意:记录所有getenv调用非常嘈杂,会产生许多繁琐、重复和无趣的结果。在浏览了大量LC_MESSAGES
、SYSTEMD_IGNORE_USERDB
、SYSTEMD_IGNORE_CHROOT
等变体后,我发现了INPUTRC
,它在chfn命令中的某处使用。直觉告诉我INPUTRC
指的是配置文件,我盲目传递了INPUTRC=/etc/shadow
看看会发生什么:
|
|
嗯。/etc/shadow
?在我的终端中?这比您想象的可能更常见。
根本原因分析
我首先搜索了"INPUTRC"。有帮助的是,搜索结果的第一个结果给了我线索,它与readline库相关。确实,通过挖掘readline-8.1源代码,我发现"INPUTRC"通过sh_get_env_value
作为参数传递给getenv。看起来没错!
|
|
在readline代码库中搜索我们之前看到的错误消息"unknown key modifier"也会返回结果。rl_read_init_file
调用_rl_read_init_file
,后者路由到rl_parse_and_bind
函数,该函数发出错误。从这个调用堆栈中,我们可以推断错误发生在readline尝试解析输入文件时——特别是当它试图将文件内容解释为键绑定配置时。
让我们从头开始。跳过空白后,_rl_read_init_file
为输入文件中的每个非注释行调用rl_parse_and_bind
。rl_parse_and_bind
函数包含四个导致_rl_init_file_error
的错误路径,该函数打印当前正在解析的行。这是漏洞的根源,因为readline不知道它以提升的权限运行,并假设打印部分输入文件是安全的。
_rl_init_file_error
在第1557、1569、1684和1759行使用参数字符串(循环遍历配置文件时的当前行)调用。其他几个错误路径可能导致当前行的部分泄露;为简洁起见,此处省略。我们还将跳过传递二进制文件时会发生的情况。
通过检查到达上述路径所需的条件,我们可以推断出从文件泄露行的条件:
- 我们可以泄露以引号开头且没有闭合引号的行:
|
|
|
|
- 我们可以泄露以冒号开头且不包含空格或空值的行:
|
|
|
|
- 我们可以泄露不包含空格、制表符或冒号(或空值)的行:
|
|
|
|
幸运的是,SSH密钥匹配这第三条路径,因此我们可以在此停止。好吧,至少多汁的部分匹配——所有密钥数据通常在PEM容器中Base64编码。我们还可以使用此漏洞读取PEM容器中的任何其他内容,如证书文件;或只是base64编码的内容,如wireguard密钥。
影响
该漏洞于2017年在版本2.30-rc1中引入,这使得该漏洞足够老旧,可以影响LTS版本。然而;Debian、Red Hat和Ubuntu的chfn由不同的包提供,因此不受影响。在Red Hat的默认配置中,/etc/login.defs
不包含CHFN_RESTRICT
。此省略将阻止util-linux/chfn更改任何用户信息,这也会杀死漏洞。在我的测试中,CentOS或Fedora似乎默认也没有安装chfn。
那么,除了chfn之外,这个漏洞的影响有多大?readline相当知名,但我们在这里感兴趣的是它在SUID二进制文件中的使用。在我的Arch盒子上对每个SUID运行ldd显示该库仅由chfn使用…我们如何快速确定更广泛的影响?
我首先想到扫描包存储库,但不幸的是,Debian、Ubuntu、Fedora、CentOS或Arch包存储库的Web界面都没有提供文件模式…这意味着我们没有足够的信息来确定给定包中的任何二进制文件是否是SUID。
所以我镜像了Debian和Arch的x86_64存储库,并手动检查它们,辅以一些糟糕的shell脚本。这项努力的要点是,Arch是唯一一个包含SUID可执行文件(chfn)的包(util-linux)默认加载readline的发行版。哦好吧!
不要在SUID应用程序中使用readline
这基本上是通过电子邮件链发送给Arch和Red Hat安全团队以及包维护者的结果,后者继续从chfn中移除readline支持。该漏洞大约一年前已修复,因此希望大多数受影响的用户现已更新。
作业: 去看看有多少SUID使用ncurses——至少在macOS上——并尝试弄乱TERMINFO
环境变量…如果您找到任何东西,请告诉我:^)
致谢
感谢Karel Zak以及Arch和Red Hat安全团队,他们都非常 helpful 且迅速推出修复。也感谢disconnect3d的帮助和建议。
时间线
- 2017年5月2日:漏洞引入
- 2020年12月31日:全局时间线重置
- 2022年2月8日:向Arch和util-linux上游报告漏洞
- 2022年2月14日:util-linux上游修复漏洞
- 2022年3月28日:关于漏洞发现的博客文章起草
- 2022年5月12日:博客文章内部发布
- 2022年5月-2023年2月:拖延^H 允许更新时间
- 2023年2月16日:博客文章发布
参考文献
- 漏洞在版本2.30-rc1中引入
- util-linux v2.37.4发布公告
- CVE-2022-0563
- Red Hat Bugzilla: Bug 2053151
- util-linux存储库:从chsh、chfn中移除readline支持 [CVE-2022-0563]