本仓库包含针对 CVE-2019-0217 的概念验证利用代码,以及用于搭建存在该漏洞的 Web 服务器的 Dockerfile。
在 Apache HTTP Server 2.4 版本 2.4.38 及更早版本中,运行在线程化服务器上的 mod_auth_digest 存在一个竞态条件,可能允许拥有有效凭据的用户使用另一个用户名进行身份验证,从而绕过已配置的访问控制限制。
当客户端尝试访问受 HTTP Digest Auth 保护的资源时,服务器会返回 401 状态码,并附带一个 WWW-Authenticate 头部,其格式大致如下:
Digest realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", algorithm=MD5, qop="auth"
客户端计算 HA1,即 A1 的 MD5 摘要(即 username:realm:password),然后将其与 nonce 及其他元数据(如 cnonce)相加得到 A2,再计算 A2 的 MD5 摘要得到 HA2。客户端将 HA2 连同 username、cnonce 及其他元数据放入 Authentication 头部发送:
'Digest username="attacker", realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", uri="/scripts/userprofile.cgi", response="bcb433e4071fa228fe0c9452a7495efd", algorithm="MD5", qop="auth", nc=00000001, cnonce="2309510923095109"
^^^^^^^^^^
如下所述,上述头部中高亮的部分可以被操纵,以创建利用所需的关键竞态条件。
该漏洞已通过此提交修复。
查看 mod_auth_digest 模块的代码(特别是 mod_auth_digest.c 中的 get_hash 函数),可以发现服务器首先解析 Authentication 头部,以确定 username= 后面引号内的内容,并将其视为与请求关联的用户(r->user)。然后检查该“用户”是否有权访问请求的资源。如果有,get_hash 函数会从身份验证文件中检索对应的 HA1。
在修复漏洞的提交之前,检索到的 HA1 存储在 conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,&auth_digest_module) 变量中,该变量显然不是线程安全的。
这就引出了我们的利用方法:
根据上述漏洞分析部分,应该可以通过同时发送带有有效 Authentication 头部的请求以及带有伪造 Authentication 头部的请求(即与有效头部相同,但将 username= 的值设置为目标用户(攻击者想要冒充的用户))来创建竞态条件。
本漏洞利用中使用的术语: - 攻击者:运行此漏洞利用的用户。他们拥有自己账户的有效用户名和密码。 - 受害者:攻击者想要冒充的用户。受害者的用户名已知,但密码(显然)未知。
我尝试通过大量 Python 线程(其中一些发送第一种类型的请求,另一些发送第二种类型的请求)来实现此方法,但该方法不可靠,并且需要大量请求才能成功。 这促使我使用 Burp 的 Turbo Intruder(免费版),它可以可靠地并行发送请求。不幸的是,Turbo Intruder 的 CLI 支持已损坏,因此漏洞利用的某些部分需要在 GUI 中执行。
要使用本仓库中包含的示例易受攻击服务器,请运行:
$ cd sample_vulnerable_server
$ docker build -t poc_httpd .
$ docker run -p 8038:80 poc_httpd
配置顶部变量后,运行 generate_turbo_intruder_script.py:
# 配置
URL = 'http://localhost:8038/scripts/userprofile.cgi' # 受摘要认证保护的资源位置
ATTACKER_USERNAME = 'attacker'
ATTACKER_PASSWORD = 'known'
VICTIM_USERNAME = 'victim'
NUMBER_OF_REQUESTS = 2000 # 发送的并发请求数,用于捕捉竞态条件
该脚本会在当前目录生成两个文件:generated/turbo_intruder_script.py 和 generated/request.txt。
现在,打开 BurpSuite Community Edition,如果尚未安装“Turbo Intruder”扩展,请前往 Extensions -> BApp Store 进行安装。
打开 Burp 中继器。设置目标的主机和端口:

将 generated/request.txt 的内容粘贴到请求部分:

在请求部分的任意位置右键单击,选择“Extensions->Turbo Intruder->Send to Turbo Intruder”。

将 generated/turbo_intruder_script.py 的内容粘贴到脚本部分:

最后,点击 Turbo Intruder 窗口底部的 Attack 按钮。它应在结果界面中显示任何成功的请求:
