感谢 https://github.com/amlweems/xzbot
测试环境搭建
- 编译环境apt install golang
- exp脚本git clone https://github.com/amlweems/xzbot
- 编译exp
1 | cd xzbot |
- 创建指向patch的符号链接 cd assets; ln -s liblzma.so.5.6.1.patch liblzma.so.5
- 在assets目录下,启动sshd env -i LANG=C LD_LIBRARY_PATH=”./“ /usr/sbin/sshd -p 2222 -r
- 回到父目录,使用./xzbot -addr 127.0.0.1:2222 -cmd ‘id > /tmp/.xz’执行命令
后门利用
带后门的liblzma文件被成功执行后会修改plt表中RSA_public_decrypt函数使其指向自己的payload
当使用证书认证方式登录时,sshd会调用RSA_public_decrypt对证书进行解密。通过对sshd的源代码进行分析,在证书认证登录时共有两次调用RSA_public_decrypt。调用链分别是
- userauth_pubkey->sshkey_from_blob->cert_parse->sshkey_verify->RSA_public_decrypt
- userauth_pubkey->sshkey_verify->RSA_public_decrypt
其中1最终RSA_public_decrypt的参数为ca证书的publickey,而2为key的publickey。由于2在调用sshkey_verify前会使用user_key_allowed函数判断证书是否正确,所以无法利用。
1 | /* test for correct signature */ |
而1中在调用RSA_public_decrypt前并未做任何前置的校验,所以适合被用来RCE。SSH的证书登录一般都是直接使用公私钥对直接认证,很少会使用CA证书签名,可以看出后门利用链是经过精心选取的。
在hook后的 RSA_public_decrypt中,后门使用一个硬编码的ED448公钥进行签名验证和解密payload。如果需要触发后门需要使用自己的密钥替换这个密钥。如果签名校验失败或者payload的格式不符合,后门会回到真的RSA_public_decrypt进行后续的校验。由于与正常的SSH证书认证流程并无差别,所以无法使用全网探测或者测绘的方式找到被感染的主机。
命令执行
进程链
后门在成功触发后会使用system函数来执行命令。
调用代码使用动态获取函数地址的方式调用system函数。
检测方式
System执行
由于使用system函数执行,进程链上会有明显的特征,可用来作为检测规则。
- 正常的ssh登录的进程链是sshd->bash->cmd
- 正常ssh未登录直接执行命令的进程链是 sshd->cmd
- 后门链的进程链是sshd->sh -c {cmd} ->cmd
环境变量
此外由于exp执行时不会执行/root/.bashrc,所以也可通过执行命令环境变量的差异来构造检测规则
误报分析
略
背景研判
略