Stupidly Simple DDoS Protocol (SSDP) generates 100 Gbps DDoS

10 minute read

Last month we shared statistics on some popular reflection attacks. Back then the average SSDP attack size was ~12 Gbps and largest SSDP reflection we recorded was:

  • 30 Mpps (millions of packets per second)
  • 80 Gbps (billions of bits per second)
  • using 940k reflector IPs

This changed a couple of days ago when we noticed an unusually large SSDP amplification. It's worth deeper investigation since it crossed the symbolic threshold of 100 Gbps.

The packets per second chart during the attack looked like this:

The bandwidth usage:

This packet flood lasted 38 minutes. According to our sampled netflow data it utilized 930k reflector servers. We estimate that the during 38 minutes of the attack each reflector sent 112k packets to Cloudflare.

The reflector servers are across the globe, with a large presence in Argentina, Russia and China. Here are the unique IPs per country:

$ cat ips-nf-ct.txt|uniq|cut -f 2|sort|uniq -c|sort -n|tail
   9103 IT
  10334 UA
  10824 KR
  14234 BR
  18962 CO
  19558 MY
  32850 CA
  41353 TW
  51222 US
  74825 AR
 135783 RU
 439126 CN

The reflector IP distribution across ASNs is typical. It pretty much follows the world’s largest residential ISPs:

$ cat ips-nf-asn.txt |uniq|cut -f 2|sort|uniq -c|sort -n|tail
   6377 12768  # RU JSC "ER-Telecom Holding"
   6604 3269   # IT Telecom Italia
   6840 8402   # RU OJSC "Vimpelcom"
   7070 10796  # US Time Warner Cable Internet
  11328 28573  # BR Claro SA
  18809 3816   # CO Colombia Telecomunicaciones
  19464 4788   # MY TM Net
  19518 6327   # CA Shaw Communications Inc.
  23823 3462   # TW Chunghwa Telecom
  72301 22927  # AR Telefonica de Argentina
  84781 4134   # CN China Telecom
 318405 4837   # CN China Unicom

What's SSDP anyway?

The attack was composed of UDP packets with source port 1900. This port is used by the SSDP and is used by the UPnP protocols. UPnP is one of the zero-configuration networking protocols. Most likely your home devices support it, allowing them to be easily discovered by your computer or phone. When a new device (like your laptop) joins the network, it can query the local network for specific devices, like internet gateways, audio systems, TVs, or printers. Read more on how UPnP compares to Bonjour.

UPnP is poorly standardised, but here's a snippet from the spec about the M-SEARCH frame - the main method for discovery:

When a control point is added to the network, the UPnP discovery protocol allows that control point to search for devices of interest on the network. It does this by multicasting on the reserved address and port ( a search message with a pattern, or target, equal to a type or identifier for a device or service.

Responses to M-SEARCH frame:

To be found by a network search, a device shall send a unicast UDP response to the source IP address and port that sent the request to the multicast address. Devices respond if the ST header field of the M-SEARCH request is “ssdp:all”, “upnp:rootdevice”, “uuid:” followed by a UUID that exactly matches the one advertised by the device, or if the M-SEARCH request matches a device type or service type supported by the device.

This works in practice. For example, my Chrome browser regularly asks for a Smart TV I guess:

$ sudo tcpdump -ni eth0 udp and port 1900 -A
IP > UDP, length 175  
MAN: "ssdp:discover"  
MX: 1  
ST: urn:dial-multiscreen-org:service:dial:1  
USER-AGENT: Google Chrome/58.0.3029.110 Windows  

This frame is sent to a multicast IP address. Other devices listening on that address and supporting this specific ST (search-target) multiscreen type are supposed to answer.

Apart from queries for specific device types, there are two "generic" ST query types:

  • upnp:rootdevice: search for root devices
  • ssdp:all: search for all UPnP devices and services

To emulate these queries you can run this python script (based on this work):

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

dst = ""  
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',
    'ST:%s' % (st,),

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)  
s.sendto('rn'.join(msg), (dst, 1900) )

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

On my home network two devices show up:

$ python
[+] ('', 1026)
HTTP/1.1 200 OK  
CACHE-CONTROL: max-age = 60  
SERVER: Network Printer Server UPnP/1.0 OS 06-17-2009  
ST: upnp:rootdevice  
USN: uuid:Samsung-Printer-1_0-mrgutenberg::upnp:rootdevice

[+] ('', 36319)
HTTP/1.1 200 OK  
Cache-Control: max-age=1800  
Content-Length: 0  
Server: Linux/3.2 UPnP/1.0 Network_Module/1.0 (RX-S601D)  
ST: upnp:rootdevice  
USN: uuid:9ab0c000-f668-11de-9976-000adedd7411::upnp:rootdevice  

The firewall

Now that we understand the basics of SSDP, understanding the reflection attack should be easy. You see, there are in fact two ways of delivering the M-SEARCH frame:

  • what we presented, over the multicast address
  • directly to a UPnP/SSDP enabled host on a normal unicast address

The latter method works. We can specifically target my printer IP address:

$ python
[+] ('', 1026)
HTTP/1.1 200 OK  
CACHE-CONTROL: max-age = 60  
SERVER: Network Printer Server UPnP/1.0 OS 06-17-2009  
ST: upnp:rootdevice  
USN: uuid:Samsung-Printer-1_0-mrgutenberg::upnp:rootdevice  

Now the problem is easily seen: the SSDP protocol does not check whether the querying party is in the same network as the device. It will happily respond to an M-SEARCH delivered over the public Internet. All it takes is a tiny misconfiguration in a firewall - port 1900 UDP open to the world - and a perfect target for UDP amplification will be available.

Given a misconfigured target our script will happily work over the internet:

$ python 100.42.x.x
[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK  
CACHE-CONTROL: max-age=120  
ST: upnp:rootdevice  
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::upnp:rootdevice  
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2  

The amplification

The real damage is done by the ssdp:all ST type though. These responses are much larger:

$ python 100.42.x.x ssdp:all
[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK  
CACHE-CONTROL: max-age=120  
ST: upnp:rootdevice  
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::upnp:rootdevice  
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2  

[+] ('100.42.x.x', 1900)
HTTP/1.1 200 OK  
CACHE-CONTROL: max-age=120  
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1  
USN: uuid:3e55ade9-c344-4baa-841b-826bda77dcb2::urn:schemas-upnp-org:device:InternetGatewayDevice:1  
SERVER: TBS/R2 UPnP/1.0 MiniUPnPd/1.2  

... 6 more response packets....

In this particular case, a single SSDP M-SEARCH packet triggered 8 response packets. tcpdump view:

$ sudo tcpdump -ni en7 host 100.42.x.x -ttttt
 00:00:00.000000 IP > 100.42.x.x.1900: UDP, length 88
 00:00:00.197481 IP 100.42.x.x.1900 > UDP, length 227
 00:00:00.199634 IP 100.42.x.x.1900 > UDP, length 299
 00:00:00.202938 IP 100.42.x.x.1900 > UDP, length 295
 00:00:00.208425 IP 100.42.x.x.1900 > UDP, length 275
 00:00:00.209496 IP 100.42.x.x.1900 > UDP, length 307
 00:00:00.212795 IP 100.42.x.x.1900 > UDP, length 289
 00:00:00.215522 IP 100.42.x.x.1900 > UDP, length 291
 00:00:00.219190 IP 100.42.x.x.1900 > UDP, length 291

That target exposes 8x packet count amplification and 26x bandwidth amplification. Sadly, this is typical for SSDP.

IP Spoofing

The final step for the attack is to fool the vulnerable servers to flood the target IP - not the attacker. For that the attacker needs to spoof the source IP address on their queries.

We probed the reflector IPs used in the shown 100 Gbps+ attack. We found that out of the 920k reflector IPs, only 350k (38%) still respond to SSDP probes.

Out of the reflectors that responded, each sent on average 7 packets:

$ cat results-first-run.txt |cut -f 1|sort|uniq -c|sed -s 's#^ +##g'|cut -d " " -f 1| ~/mmhistogram -t "Response packets per IP" -p
Response packets per IP min:1.00 avg:6.99 med=8.00 max:186.00 dev:4.44 count:350337  
Response packets per IP:  
 value |-------------------------------------------------- count
     0 |                    ****************************** 23.29%
     1 |                                              ****  3.30%
     2 |                                                **  2.29%
     4 |************************************************** 38.73%
     8 |            ************************************** 29.51%
    16 |                                               ***  2.88%
    32 |                                                    0.01%
    64 |                                                    0.00%
   128 |                                                    0.00%

The response packets had 321 bytes (+/- 29 bytes) on average. Our request packets had 110 bytes.

According to our measurements with the ssdp:all M-SEARCH attacker would be able to achieve:

  • 7x packet number amplification
  • 20x bandwidth amplification

We can estimate the 43 Mpps/112 Gbps attack was generated with roughly:

  • 6.1 Mpps of spoofing capacity
  • 5.6 Gbps of spoofed bandwidth

In other words: a single well connected 10 Gbps server able to perform IP spoofing can deliver a significant SSDP attack.

More on the SSDP servers

Since we probed the vulnerable SSDP servers, here are the most common Server header values we received:

 104833 Linux/2.4.22-1.2115.nptl UPnP/1.0 miniupnpd/1.0
  77329 System/1.0 UPnP/1.0 IGD/1.0
  66639 TBS/R2 UPnP/1.0 MiniUPnPd/1.2
  12863 Ubuntu/7.10 UPnP/1.0 miniupnpd/1.0
  11544 ASUSTeK UPnP/1.0 MiniUPnPd/1.4
  10827 miniupnpd/1.0 UPnP/1.0
   8070 Linux UPnP/1.0 Huawei-ATP-IGD
   7941 TBS/R2 UPnP/1.0 MiniUPnPd/1.4
   7546 Net-OS 5.xx UPnP/1.0
   6043 LINUX-2.6 UPnP/1.0 MiniUPnPd/1.5
   5482 Ubuntu/lucid UPnP/1.0 MiniUPnPd/1.4
   4720 AirTies/ASP 1.0 UPnP/1.0 miniupnpd/1.0
   4667 Linux/, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
   3334 Fedora/10 UPnP/1.0 MiniUPnPd/1.4
   2814  1.0
   2044 miniupnpd/1.5 UPnP/1.0
   1330 1
   1325 Linux/, UPnP/1.0, Portable SDK for UPnP devices/1.6.6
    843 Allegro-Software-RomUpnp/4.07 UPnP/1.0 IGD/1.00
    776 Upnp/1.0 UPnP/1.0 IGD/1.00
    675 Unspecified, UPnP/1.0, Unspecified
    648 WNR2000v5 UPnP/1.0 miniupnpd/1.0
    562 MIPS LINUX/2.4 UPnP/1.0 miniupnpd/1.0
    518 Fedora/8 UPnP/1.0 miniupnpd/1.0
    372 Tenda UPnP/1.0 miniupnpd/1.0
    346 Ubuntu/10.10 UPnP/1.0 miniupnpd/1.0
    330 MF60/1.0 UPnP/1.0 miniupnpd/1.0

The most common ST header values we saw:

 298497 upnp:rootdevice
 158442 urn:schemas-upnp-org:device:InternetGatewayDevice:1
 151642 urn:schemas-upnp-org:device:WANDevice:1
 148593 urn:schemas-upnp-org:device:WANConnectionDevice:1
 147461 urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1
 146970 urn:schemas-upnp-org:service:WANIPConnection:1
 145602 urn:schemas-upnp-org:service:Layer3Forwarding:1
 113453 urn:schemas-upnp-org:service:WANPPPConnection:1
 100961 urn:schemas-upnp-org:device:InternetGatewayDevice:
 100180 urn:schemas-upnp-org:device:WANDevice:
  99017 urn:schemas-upnp-org:service:WANCommonInterfaceConfig:
  98112 urn:schemas-upnp-org:device:WANConnectionDevice:
  97246 urn:schemas-upnp-org:service:WANPPPConnection:
  96259 urn:schemas-upnp-org:service:WANIPConnection:
  93987 urn:schemas-upnp-org:service:Layer3Forwarding:
  91108 urn:schemas-wifialliance-org:device:WFADevice:
  90818 urn:schemas-wifialliance-org:service:WFAWLANConfig:
  35511 uuid:IGD{8c80f73f-4ba0-45fa-835d-042505d052be}000000000000
   9822 urn:schemas-upnp-org:service:WANEthernetLinkConfig:1
   7737 uuid:WAN{84807575-251b-4c02-954b-e8e2ba7216a9}000000000000
   6063 urn:schemas-microsoft-com:service:OSInfo:1

The vulnerable IPs are seem to be mostly unprotected home routers.

Open SSDP is a vulnerability

It's not a novelty that allowing UDP port 1900 traffic from the Internet to your home printer or such is not a good idea. This problem has been known since at least January 2013:

Authors of SSDP clearly didn't give any thought to UDP amplification potential. There are a number of obvious recommendations about future use of SSDP protocol:

  • The authors of SSDP should answer if there is any real world use of unicast M-SEARCH queries. From what I understand M-SEARCH only makes practical sense as a multicast query in local area network.

  • Unicast M-SEARCH support should be either deprecated or at least rate limited, in similar way to DNS Response Rate Limit techniques.

  • M-SEARCH responses should be only delivered to local network. Responses routed over the network make little sense and open described vulnerability.

In the meantime we recommend:

  • Network administrators should ensure inbound UDP port 1900 is blocked on firewall.

  • Internet service providers should never allow IP spoofing to be performed on their network. IP spoofing is the true root cause of the issue. See the infamous BCP38.

  • Internet service providers should allow their customers to use BGP flowspec to rate limit inbound UDP source port 1900 traffic, to relieve congestion during large SSDP attacks.

  • Internet providers should internally collect netflow protocol samples. The netflow is needed to identify the true source of the attack. With netflow it's trivial to answer questions like: "Which of my customers sent 6.4Mpps of traffic to port 1900?". Due to privacy concerns we recommend collecting netflow samples with largest possible sampling value: 1 in 64k packets. This will be sufficient to track DDoS attacks while preserving decent privacy of single customer connections.

  • Developers should not roll out their own UDP protocols without careful consideration of UDP amplification problems. UPnP should be properly standardized and scrutinized.

  • End users are encouraged to use the script scan their network for UPnP enabled devices. Consider if these devices should be allowed to access to the internet.

Furthermore, we prepared on online checking website. Click if you want to know if your public IP address has a vulnerable SSDP service:

Sadly, the most unprotected routers we saw in the described attack were from China, Russia and Argentina, places not historically known for the most agile internet service providers.


Cloudflare customers are fully protected from SSDP and other L3 amplification attacks. These attacks are nicely deflected by Cloudflare anycast infrastructure and require no special action. Unfortunately the raising of SSDP attack sizes might be a tough problem for other Internet citizens. We should encourage our ISPs to stop IP spoofing within their network, support BGP flowspec and configure in netflow collection.

This article is a joint work of Marek Majkowski and Ben Cartwright-Cox.

Dealing with large attacks sounds like fun? Join our world famous DDoS team in London, Austin, San Francisco and our elite office in Warsaw, Poland.



Spotlight on Women in Cybersecurity

less than 1 minute read

Sucuri is committed to helping women develop their careers in technology. On International Women’s Day, Sucuri team members share their insights into workin...

Hacked Website Trend Report – 2018

less than 1 minute read

We are proud to be releasing our latest Hacked Website Trend Report for 2018. This report is based on data collected and analyzed by the GoDaddy Security / ...