Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-34207 — SSRF过滤器检查了主机名文本,但实际目的地是由后续的DNS解析决定的。这个漏洞使得攻击者控制的Webhook URL能够访问回环地址、元数据以及私有网络目标。 | Kitploit
工具/GitHubGitHub/0xmrma/cve-2026-34207
漏洞分析漏洞利用Web安全渗透测试论文与研究学习与教育
GitHub0xmrma/cve-2026-34207

CVE-2026-34207

SSRF过滤器检查了主机名文本,但实际目的地是由后续的DNS解析决定的。这个漏洞使得攻击者控制的Webhook URL能够访问回环地址、元数据以及私有网络目标。

查看仓库
12个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-34207

SSRF过滤器检查了主机名字符串,但实际目的地是由后续的DNS决定的。这一漏洞使得攻击者控制的Webhook URL能够到达回环地址、元数据服务和私有网络目标。

介绍

我在审查Typebot(一个开源聊天机器人构建器)时发现了这个漏洞,心中带着一个简单的安全问题:

如果SSRF保护验证的是主机名字符串,而实际目的地是由后续的DNS决定的,会发生什么?

在这个案例中,这个问题引出了一个真正的漏洞。

Typebot 的 Webhook / HTTP 请求块的 SSRF 保护仅验证了:

  • URL 字符串,
  • 封禁了主机名字面量,
  • 以及字面量 IP 格式

它没有在允许请求之前解析主机名。

这意味着像 ssrf-repro.example 这样的主机名在验证时看起来无害,但随后可能解析为:

  • 127.0.0.1
  • 169.254.169.254
  • 或 RFC1918/私有网络空间

并且仍然会被后端 HTTP 客户端获取。

这个问题成为了 CVE-2026-34207。

Typebot: Typebot on GitHub
CVE: CVE-2026-34207
修复版本: 3.16.0

这影响了Typebot,一个被广泛使用的开源聊天机器人平台。在其官方网站上,Typebot 被宣传为受全球 650+ 家公司信赖。该网站还宣称拥有 200 万+ 月聊天量 和 150 万+ 已发布的机器人。

photo0

攻击链

攻击者控制的 Webhook URL -> 主机名通过仅验证字面量的 SSRF 检查 -> 在允许判定前未进行 DNS 解析 -> 后端 HTTP 客户端将主机名解析为内部目标 -> 服务端请求到达回环地址 / 元数据服务 / 私有网络 -> 响应数据通过执行日志变得可用


Typebot 的功能

Typebot 是一个聊天机器人构建器。

它允许用户创建可以执行以下操作的流程:

  • 提问
  • 收集结构化输入
  • 调用外部服务
  • 串联业务逻辑
  • 并通过 Webhook / HTTP 请求块触发出站 HTTP 请求

这意味着出站请求执行是一个真正的安全边界。

这里的关键问题不是 Typebot 是否支持 Webhook 块。

真正的问题是:

SSRF 保护验证的是服务器将要连接的实际目的地,还是只是 URL 中出现的主机名字符串?

在这个案例中,它首先只验证了文本形式。

这就是错误所在。


为什么这个攻击面值得关注

SSRF 防御以非常可预测的方式失效。

大多数时候,有趣的错误不是:

  • "你忘了封禁 169.254.169.254"
  • 或者 "你忘了封禁 localhost"

更强的错误是边界错误:

  • 验证发生在规范化之前
  • 验证发生在重定向之前
  • 验证发生在 DNS 解析之前
  • 验证发生在一个表示上,但网络栈使用了另一个

这正是需要检查的地方。

Typebot 已经拥有针对字面量元数据 IP、回环、私有范围和编码 IP 技巧的 SSRF 强化逻辑。

这使得下一个问题显而易见:

如果主机名本身不是危险的,但后来解析到了一个危险的目的地,会发生什么?

这正是发生的情况。


根本原因

根本问题是基于主机名字符串而非已解析 IP 地址的目的地验证。

在易受攻击的实现中,validateHttpReqUrl():

  • 解析了 URL
  • 只允许 http: 和 https:
  • 封禁了一小部分字面量主机名,例如 metadata.google.internal、metadata.goog、metadata 和 localhost
  • 检测字面量十进制 / 十六进制 / 八进制 IP 技巧
  • 解析字面量 IPv4 / IPv6 地址
  • 仅当主机名本身已经是字面量 IP 时才验证该地址

这是关键部分。

如果主机名是一个普通值,例如:

ssrf-repro.example

那么 parseIPAddress(hostname) 返回 null,验证器就此停止。

在批准之前没有进行 DNS 解析。

因此,脆弱的逻辑实际上简化为:

root@kitploit:~
const ip = parseIPAddress(hostname);
if (ip) {
  validateIPAddress(ip);
}

这意味着:

  • 字面量危险 IP 被封禁
  • 编码的危险 IP 被封禁
  • 但解析为危险 IP 的主机名未被封禁

漏洞的另一半在执行路径中。

在 executeHttpRequest() 中,Typebot 首先运行验证,然后稍后使用 ky(request.url, ...) 执行实际请求。

因此,顺序是:

  • 验证 URL 字符串
  • 接受主机名
  • 稍后在真实出站请求期间解析主机名
  • 连接到已解析的内部目标

这就是完整的漏洞。


为什么这是一个安全问题,而不仅仅是不完整的过滤

重要的区别在于信任决策是在哪里做出的。

许多漏洞如果描述不当,看起来都很小。

如果你把这个漏洞描述为:

“主机名过滤器不完整”

听起来像是一个质量问题。

但这并不是真正的问题。

真正的问题是:

  • 服务器在知道实际目的地之前就做出了安全决策
  • 网络栈稍后连接到了其他地方
  • 并且应用程序将该请求视为有效

这不是表面的过滤弱点。

这是一个信任边界失败。

而且由于 HTTP 执行器在执行日志中记录了响应数据,这个问题在最严重的情况下甚至不是盲目的。

所以这不只是:

  • “发生了意外的内部流量”

而是:

  • 内部流量发生了
  • 并且攻击者通常可以通过正常应用程序行为恢复证明和响应内容

这是一个真正的 SSRF 漏洞。


概念验证

我使用了两个验证层,因为它们展示了两个不同方面。

PoC 1:自包含本地解析器演示

第一个 PoC 清晰地隔离了根本原因。

我使用了一个小型本地测试框架,该框架:

  • 在 127.0.0.1 上启动了一个回环 HTTP 服务器
  • 验证了诸如 http://ssrf-repro.example:18080/... 这样的 URL
  • 使用受控解析器,使得 ssrf-repro.example 解析为 127.0.0.1
  • 然后执行请求

这精确演示了缺陷:

  • 验证通过,因为主机名不是字面量封禁值
  • 后续请求仍然到达了回环地址

捕获的输出显示:

  • 验证结果:通过
  • 请求执行结果:到达回环
  • 从回环服务返回的响应体

这直接证明了验证的缺口。


PoC 2:真实的 Typebot 执行路径

第二个 PoC 通过实际的功能路径展示了漏洞,这才是关键。

最简单的复现方法是:

  1. 在 Typebot 后端解析 DNS 的机器上,将一个良性主机名映射到回环地址
  2. 启动一个本地 HTTP 服务
  3. 创建一个指向该良性主机名的 Webhook 块
  4. 通过正常的经过身份验证的预览或实时执行路径触发该块

一个代表性的块如下所示:

root@kitploit:~
{
  "id": "blk-webhook",
  "type": "Webhook",
  "options": {
    "webhook": {
      "method": "GET",
      "url": "http://ssrf-repro.example:8000/"
    }
  }
}

配合如下的 hosts 文件条目:

root@kitploit:~
127.0.0.1 ssrf-repro.example

验证器仍然接受了该 URL,因为:

  • ssrf-repro.example 不在 blockedHostnames 中
  • 它不是 localhost
  • parseIPAddress("ssrf-repro.example") 返回 null
  • 没有进行目的地 IP 验证

然后后端 HTTP 客户端将主机名解析为 127.0.0.1 并仍然连接了。

这确立了完整的论断:

  • 易受攻击的验证逻辑在实际功能使用中是可达的
  • 请求命中了被禁止的目的地类别
  • 并且应用程序仍然将其视为一次成功的出站 HTTP 请求

为什么选择这两个 PoC

第一个 PoC 证明了根本原因。

第二个 PoC 证明了产品影响。

这种区分很重要。

如果你只展示:

“这个过滤器接受了一个主机名”

你展示得还不够。

如果你只展示:

“发生了一次内部请求”

你没有隔离原因。

更全面的报告是:

  • 基于主机名的验证接受了一个本不应被信任的值
  • 后续的 DNS 解析改变了该值的实际安全含义
  • 后端连接到了一个被禁止的目的地
  • 并且功能路径仍然完成

这是完整的故事。


严重性与分类

该问题被合理分类为高。

公告分类为:

  • CWE-918: 服务器端请求伪造 (SSRF)
  • CWE-20: 输入验证不当
  • CVSS:
root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L

这说得通。

这本身不是一个未经身份验证的互联网范围的 SSRF。

所需的权限为低,因为独立漏洞需要一个能够配置或触发 Webhook / HTTP 请求块的参与者。

但是在这个边界内,影响是严重的:

  • 回环访问
  • 私有网络访问
  • 元数据访问
  • 以及通过日志的数据泄露

这本身就是一个强 SSRF 问题。

而且当与其他扩大可达性的漏洞结合时,它变得更加危险。


为什么这仍然值得报告

有些人看到经过身份验证的 SSRF 就立即低估它。

这是一个错误。

真正的问题不是:

“攻击者是否已登录?”

真正的问题是:

“那个攻击者能否让服务器连接到安全模型本应禁止的地方?”

在这里,答案是肯定的。

验证器声称保护:

  • 元数据服务
  • 回环地址
  • RFC1918 私有范围
  • IPv6 本地范围

但一个主机名解析缺口让这些相同目的地通过另一种表示重新回来。

这正是那种值得获得 CVE 的漏洞。


修复分析

修复是扎实的,因为它纠正了真正的边界,而不仅仅是症状。

在修补后的实现中,validateHttpReqUrl() 被修改为在批准请求之前解析主机名。

验证器现在:

  • 从 node:dns/promises 导入 lookup
  • 将验证视为异步
  • 在允许之前解析非字面量主机名
  • 解析每个解析后的地址
  • 对每个解析后的地址针对相同的封禁范围进行验证

这是正确的修复,因为它将信任决策从:

  • “主机名字符串看起来可以吗?”

改为:

  • “实际目的地是否解析为一个允许的地址?”

这是从一开始就应该存在的安全属性。

修复还增加了针对以下方面的回归测试:

  • 解析为回环的主机名
  • 解析为 RFC1918 空间的主机名
  • 为自托管用户提供的允许列表内部主机
  • 保留对元数据和回环目标的不可绕过保护

这是你希望在真实 SSRF 修复中看到的强化方式:

  • 边界被纠正
  • 预期行为在代码中有文档说明
  • 并且测试锁定了该漏洞类别

该问题已在 Typebot 3.16.0 中解决。


披露

该问题通过 GitHub 的安全报告流程私下报告。

报告内容包括:

  • validateHttpReqUrl() 中的根本原因
  • executeHttpRequest() 中的下游执行路径
  • 使用主机名解析到回环 / 私有目标的可复现策略
  • 以及一个自包含的演示,用于隔离验证缺口

维护人员接受了该问题,修复了验证逻辑,该漏洞后来被发布为:

CVE-2026-34207

修复版本已发布在 Typebot 3.16.0 中。


这个漏洞实际上教会了我们什么

关键教训很简单:

安全决策必须基于网络栈实际使用的相同表示。

这听起来很明显。

但许多 SSRF 保护之所以失效,正是因为没有遵循这条规则。

  • 一个主机名字符串看起来安全。
  • DNS 改变了它的含义。
  • 请求仍然发出去了。

这就够了。

这个漏洞还强化了关于 SSRF 审查的重要一点:

  • 字面量 IP 过滤是不够的
  • 主机名黑名单是不够的
  • 编码 IP 检查是不够的

如果你不解析并验证实际目的地,你的 SSRF 过滤器仍然是不完整的。

这才是真正的收获。


关键要点

  • 当验证发生在目的地解析之前时,SSRF 防御会失效
  • 主机名字符串验证并不等同于目的地 IP 验证
  • Webhook / HTTP 请求功能是真正的安全边界
  • 经过身份验证的 SSRF 在到达元数据和内部服务时仍然可以是高严重性
  • 一份强有力的报告要连接根本原因和影响,而不仅仅是其中之一
  • 修复是正确的,因为它将决策移到了实际解析的目的地

最后的话

这个漏洞并不在于什么花哨的 payload。

而在于提出正确的边界问题。

在 Typebot 中,SSRF 验证器首先检查了主机名字符串。 实际目的地是由后续的 DNS 决定的。 网络客户端遵循了解析后的地址。

这个缺口就是漏洞。

这就是为什么它成为了 CVE-2026-34207。

已在 Typebot 3.16.0 中修复。

下载工具