CVE-2026-54665:ApacheNiFi中的预认证主机头注入漏洞

admin 2026-06-23 06:21:00 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: CVE-2026-54665是ApacheNiFi中的预认证主机头注入漏洞,攻击者可通过X-Forwarded-Host或X-ProxyHost头操控OAuth2重定向URI等关键参数。该漏洞源于2025年重构时误删主机允许列表验证机制,影响0.0.1至2.9.0版本,在启用OIDC时可能导致账户接管(CVSS8.1)。官方已在2.10.0版本通过NIFI-15953修复,建议用户立即升级并验证代理配置。 综合评分: 85 文章分类: 漏洞分析,WEB安全,应用安全,云安全,威胁情报


cover_image

CVE-2026-54665:Apache NiFi 中的预认证主机头注入漏洞

Ots安全

2026年6月21日 11:55 广东

在小说阅读器读本章

去阅读

威胁简报

恶意软件

漏洞攻击

CVE-2026-54665:Apache NiFi 中的预认证主机头注入漏洞

发布日期:2026-06-20报告日期:2026-05-15严重性:5.4 中等(基线)/ 8.1 高(使用 OIDC)状态:已在 NiFi 2.10.0 中修复CWE:CWE-444(HTTP 请求解析不一致)+ CWE-601(开放重定向)

Apache NiFi 中存在预认证主机头注入漏洞。任何未经认证的客户端都可以发送 <host>X-Forwarded-Host或 X-ProxyHost<host> 值,并且该值会被 NiFi 为 OAuth2 重定向、SAML SP 实体、CSRF cookie 域和公共端点构建的 URI 所反映出来/nifi-api/authentication/configuration。受影响版本:0.0.1 至 2.9.0。已在 2.10.0 中修复。

有趣的地方不在于这个 bug 本身,而在于它是如何产生的。2025 年的一次重构(NIFI-14209)删除了HostHeaderHandler之前强制执行已记录nifi.web.proxy.host十年的允许列表的组件,并用一个仅验证端口的自定义程序取而代之。重构后,允许列表仍然出现在文档和配置中,但在运行时,没有任何程序会读取主机部分。

漏洞

nifi-commons/nifi-web-servlet-shared/src/main/java/org/apache/nifi/web/servlet/shared/StandardRequestUriProvider.java:97-115:

private String getHost(final HttpServletRequest request) { &nbsp; &nbsp;final String host; &nbsp; &nbsp;final String serverName = request.getServerName(); &nbsp; &nbsp;final String headerHost = getFirstHeader(request, &nbsp; &nbsp; &nbsp; &nbsp;ProxyHeader.PROXY_HOST, &nbsp; &nbsp; &nbsp; &nbsp;// X-ProxyHost &nbsp; &nbsp; &nbsp; &nbsp;ProxyHeader.FORWARDED_HOST, &nbsp; &nbsp;// X-Forwarded-Host &nbsp; &nbsp; &nbsp; &nbsp;ProxyHeader.HOST &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Host &nbsp; &nbsp;); &nbsp; &nbsp;if (headerHost == null) { &nbsp; &nbsp; &nbsp; &nbsp;host = serverName; &nbsp; &nbsp;} else { &nbsp; &nbsp; &nbsp; &nbsp;final Matcher matcher = HOST_PATTERN.matcher(headerHost); &nbsp; &nbsp; &nbsp; &nbsp;if (matcher.matches()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;host = matcher.group(FIRST_GROUP); &nbsp; &nbsp; &nbsp; &nbsp;} else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;host = serverName; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;} &nbsp; &nbsp;return host;}

匹配模式为^([^:]+):?([1-9][0-9]{2,4})?$:。它接受主机部分不包含冒号的任何字符串。例如attacker.example.com:,,nifi-prod.example.com.evil-attacker.net。127.0.0.1全部匹配。没有允许列表检查。

对比一下同一文件getPath()往下几行的内容:它会对 <value> X-ProxyContextPath、 <value> X-Forwarded-Context<value> 进行验证,并在值不在允许列表中时抛出异常。主机检查只是忘记执行同样的操作了。X-Forwarded-Prefixnifi.web.proxy.context.pathIllegalArgumentException

不验证主机的允许列表

NiFiProperties.java:1603-1614将属性解析nifi.web.proxy.host成列表:

public List<String> getAllowedHostsAsList() { &nbsp; &nbsp;String rawProperty = getProperty(WEB_PROXY_HOST, ""); &nbsp; &nbsp;List<String> hosts = Arrays.asList(rawProperty.split(",")); &nbsp; &nbsp;return hosts.stream() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.map(this::normalizeHost) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.filter(host -> !StringUtils.isBlank(host)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.collect(Collectors.toList());}

唯一的调用者是FrameworkServerConnectorFactory.getValidPorts(),它仅从每个条目中提取端口,以构建 Jetty 监听器接受的端口集:

private static Set<Integer> getValidPorts(final NiFiProperties properties) { &nbsp; &nbsp;final Set<Integer> validPorts = new HashSet<>(); &nbsp; &nbsp;final int serverPort = getPort(properties); &nbsp; &nbsp;validPorts.add(serverPort); &nbsp; &nbsp;final List<String> allowedHosts = properties.getAllowedHostsAsList(); &nbsp; &nbsp;for (final String allowedHost : allowedHosts) { &nbsp; &nbsp; &nbsp; &nbsp;final Matcher portMatcher = HOST_PORT_PATTERN.matcher(allowedHost); &nbsp; &nbsp; &nbsp; &nbsp;if (portMatcher.matches()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final String portGroup = portMatcher.group(PORT_GROUP); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;final int allowedPort = Integer.parseInt(portGroup); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;validPorts.add(allowedPort); &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;} &nbsp; &nbsp;return validPorts;}

因此,如果操作员阅读了管理指南中关于主机配置的部分nifi.web.proxy.host,将其设置为某个值nifi.example.com,nifi-internal.example.com,并认为 NiFi 会拒绝其他主机值的请求,那就错了。NiFi 仅使用这些配置来了解哪些端口是有效的。

概念验证

服务器:apache-nifi-2.9.0-bin.zip以默认设置启动conf/nifi.properties(仅nifi.web.https.port=18443更改以释放默认端口)。单用户模式,HTTPS 已启用127.0.0.1:18443。

基线:

$ curl -sk --resolve localhost:18443:127.0.0.1 -H 'Accept: application/json' \ &nbsp; &nbsp;https://localhost:18443/nifi-api/authentication/configuration{"authenticationConfiguration":{"externalLoginRequired":false,"loginSupported":true, "loginUri":"https://localhost:18443/nf/#/login", "logoutUri":"https://localhost:18443/nifi-api/access/logout/complete"}}

和X-Forwarded-Host:

$ curl -sk --resolve localhost:18443:127.0.0.1 -H 'Accept: application/json' \ &nbsp; &nbsp;-H 'X-Forwarded-Host: attacker.example.com' \ &nbsp; &nbsp;https://localhost:18443/nifi-api/authentication/configuration{"authenticationConfiguration":{"externalLoginRequired":false,"loginSupported":true, "loginUri":"https://attacker.example.com:18443/nf/#/login", "logoutUri":"https://attacker.example.com:18443/nifi-api/access/logout/complete"}}

和X-ProxyHost:

$ curl -sk --resolve localhost:18443:127.0.0.1 -H 'Accept: application/json' \ &nbsp; &nbsp;-H 'X-ProxyHost: evil.example.com' \ &nbsp; &nbsp;https://localhost:18443/nifi-api/authentication/configuration{"authenticationConfiguration":{"externalLoginRequired":false,"loginSupported":true, "loginUri":"https://evil.example.com:18443/nf/#/login", "logoutUri":"https://evil.example.com:18443/nifi-api/access/logout/complete"}}

值得注意的是:TLS 层 Host 头部得到了正确的控制。即使请求的Host: attacker.example.comSNI 匹配,也会被拒绝,Error 400 Invalid SNI因为 JettySecureRequestCustomizer强制执行了 SNI 对抗 Host 的机制。这种防御机制涵盖了 TLS 层 Host 头部。但它并不涵盖上面提到的两个 HTTP 应用层头部,而这两个头部正是 NiFi 前端的反向代理会从不受信任的客户端转发的头部。

下游

RequestUriBuilder.fromHttpServletRequest()在 NiFi 框架的 26 个站点中被调用。反射主机会遍历所有这些站点。安全关键型站点包括:

请求网站     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;它所构建的StandardOAuth2AuthorizationRequestResolver.java:97   redirect_uri已向 OIDC 身份提供商发送OAuth2请求StandardRelyingPartyRegistrationResolver.java:114    AuthnRequest 中的 SAML SP 实体和 ACS URIOidcAuthenticationSuccessHandler.java:102, 105   OIDC 重定向目标Saml2AuthenticationSuccessHandler.java:103, 106   SAML重定向目标OidcLogoutSuccessHandler.java:213  OIDC 注销后重定向目标StandardCookieCsrfTokenRepository.java:71  CSRF cookie URI,用于推导 cookie 域AuthenticationResource.java:99 匿名/nifi-api/authentication/configuration回复FlowResource.java:398, 2621   内容查看器 URIApplicationResource.java:173, 187, 329 用于集群复制的请求 URI

已验证的影响是匿名/authentication/configuration反射。值得关注的是 OAuth2 redirect_uri。对于启用了 OIDC 的部署,redirect_uri发送给身份提供商 (IdP) 的数据来自攻击者可控制的主机。如果 IdP 接受未注册的重定向 URI,或者对已注册的 URI 不进行通配符匹配(这种情况比您想象的要常见),攻击者就可以控制授权码的发送位置。这就是 5.4 版本中等影响的反射漏洞和 8.1 版本高影响的账户接管漏洞之间的区别。

它是如何来到这里的:NIFI-14209

提交ae5a77b84f5c7e5e51e85e99f1d40079dbdee5f1于 2025 年 2 月 5 日,标题为“重构主机头验证”。提交信息如下:

将 HostHeaderHandler 替换为 HostPortValidatorCustomizer。Jetty SecureRequestCustomizer 强制执行使用服务器证书 DNS 主题备用名称 (SNI) 的主机验证。添加了针对无效主机和端口值的 TLS SNI 的测试。重构并简化了 RequestUriBuilder.fromHttpServletRequest() 方法。

此次删除的差异代码HostHeaderHandler.java共 318 行,是 JettyHandler之前用于处理nifi.web.proxy.host列表并拒绝主机值超出列表范围的请求的代码。替换后的代码HostPortValidatorCustomizer.java共 85 行,仅用于验证端口。

前提是它SecureRequestCustomizer涵盖了通过 TLS SNI 进行的主机验证。这个前提对于 TLS 层的 Host 头部来说是正确的。但它并不适用于接下来读取的两个应用层头部(host 和X-Forwarded-Hosthost X-ProxyHost)StandardRequestUriProvider.getHost()。重构移动了信任边界,但没有更新另一侧的读取器。

受影响的版本

Apache NiFi 0.0.1 至 2.9.0 版本(根据官方公告,存在漏洞)

Apache NiFi 2.10.0(已修复)

引入此回归的 NIFI-14209 提交于 2025 年 2 月发布。2.2.0 之前的版本保留了原有的HostHeaderHandler防御机制;此回归是从该版本开始的。

修复

NiFi 2.10.0(Jira NIFI-15953,PR #11268)重新添加了允许列表验证,这次除了 Host 标头之外X-ProxyHost,还覆盖了其他标头。此修复与之前针对 context-path 标头的处理方式一致。公告文本如下:X-Forwarded-HostgetPath()

Apache NiFi 2.10.0 基于 nifi.web.proxy.host 属性实现了对 X-ProxyHost 和 X-Forwarded-Host HTTP 请求头的验证。启用请求头验证需要将应用程序配置为使用 HTTPS。位于 Apache NiFi 前端的反向代理服务器负责过滤输入请求头,并将允许的值提供给应用程序。

对于使用 2.2.0 到 2.9.0 版本且无法立即升级的运维人员,缓解措施是在反向代理上剥离这些标头X-Forwarded-Host,X-ProxyHost然后再将其传递到 NiFi。默认情况下nifi.properties不会对此发出警告;如果您在任何转发来自不受信任客户端的这些标头的服务器后运行 NiFi,请务必进行审计。

披露

已于 2026 年 5 月 15 日提交报告,[email protected]并附有上述实时复现步骤。Apache 方面迅速完成了漏洞分类和补丁开发。已分配 CVE 编号,PR 已合并,安全公告已于 2026 年 6 月 20 日发布。

链接

安全公告:https://nifi.apache.org/documentation/security/#CVE-2026-54665

CVE 记录:https://www.cve.org/CVERecord?id= CVE-2026-54665

NVD:https://nvd.nist.gov/vuln/detail/CVE-2026-54665

jira:https://issues.apache.org/jira/browse/NIFI-15953

修复 PR:https://github.com/apache/nifi/pull/11268

CWE-444:https://cwe.mitre.org/data/definitions/444.html

CWE-601:https://cwe.mitre.org/data/definitions/601.html

END

公众号内容都来自国外平台-所有文章可通过点击阅读原文到达原文地址或参考地址

排版 编辑 | Ots 小安

采集 翻译 | Ots Ai牛马

公众号 | AnQuan7 (Ots安全)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Ots安全 《CVE-2026-54665:Apache NiFi 中的预认证主机头注入漏洞》

评论:0   参与:  0