← 返回博客

代理密码通过HTTP客户端泄露:curl、libsoup和requests中的CVE

在2026年,curl、libcurl和libsoup发现了漏洞,导致Proxy-Authorization头部发送给错误的代理或直接发送给目标网站。我们来分析一下在什么情况下会发生这种情况,哪些版本是安全的,如何通过实际测试检查自己的解析器,以及如果密码泄露,如何限制损失。

📅2026年10月17日
代理密码通过HTTP客户端泄露:curl、libsoup和requests中的CVE

代理的密码通常会被保护起来:不会在截图中显示,不会提交到 git,保存在环境变量中。但在 2026 年,发现 HTTP 客户端可能会泄露它。在四月到七月之间,curl、libcurl 和 libsoup 出现了几处漏洞,导致 Proxy-Authorization 头部发送给错误的代理,甚至直接发送给目标网站。下面将分析在什么情况下会发生这种情况,并逐步检查自己的技术栈。

发生了什么:四个月内的四个泄露

所有这些漏洞的机制相同:客户端记住一个代理的用户名和密码,并错误地将其发送到链条的下一个环节。

  • CVE-2026-6253 (curl 和 libcurl 7.14.1–8.19.0). 如果 http:// 和 https:// 配置了不同的代理,第一个需要密码,而第二个不需要,那么在重定向时,curl 会将第一个代理的凭据发送给第二个。数据以 base64 形式发送,实际上是明文。该问题在 2026 年 4 月 29 日发布的 curl 8.20.0 中修复。控制台 curl 也受到影响,不仅仅是库。
  • CVE-2026-8927 (libcurl 7.12.0–8.20.0). 应用程序重用一个句柄进行多个请求,代理从环境变量中获取,授权使用 Digest。当此时,代理 A 的 Proxy-Authorization 头部被发送给代理 B,后者可以重复使用它来冒充你。该问题在 2026 年 6 月 24 日发布的 curl 8.21.0 中修复。控制台 curl 不受影响。几乎相同的漏洞在 CVE-2026-7168 中被描述,唯一的区别在于如何选择代理。
  • CVE-2026-12547 (libsoup, SoupAuthManager). libsoup 缓存代理凭据,但不将其绑定到 host:port 地址。当代理设置发生变化(系统参数,WPAD)时,旧的头部会发送给新的代理。该问题于 2026 年 7 月 21 日发布,评估较低。
  • CVE-2026-66339 (libsoup, CONNECT 隧道). 通过 HTTP 代理建立 CONNECT 隧道后,libsoup 会将 Proxy-Authorization 附加到隧道内的后续 HTTPS 请求中。目标服务器可以看到该头部。CVSS 6.5,于 2026 年 7 月 24 日发布。

这个问题并不新鲜。在 Python 库 requests 的版本 2.3.0 到 2.31.0 (CVE-2023-32681) 中,在重定向到 HTTPS 时,Proxy-Authorization 头部会发送给目标服务器,如果用户名和密码直接写在代理的 URL 中。在 urllib3 的版本 1.26.19 和 2.2.2 (CVE-2024-37891) 中,手动设置的头部而不是通过内置的代理支持在重定向到其他域时不会被删除。

为什么这对使用代理特别重要

对于付费代理,密码等同于金钱。谁获得了它,谁就会消耗你的流量,直到你更改访问权限。按流量计费时,这是一笔直接的费用,而在团队共享访问时,其他人还会通过你的 IP 进行操作。

最脆弱的场景如下:

  • 解析器和监控工具,它们会自动跟随重定向。目标网站或中间重定向可能会将请求引导到收集头部的域。
  • 使用多个代理的脚本:不同的代理用于不同的协议,在同一连接中在请求之间切换代理,混合“有密码的代理”和“无密码的代理”。
  • 在 Linux 服务器上长期运行的进程,其中 libcurl 和 libsoup 随系统包一起提供,并与发行版一起更新,而不是与您的代码一起更新。
  • 使用 WPAD 和 PAC 文件的企业网络:代理在应用程序不参与的情况下发生变化,而这个案例在 CVE-2026-12547 中被描述。

如何检查自己的技术栈:逐步进行

  1. 了解真实的 libcurl 版本,而不仅仅是控制台 curl。 命令 curl -V 显示两者,但应用程序可能使用了自己的库副本。对于 Python 使用 pycurl 执行 python -c "import pycurl; print(pycurl.version)",对于 PHP 调用 curl_version()。安全边界:8.21.0 及以上,或修复的分支 8.20.1+、8.16.1+ 和 8.14.2+。
  2. 检查 Python 依赖。 执行 pip show requests urllib3。需要 requests 版本不低于 2.31.0 和 urllib3 版本不低于 1.26.19(1.x 分支)或 2.2.2(2.x 分支)。如果依赖是通过传递方式引入的,请在解析器运行的同一环境中查看 pip list。
  3. 在 Linux 上检查 libsoup。 这适用于 GNOME 应用程序、WebKitGTK 以及所有基于该技术栈构建的内容。通过发行版的包管理器更新该包,并与发行版的安全公告进行对照:在这些 CVE 的卡片中,红帽公司指出受影响的 RHEL 6–10。
  4. 在代码中查找手动设置头部。 在整个代码库中搜索 Proxy-Authorization。如果头部是手动设置的,而不是通过客户端的标准代理机制(proxies= 在 requests 中,ProxyManager 在 urllib3 中,CURLOPT_PROXYUSERPWD 在 libcurl 中),这就是重定向时泄露的候选者。
  5. 查找在更换代理时的连接重用。 一个 libcurl 句柄,一个 requests 会话或一个 HTTP 代理,通过它们依次发送不同代理的请求。最简单的修复方法是为每个代理创建一个单独的会话。
  6. 在不需要的地方禁用自动重定向。 在 requests 中这是 allow_redirects=False,在 urllib3 中是 redirect=False,在 curl 中不要使用 -L 和 CURLOPT_FOLLOWLOCATION。这样 3xx 状态码将被手动处理,你可以自己决定接下来要去哪里。正是这个绕过方法由 requests 和 urllib3 的作者提供。
  7. 进行实时捕获测试。 在你自己搭建一个简单的 HTTP 服务器,打印所有接收到的头部,并在其上重定向到第二个相同的服务器。通过你的解析器使用代理运行真实场景,包括从 http 切换到 https 的方案。如果任何一个服务器看到 Proxy-Authorization,泄露就已在你的代码中得到确认,而不是理论上的。

潜在问题

  • Docker 镜像独立运行。 在主机上更新了 curl,但解析器在使用旧基础镜像的容器中运行。需要在容器内部检查:docker exec <容器> curl -V。
  • 控制台 curl 和 libcurl 更新方式不同。 CVE-2026-8927 不影响控制台 curl,而 CVE-2026-6253 则影响它。终端中的新 curl -V 并未说明你的 PHP 或 Python 是与哪个库构建的。
  • Digest 并不能拯救。 是的,在 Digest 中密码不会以明文形式发送。但在 CVE-2026-8927 中,攻击者并不需要密码:被拦截的头部会在 nonce 有效时被重复使用。
  • URL 中的密码方便,但危险。 在 requests 中的泄露正是在凭据被写入形式为 user:pass@host:port 的代理地址时发生的。这并不是放弃该格式的理由,但却是保持库更新的理由。
  • 重定向可能并非来自目标。 验证码页面、同意横幅、链接缩短器和 CDN 也会返回 3xx 状态码。爬虫中“跟随链接”的行为越多,攻击面就越大。

如果密码确实泄露,如何限制损失

完全消除泄露是不可能的:明天可能会出现下一个 CVE。因此,了解一次泄露的代价是很重要的。

  • 一个项目,一个访问权限。 不要为所有解析器保留一个共享的登录。ProxyCove 中每个购买的代理都会获得一对独立的用户名和密码,因此一个脚本泄露的访问权限不会影响其他的流量。
  • 不要在一个访问权限上保留超过所需的流量。 根据任务逐步补充,而不是提前六个月。
  • 监控流量消耗。 流量的突然增长而任务数量没有增加——这是你访问权限被其他人使用的第一个迹象。
  • 在怀疑时立即更改密码,并按照计划定期更改。如何在不造成停机的情况下进行安排,在关于 代理密码轮换安全指南 的指南中进行了详细说明。

选择哪种类型的代理以及它的相关性

泄露与代理类型无关:漏洞存在于客户端。但泄露的代价是不同的。数据中心代理 每 GB 价格更便宜,对于解析简单网站和频繁重定向的情况,合理地将它们与昂贵的流量分开。住宅代理 应该用于真正需要它们的任务,并为它们单独设置访问权限,关闭自动重定向。移动代理,每 GB 价格最高,最好在代码中保持最少的外部依赖,并在每次构建时检查库的版本。

总结

代理的密码可能在没有被黑客攻击、没有病毒和没有人为错误的情况下泄露:只需过时的 libcurl、重定向到其他域和重用的连接。检查清单很简单:curl 和 libcurl 版本 8.21.0 及以上,requests 版本 2.31.0 及以上,urllib3 版本 1.26.19 或 2.2.2,最新的 libsoup,每个代理使用单独的会话,重定向在控制之中,以及一次实时捕获测试。此外,每个项目使用单独的访问权限,以便一次泄露只影响一个脚本,而不是整个余额。