This is a post I wrote for O'Reilly back in January 2003 when the SQL Slammer worm hit. It seems it's gone from their site now, so I'm putting it here, including the comments.
Here in Europe, the MS SQL worm hit early Saturday morning. Of the four networks that I manage or help manage, three had a small number of hosts that were infected. On each network, the results were different.
On the first network, the Cisco 7200 routers became extremely slow because of all the traffic generated by the worm. This was so bad the router sometimes didn't get around to sending BGP keep-alive packets in time, so the BGP session broke. This meant the router was unable to advertise the network's IP address ranges to the rest of the world, with the result that these addresses became unreachable.
Under normal circumstances, a Cisco 7200 router can forward several hundred megabits worth of traffic. However, the packets the worm generates are relatively small (404 bytes from what I observed), and because one of the routers in this network was starved for memory, it didn't run the Cisco Express Forwarding (CEF) algorithm. This made the problem worse because without CEF, the router must take time to create a "route cache" for each destination in order to forward packets at high speed. Since the worm generates random destination addresses, the router ended up spending most of its time creating these route cache entries, and it ran out of memory to boot. Most important lesson: always use packet forwarding algorithms with good worst-case properties; cache or flow-based algorithms are dangerous.
But I'm getting ahead of things: I didn't know I was dealing with a worm at that time. We suspected a denial-of-service (DoS) attack, but when I looked at the traffic counters I noticed there was more traffic coming out of the network than going in! I quickly installed a filter for logging purposes:
!
access-list 140 permit ip any any log-input
!
interface ethernet0/0
ip access-group 140 in
!
This filter doesn't filter anything, but it does log a sample of the traffic coming in on the interface to the router's log buffer:
7w1d: %SEC-6-IPACCESSLOGP: list 140 permitted udp 192.168.3.172(1189)
(Ethernet0 0001.0229.23b6) -> 223.183.47.3(1434), 1 packet
I could now see which hosts were sending out the offending traffic (something like 70 megabits of it) so I could filter all packets with those hosts as the source:
!
access-list 140 deny ip host 192.168.3.172 any
access-list 140 permit ip any any
!
Obviously, inspecting packets to see if they should be forwarded or dropped (filtered out) takes additional CPU time, but dropping the packet immediately as it comes in on an interface takes much less CPU time than forwarding it or trying to forward it. So with this filter in place the network returned to normal, more or less. But I suspected there was more to this, so I had a look at the most recent messages posted to the North American Network Operators Group (NANOG) mailing list. There, people mentioned a new worm operating on UDP port 1434. So I changed the filter to look for UDP packets destined for port 1434:
!
access-list 140 deny udp any any eq 1434
access-list 140 permit ip any any
!
And this caught the worm's packets very well:
show access-list 140
Extended IP access list 140
deny udp any any eq 1434 (87352 matches)
permit ip any any (3103 matches)
It turned out that the entire code for the MS SQL worm is only a few hundred bytes and it's contained in a single UDP packet. The packet contains a request to the Microsoft SQL service that is malformed: a value is longer than it should be. The server doesn't check for this properly, so the excess data overwrites stack memory pointing to instructions that should be executed later.
This is how the worm tricks the server into executing the code contained in the packet. The executable code in the worm then simply generates random addresses and sends out copies of itself to these addresses. Unlike the TCP protocol that is used for most applications, such as the web and mail, UDP doesn't require a session establishment phase; a client request or server response can be contained in a single packet, so there is no waiting for a response before the next packet can be sent. Infected hosts simply send out copies of the worm as fast as they can. This easily can be upwards of 10,000 packets per second.
Another network I manage had just upgraded to fast Cisco 12000 routers. These could easily handle the additional 100 megabits worth of worm traffic as well as the typical 50 megabits or so of early Saturday morning traffic. I installed a filter anyway to spare the recipients the unwanted traffic. At one point on Saturday, 25 percent of all packets coming in were copies of the worm. And strangely enough, after the infected hosts were cleaned up, there were still one or two copies of the worm coming in from the internal network. It looks like the worm was also successful in spreading over broadcast and multicast addresses. This should prove an interesting subject for future study.
As is the case for very aggressive biological viruses (such as Ebola), the worm's success was also its downfall: each packet generated by the worm was targeted at the Microsoft SQL service, which lives on a (relatively) fixed UDP port. This makes the worm packets easy to filter out. The very high traffic volumes make it virtually impossible for the worm to remain undetected. A worm with a different agenda would have to spend resources doing other things than simply spreading, so it wouldn't spread as fast as this worm did--this one seems to have infected pretty much the entire Internet within a minute or so.
Showing messages 1 through 7 of 7.
I've tried to contact folks be no luck.
06/07-20:21:40.799922 68.54.56.49:1229
06/07-20:36:53.659166 69.2.246.10:65091
06/07-22:06:19.724612 206.15.136.224:3644
06/08-00:34:17.045298 68.8.168.37:1664
06/08-03:19:28.027834 61.196.121.145:1028
06/08-06:54:03.316317 212.172.49.170:2492
06/08-16:01:07.194212 63.138.52.131:3954
06/08-19:53:17.972262 202.88.65.73:3566
06/08-21:11:50.571431 200.35.80.94:1209
06/09-01:48:15.194826 67.161.240.97:3925
06/09-02:17:02.211840 217.97.46.137:3158
06/09-03:01:56.777486 210.84.85.223:1330
06/09-03:03:06.811523 212.172.49.170:2492
06/09-05:23:17.665997 210.15.187.12:1066
06/09-14:04:39.362386 210.3.132.195:1770
06/09-15:06:32.955797 80.55.208.50:8962
06/09-23:12:10.257125 212.172.49.170:2492
06/10-00:34:54.494105 141.28.4.77:1162
06/10-00:53:27.264823 167.206.72.228:1093
06/10-01:41:11.320126 217.96.234.158:4159
06/10-07:15:15.204397 24.218.1.12:1217
06/10-09:36:11.066524 64.200.53.111:3296
06/10-10:59:54.666694 130.228.2.189:1072
06/10-11:57:42.551742 209.208.242.162:4458
06/10-12:15:41.674662 202.99.48.55:1085
06/10-14:57:45.399817 212.211.99.7:1135
06/10-15:09:37.233633 209.242.37.83:4808
06/10-16:44:20.416211 129.42.4.239:3031
06/10-19:10:22.835916 32.101.181.82:1051
06/10-23:06:39.314753 12.224.191.100:4858
06/11-00:04:50.625605 213.100.27.24:2511
06/15-08:32:45.484685 82.43.50.217:1337
06/15-15:58:05.142420 217.117.52.169:3535
06/15-19:56:51.158776 24.136.153.94:1359
06/16-01:08:56.538307 202.118.212.20:1332
06/16-02:51:08.283797 172.202.129.144:1817
06/16-15:56:41.741120 67.194.107.179:1486
06/16-19:03:07.637510 194.0.57.124:1232
06/17-04:37:44.157832 210.58.80.47:3387
06/17-06:07:12.515323 194.67.26.118:1045
06/17-08:48:58.238406 32.100.134.95:1557
06/17-16:22:42.969146 64.185.196.81:6073
06/17-18:20:22.770553 200.175.179.142:1728
06/17-22:47:59.688180 172.176.155.48:4106
06/18-00:50:35.110709 218.194.84.183:1038
06/18-08:07:25.732447 194.67.26.118:1045
06/18-08:28:33.485342 65.33.129.71:1221
06/18-14:00:29.413525 64.146.131.71:1668
06/21-22:58:17.925622 202.133.227.115:1261
06/22-07:34:14.688396 210.58.80.47:3056
06/22-10:22:32.782964 65.160.42.5:1047
06/22-10:53:59.469958 220.98.233.171:1039
06/22-15:32:34.957718 219.95.191.49:4159