Today I ran a workshop with our newest network administrators; Our topic was denial of service mitigation. We currently utilize Arbor Peakflow Threat Management System to detect and scrub inbound attacks. Arbor is a phenomenal system capable of amazing performance. With the right tuning, templates and bandwidth it’s virtually handsfree. However some motivated attackers manage to sneak through occasionally. My goal was to educate our team on the nature of denial of service attacks and manual operation of the Arbor system. The ultimate goal was sparking interest in security while ensuring our newest members can think on their feet when Arbor’s magic runs out. Through the workshop I escalated my attacks in terms of difficulty rather than volume. I didn’t stick to a concrete lesson plan when it came to crafting the attacks, instead I adapted my attacks to their reactions much like a real determined attacker would.
The first attack I tried was a simple tcp synflood with spoofed sources to port 80, I used hping to send the attack. Our Arbor Peakflow unit picked the attack up quickly as expected and our team off-ramped the target’s IP to the Arbor TMS unit for scrubbing manually. They knew an attack was coming and were actively monitoring instead of waiting for the Peakflow to assess the threat level and auto-mitigate. Our default mitigation templates enabled synflood protection so the attack was effectively stopped in it’s tracks as soon as they off-ramped.
I decided to launch a few other simple attacks to mess around. Then I went to a UDP flood with packets totaling 29 bytes, that’s 20 bytes for the IP header, 8 bytes for UDP header, 1 byte of payload, but not counting MAC 14 byte header, 4 byte CRC or the ethernet frame 8 byte preamble sequence. If you count those it’s 55 bytes. I used randomized spoofed source IPs and randomized source ports to hit our target on destination port 0. The reason for the 1 byte payload, was because I knew empty 28 byte UDP packets would get discarded due to existing filters, bit of cheating I suppose. The attack did sneak past the Arbor TMS, however the team targeted my byte size via blacklist filters and were able to stop it just a few minutes after it was launched. It was a good test to show they were thinking.
Next I decided to get sneaky and randomize the UDP packet size. It was pretty easy to accomplish with the following bash script:
PACKSIZE=`echo $RANDOM % 1500 | bc`;
hping3 --udp -i u1 -c 500 -d $PACKSIZE --rand-source xxx.xxx.xxx.xxx;
As you can see I generated a random number up to 1,500 and then used it as the packet size. I do this in a while loop and send 500 UDP packets of that size before generating a new packet size, again from random spoofed source IPs and random ports to destination port 0. This was a good way to throw off the team. They were now unable to simply target a single packet size. However they began to attempt to target my attack due to it’s fixed payload content, furthermore they targeted port 0 which isn’t ideal as it can block valid traffic. To block the payload they sampled it and saw it was filled with X characters. They also had to use a range for the source ports since I was randomizing them, here was the payload:
They were pretty successful, however I had another trick up my sleeve. I decided I would randomize the packet payload and the destination ports instead of using port 0:
PACKSIZE=`echo $RANDOM % 1500 | bc`;
RNDPORT=`echo $RANDOM % 65535 | bc`;
hping3 --udp -i u1 -p $RNDPORT -c 500 -d $PACKSIZE --file /dev/urandom --rand-source xxx.xxx.xxx.xxx;
My changes introduced another random number, up to 65535 for the random destination port. Furthermore to fill my packet’s payload I read data from /dev/urandom. This is a special file used as a blocking pseudorandom number generator, it uses entropy from environmental noise sources. A faster attack could use openssl to generate random data as it’s quicker than reading /dev/urandom, this was suggested by a colleague who I was chatting with on the side at the time.
So how effective was this? My attack has the following characteristics:
- UDP stateless protocol capable of spoofed sources.
- Source IPv4 address spoofed for every packet.
- Source port randomized for every packet.
- Packet size randomized every 500 packets.
- Payload randomized from /dev/urandom per packet, not per 500 packets as it will continue reading /dev/urandom for each packet it generates.
- Destination ports randomized every 500 packets.
This means my team using Arbor had the following challenges:
- Incapable of using basic blacklists to filter out the attack by static source ip/port or packet size.
- Incapable of using basic blacklists to filter out the attack by static destination ports.
- Incapable of using zombie filters to block the attack based on bytes/pps per unique ip address.
- Incapable of using payload filtering due to randomized payload.
- Incapable of using various invalid/malformed packet countermeasures.
Possible solutions included:
- Blocking all UDP traffic. This is effectively a DoS attack on it’s own if you need UDP for specific services (DNS, NTP, SNMP, TFTP, etc…)
- Blocking all UDP ports higher than 1024, this is somewhat effective, however attacker can just randomize within 1-1024 and still cause chaos.
- Blocking all UDP traffic and punching holes for specific services, such as DNS on port 53. This has it’s own set of challenges as attacker can now shift his attack to target the open port, i.e DNS port 53 which are now whitelisted. The team was able to enable DNS malformed filtering, which did block my randomized UDP flood against DNS port 53. Arbor picked up the flood as malformed DNS traffic. However attacker could effectively flood DNS with valid randomized requests, it won’t necessarily be as effective at choking up the server, but will impact the service you’re whitelisting. Though I did not take the time to proof of concept this.
- Blackhole the targeted IP address. This is crude since communications with that IP may be very important. However the TMS unit itself is limited by your line cards and total transit going to your destination, so other volumetric attacks will also cause you to blackhole.
Weaknesses of the attack include:
- Inability to use this attack in a Distributed Reflected Denial of Service (DRDoS) attack to generate large attack volume through amplification.
- Big bandwidth is required to take down very high performance targets or to operate at scale against multiple targets. It will be difficult to generate sufficient volume to cause saturation or resource starvation on the host. A big botnet is needed.
- Attacker would have to be dedicated enough to properly profile the target throughout the attack to know how they’re attack is being challenged. This is a time/effort intensive attack.
In conclusion I would say that the team performed very well, but it shows that attacks are a fact of life and nothing is foolproof.