[nsp-sec] SSDP fun (Ubiquiti)

Borja Marcos borjamar at sarenet.es
Wed Dec 5 05:48:17 EST 2018


Just slapping a router manufacturer (Ubiquiti) because of a really nasty variation of the UPnP/SSDP problem.

They offer two versions called “upnp” and “upnp2”. The first one replies to udp/1900 packets
and I’ve observed an amplification factor of 50.

10:38:28.401510 IP 192.168.1.21.33368 > 10.0.0.01.1900: UDP, length 90
10:38:28.417423 IP 10.0.0.01.57064 > 192.168.1.21.33368: UDP, length 433
10:38:28.517411 IP 10.0.0.01.57064 > 192.168.1.21.33368: UDP, length 442
10:38:28.618419 IP 10.0.0.01.57064 > 192.168.1.21.33368: UDP, length 505
10:38:28.721223 IP 10.0.0.01.52327 > 192.168.1.21.33368: UDP, length 477
10:38:28.822222 IP 10.0.0.01.55701 > 192.168.1.21.33368: UDP, length 442
10:38:28.922216 IP 10.0.0.01.55701 > 192.168.1.21.33368: UDP, length 481
10:38:29.022235 IP 10.0.0.01.36609 > 192.168.1.21.33368: UDP, length 513
10:38:29.120415 IP 10.0.0.01.42536 > 192.168.1.21.33368: UDP, length 442
10:38:29.220422 IP 10.0.0.01.42536 > 192.168.1.21.33368: UDP, length 501
10:38:29.323226 IP 10.0.0.01.35254 > 192.168.1.21.33368: UDP, length 495

To make it much worse, the replies are sent from *random ports* so no source port 1900
filtering. 

I’ve suggested them to phase out the “upnp” service. At least “upnp2” rejects requests
received on port 1900 through an interface configured as “wan”. 

Cheers,






Borja.



In case someone wants a script to test (not my work, I got it from
Cloudflare’s blog and I just added the ´\r\n’ empty field to the SSDP request.

https://blog.cloudflare.com/ssdp-100gbps/



#!/usr/bin/env python2.7
import socket
import sys

dst = "239.255.255.250"
if len(sys.argv) > 1:
    dst = sys.argv[1]
st = "upnp:rootdevice"
if len(sys.argv) > 2:
    st = sys.argv[2]

msg = [
    'M-SEARCH * HTTP/1.1',
    'Host:239.255.255.250:1900',
    'ST:ssdp:all',
    'Man:"ssdp:discover"',
    'MX:3',
    '\r\n']

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(10)
s.sendto('\r\n'.join(msg), (dst, 1900) )

while True:
    try:
        data, addr = s.recvfrom(32*1024)
    except socket.timeout:
        break
    print "[+] %s\n%s" % (addr, data)



More information about the nsp-security mailing list