curl持久化文件权限漏洞分析:Cookie与HSTS缓存泄露风险

本文详细分析curl持久化文件权限漏洞,该漏洞导致Cookie、HSTS和Alt-Svc缓存文件继承umask权限,可能被本地用户读取或篡改,造成会话劫持等安全风险。

执行摘要

Curl_fopen()在创建临时文件时会克隆任何已存在持久化文件的权限。当持久化文件不存在时,它会首先使用进程umask(通常为022,即0644)创建一个文件。该模式随后通过0600 | sb.st_mode复制到临时文件,因此最终的cookie/HSTS/Alt-Svc存储文件最终变为组/其他用户可读,即使它包含承载令牌。(lib/curl_fopen.c:101-150)

所有依赖Curl_fopen()的有状态持久化功能——cookie_output()Curl_hsts_save()Curl_altsvc_save()——都继承了此行为,将会话cookie、HSTS缓存条目和Alt-Svc元数据泄露给任何本地用户。

复现步骤

环境:macOS 26.1 Dev Beta 4,提交a49e4e3d16991465144558f405b2d7972824abb0,使用./configure --disable-shared --with-openssl=/opt/homebrew/opt/openssl@3 --without-libpsl && make -j8构建。

确保没有残留文件并模拟正常的多用户umask:

1
2
3
4
rm -f /tmp/cookie-leak.txt && umask 022 \
&& ./src/curl -s -o /dev/null -c /tmp/cookie-leak.txt https://example.org \
&& ls -l /tmp/cookie-leak.txt
.rw-r--r-- 131 geeknik 26 Oct 22:22 /tmp/cookie-leak.txt

即使没有设置cookie,也会创建cookie jar,这足以演示默认模式0644。

作为另一个本地用户,只需cat /tmp/cookie-leak.txt即可读取文件内容——在实际流量中,完整的会话cookie将被暴露。相同的复现方法适用于--hsts--alt-svc文件,因为它们使用相同的代码路径调用Curl_fopen()

此外,我们在Fedora上使用curl 8.6.0(x86_64-redhat-linux-gnu)复现了此行为。

CVSS v3.0

AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

建议修复

将第140-141行替换为:

1
fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);

影响

同一主机上的任何本地用户(共享CI运行器、大学shell、托管桌面等)可以读取另一个用户的curl/libcurl客户端写入的身份验证cookie、会话令牌、CSRF nonce、HSTS预加载数据或Alt-Svc目标。直接后果范围从完全账户接管(cookie重放)到绕过HSTS(通过在受害者读取文件之前重写文件)以及对Alt-Svc缓存中列出的内部端点进行情报收集。由于每当使用CURLOPT_COOKIEJARCURLOPT_HSTSWRITEFUNCTIONCURLOPT_ALTSVC时,文件会自动写入,即使配置良好的自动化也会无意中将秘密泄露给共同驻留的用户。

讨论记录

geeknik提交报告(11天前)

**bagder (curl工作人员)**回复: 感谢您的报告!我们将花时间调查您的报告,并尽快回复您详细信息和可能的后续问题!很可能在接下来的24小时内。

**bagder (curl工作人员)**回复: 如果用户希望创建的文件受到保护,为什么他们会设置一个允许其他用户读/写创建文件的umask,这难道不是完全按照用户的要求执行吗?这似乎正是umask的用途。

**jimfuller2024 (curl工作人员)**回复: 这里没有看到任何安全问题,更多信息可能有助于澄清。

**bagder (curl工作人员)**回复: 相关旧问题:https://hackerone.com/reports/1024749

geeknik回复: 感谢反馈。我完全理解"umask是用户选择"的观点,但以下是我们仍然认为这需要修复的原因:

  1. curl已经特殊处理凭据 libcurl对~/.netrc文件强制使用0600权限(参见lib/netrc.c),认识到身份验证令牌不应从环境继承环境权限。COOKIEJAR、HSTS和Alt-Svc文件具有完全相同的功能。它们是启用会话重放和持久化的凭据存储。当前行为不一致:它保护.netrc文件但让cookie文件暴露。

  2. 在大多数系统上默认行为不安全 绝大多数多用户*nix系统上的默认umask是022。用户无需进行任何配置更改,curl -c cookies.txt就会产生一个包含潜在敏感会话令牌的世界可读文件。这不是用户"选择加入"不安全权限的情况;这是默认的开箱即用行为。

  3. 最小意外原则 当用户输入curl -c cookies.txt时,他们的意图是为将来的会话保存cookie。自然的假设是处理凭据的工具会安全地执行此操作。默认为世界可读权限违反了此用户期望和最小意外原则。

  4. 现实世界自动化陷阱 在自动化环境(如CI/CD流水线和cron作业)中,持久化文件通常跨运行重复使用。如果早期作业以宽松的umask运行并创建cookie jar,所有后续作业都会继承这些弱权限,即使它们自己的umask更严格。第一次运行有效地"毒化"了所有未来使用该文件的自动化的安全状况。

  5. 行业先例 其他管理敏感文件的工具优先考虑安全性而非环境权限。例如,如果私钥权限不是0600,OpenSSH将报错。凭据处理工具的既定模式是为敏感数据覆盖umask,并允许用户在异常用例需要时手动放宽权限。

**bagder (curl工作人员)**回复:

libcurl对~/.netrc文件强制使用0600权限

您现在在使用AI吗?这似乎是完全编造的,超出了可能的误解范围。A) libcurl不"强制"0600,B) 它根本不创建netrc文件。

用编造的小说浪费我们的时间是非常粗鲁的,这是我们终身禁止记者的冒犯行为。由于您的记录,这次原谅您。我对您期望更高。

所有其他论点似乎只是列出了为什么如果您想防止系统上的其他用户读取您创建的文件,umask 022是个坏主意的原因。

“行业先例"论点感觉像是苹果与橘子的比较。

我们故意这样创建文件。我们不认为这是一个安全问题。当然,我们可以在未来版本中讨论更改此决定,但这样的讨论应该在公开场合进行。可能在邮件列表或GitHub讨论中。

geeknik关闭报告并将状态更改为不适用: 得知我在早上第一杯咖啡之前表现得像AI,真是令人失望。😔下次我会先喝两杯。

我误解了https://daniel.haxx.se/blog/2022/05/31/netrc-pains/,其中说”.netrc文件通常设置没有组或世界读取权限(0600)以减少泄露这些秘密的风险。“你知道他们对假设的说法。

但既然这不是安全问题,我将关闭错误,我们可以披露此问题。

**bagder (curl工作人员)**请求披露此报告(10天前)

**bagder (curl工作人员)**回复:

得知我在早上第一杯咖啡之前表现得像AI,真是令人失望

我的错。我为那个指控道歉。这是错误的。

**bagder (curl工作人员)**披露此报告(10天前)

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计