World of Warcraft Classic servers knocked offline by a DDoS (Sept 7th, 2019)

The goal of this article is to convince you there is a way to prevent SYN Flood DDoS attacks, spoofed source IP’s, and port scanning once and for all.

Heads up! This article has been written for highly technical people who work in network engineering, cyber security or IT architectural/infrastructure positions. A basic knowledge of IPv4, TCP and/or IPv6 is expected and a basic understanding of security tokens and firewall administration will also help. Also, mathematicians may be interested in the token generation section since they are needed to generate tokens within specified boundaries. If you are a math major, please scroll to the “Mathematicians Wanted” section below.

Without further ado, let’s dive in and hopefully you’ll leave this article convinced we can prove a client’s identity even before they establish a connection!

The Goal:

The quick version (TL;DR) of this article is simply this:

Utilize the ISN field in TCP headers for SYN’s, or the Flow Label field in IPv6 packets to carry identity tokens from clients to servers. These tokens are then used to ACCEPT or DENY traffic from any source, regardless of the IP address. These tokens are generated every minute on both client and server, and compared to ACL’s in network appliances (firewalls) or proxy servers. If the tokens are not currently in the “allowed tokens” ACL, they are dropped. Otherwise, they are accepted.

For IPv4 TCP SYN packets — The initial sequence number (ISN) would be the unique token. The server would know exactly who sent the packet before a connection is ever established. This can be denied if the sender is unknown. Unfortunately, packets have to be decapsulated first to get to the Transport Layer. Deep packet inspection firewalls (Hi Palo Alto!) could handle this, otherwise a proxy server of some sort may be needed.

For IPv6 packets — We have a wonderful new field designed specifically for this kind of thing. Let’s use it in a new way! We also do not need to decapsulate packets at this layer!

First, let’s talk about a few important points:

1. TCP is Flawed.

TCP in of itself is great, and I mean no disrespect to it’s creators. It was built in a time when network communication was more polite, and bad guys weren’t rampant like they are today. The flaw in TCP is that it requires said “politeness” and if one of the two people communicating refuse to be polite, they can cause harm. This is seen in DDoS attacks which take advantage of TCP’s three-way handshake.

The left shows a typical polite “three way handshake”. The right is a “half-open” connection.

In the above example, a bad guy has refused to send the third ACK which is required to complete the handshake, and caused the server to hold open his socket until timing out. The bad guy repeats this rude connection over and over so that the server runs out of sockets and service is now denied to legitimate traffic.

This is known as a SYN Flood attack, and is the most common type of DDoS attack.

DDoS attacks are still considered unpreventable, and companies regularly suffer at their hands. Botnets are growing so large they are becoming threats to even major organizations. Just recently as of this article, both Wikipedia and Blizzard Entertainment suffered a major DDoS attack from the same individual(s) on the same day. Wikipedia was down for hours, before the attack was shifted to Blizzard’s World of Warcraft Classic servers, which killed every single game server.

World of Warcraft Classic servers knocked offline by a DDoS (Sept 7th, 2019) Many more servers were offline, this is merely a sample.

2. IPv4 is old and busted.

IPv4 works well and is still the backbone of the Internet. It’s our humble Internet layer protocol, but alas it does not have any fields left we can use in a reliable manner to prove identity.

3. Source IP addresses are not proof of identity.

Many of you are aware spoofed source IP addresses are common in DDoS attacks and are also why they are so difficult to stop. Nothing prevents a bad guy from sending hundreds of thousands of SYN packets to your servers with randomized source IP’s so they are impossible to blacklist, even temporarily.

Many companies turn to highly reduced timeout’s for the third ACK in a handshake in an attempt to survive the onslaught of an attack, but when a botnet is large enough, an enterprise is by all accounts, helpless.

4. One-Time Pads are super secure.

Okay, by definition this isn’t technically OTP, but the concept is very similar. Assigning a client a unique ID (UUID) and an algorithm to pregenerate tokens every minute, is a great way to verify identity. If the algorithm creating the tokens is pseudo-random and the unique key (ID) is truly unique, then we have something quite powerful. (Mathematicians wanted!)

Defining “Tokenized”

Most of us are aware of MFA/2FA authentication mechanisms where an end-user is required to provide a token (typically a 6-digit number) as a second factor of authentication. These can be sent to the user via a text message or phone call, but they can also be generated via “authenticator” apps, such as Duo, Microsoft Authenticator, Google Authenticator, RSA SecureID, etc.

Microsoft Authenticator App. Notice the tokens expire after 22 seconds.

The definition of a “tokenized” Initial Sequence Number (ISN) or Flow Label is simply that these fields will carry the tokens to the receiving server, which will verify the packet based on this ever-changing token.

Creating the token (Mathematicians Wanted!)

An algorithm would need to be created that can generate tokens using unique IDs (UUIDs) and the current date/time in UTC in a pseudo-random way, and fit within a certain range. These ranges are determined by the allowed field size in both TCP and IPv6 (32 bits for TCP or 20 bits for IPv6.)

For example: A corporation such as Blizzard (*cough* World of Warcraft DDoS *cough*) generates a unique ID for each paying customer. This UUID is sent to each customer, and the token is generated using an algorithm that exists on both the server and the client.

“UUID+YYYY:MM:DD:HH:MM” is fed into an algorithm, and spits out a token that fits between 0 and 4294967294 for TCP, or between 0 and 1048575 for IPv6. (Unsigned)

Example: e28e8682–8b40–4472–8fc7–26e46f4c591d + 2019:09:12:09:25 = some number between 0 and 4294967294 OR 0 and 1048575.

import datetime now = datetime.datetime.now()

time = now.year, now.month, now.day, now.hour, now.minute

## UUID's should be generated by the company and given to

## clients. Either embed the token generating algorithm into the

## software you've sold them, or otherwise have the token be

## generated on their system. The server will have a list of all

## distributed UUID's and will pregenerate tokens to be used ahead

## of time. Likewise, the client can pregenerate tokens too if

## desired. Just be aware changing the clients UUID will require

## regeneration of new tokens.

## P.S. - UUIDs are super easy to generate.

## import uuid

## unique_id = uuid.uuid4()

## Yep. That easy in Python. token = generate_token(“e28e8682–8b40–4472–8fc7–26e46f4c591d”, “time”)

The example above shows a hypothetical way tokens can be generated for both the client and server. The “generate_token” function is yet to be created, but I’m hoping one of my dear readers can solve this and maybe change the way we all communicate forever.

Putting it all together

By now, I hope most of you see where this is going. Once we have created a token using a unique identity and the current time (to the minute), we can simply craft our initial SYN packets (for TCP) or every IPv6 packet to utilize these tokens.

The receiving appliance or server simply has to reference an ever-changing ACL (access control list) and compare the ISN on SYN packets, or the Flow Label field on IPv6 packets to verify identity!

This means identification occurs even before a connection is fully established.

This is an example of a firewall ACL for TCP SYN packets. The numbers represent “allowed ISNs”, which means any SYN packet that does not match one of these tokens is dropped, killing the session outright! No half-open connections. No SYN Floods!

Why only “tokenize” SYN packets for TCP?

Since a SYN packet is the first packet sent in any TCP communication, if we drop it we kill the entire session from occurring. For this reason, we do not need the overhead of watching every packet. We only need to watch SYN packets. If we allow it, the connection can be established and we can trust it henceforth. Also, the most important reason is because the sequence number in TCP is used to guarantee delivery of data. Since we can choose our ISN, we can use it for token verification. After that, we cannot change the sequence numbers or we will corrupt/break the data being transported.

Why “tokenize” all packets for IPv6?

Since IPv6 is an Internet Layer protocol, every packet has to be examined upon entry. The good news is, however, we have far more control over every Transport Layer communication that would occur if a packet was allowed through. Arguably, IPv6 would be better at this, since no decapsulation or deep packet inspection needs to occur.

So TCP SYN packets or IPv6? Which one?

Well, that’s for the world to decide. The future is IPv6, and since no decapsulation is required on the Internet Layer, we can start using a “tokenized” Flow Label field instead of Source IP for firewall blacklisting. No deep packet inspection required!

However, a vast majority of the world still lives on IPv4, and deep packet inspection firewalls exist. (Hi again Palo Alto!) Since we have firewalls that can see the ISN on SYN packets at the TCP layer as soon as they hit the firewall, then we can, in theory, drop those packets immediately if their ISN does not match one of our allowed tokens.

Let’s make sure we’re clear on one thing here. If we use the Initial Sequence Number (ISN) in SYN packets in TCP, we are working at the Transport Layer, which requires a little more overhead (Decapsulation.) BUT — we get the advantage of having a much larger space to put tokens in. The sequence (ISN) field in a TCP header allows a range from 0 to 4294967294 (32-bits) as tokens, whereas the Flow Label field in an IPv6 packet allows 0 to 1048575 (20-bits).

When it comes to token generation, as long as the algorithm generating the tokens is consistent, pseudo-random, and fits within one of these spaces, we are good to go!

Time Drift

Due to the nature of time drift, it’s possible your clients have a slightly different time than you. All this means is that your ACL needs to contain tokens for the previous minute, current minute, and future minute to account for this drift. If a client lives outside of this 3 minute window, you simply do not allow them to connect. (This gap can certainly be adjusted — I am using a minute simply as an example. As processing power grows, these windows can becomes insanely tiny if desired.)

Simple example of the flow

Since I have no artistic skills, I will type the flow out. Maybe someone with art skills can come along and make a cool picture of how this would work and send it to me. I’ll put it here instead:

Corporation generates a list of UUID’s per customer. For each UUID, they pregenerate access control lists for every minute which contain authorized tokens for the current minute, previous minute, and future minute. Corporation sends client software with the client’s UUID and the algorithm to calculate their tokens. Client software can also pregenerate tokens using their UUID and the time.

For TCP:

5. Client sends their initial SYN packet to establish a connection. This is an IPv4 packet (or IPv6 I suppose) encapsulating TCP.

6. The IPv4 packet carrying the SYN travels the Internet, and lands at the corporate firewall.

7a. If the firewall can perform deep packet inspection, it can first check if the TCP header inside is a SYN packet or not. If it is a SYN packet, it then checks the ISN and compares it to it’s ACL. If the tokens match, it allows the connection to continue, otherwise it drops the packet. Any server on the back-end never receives a packet.

7b. If the the firewall is not capable of deep packet inspection, a proxy server would be required to intercept the decapsulated TCP packet and perform the same activity.

Note: All non-SYN packets do not need to be observed!

For IPv6:

5. Client sends their IPv6 packet with their token in the Flow Label field.

6. The IPv6 packet travels the Internet and lands at the corporate firewall.

7. The firewall compares the Flow Label field with it’s ACL. If the token in the field matches an authorized token, it allows the connection, otherwise the packet is dropped.

IP Spoofing-IP Schmoofing/Port Knocking-Schmort Knocking

We now have a way to verify identity before a session is established.

“Gotchas”:

Data Smuggling

I wrote a previous article on data smuggling using Scapy that relies on abusing the ISN field in TCP packets (and could be used in the Flow Label field of IPv6.) (Shameless self-plug: https://medium.com/swlh/smuggler-and-cove-a-poc-for-data-exfiltration-using-scapy-e44649feae6)

After writing that PoC, I quickly learned how awesome some firewalls are — and unfortunately, how they could interfere with this idea.

Currently, if you craft your own ISN on a SYN packet or your own Flow Label on IPv6, a smart firewall will rewrite it before sending it on.

They do this because they want to prevent data smuggling out of a network. This should be considered when it comes to crafting your own packets, and firewalls would need to have a “tokenized fields allowed” option so this entire concept can work.

The trade off is that smuggling data becomes possible again — though we can always talk about detecting data smuggling instead of not allowing field alterations in packets.

Token generation should be as random as possible

If the token generation algorithm isn’t random enough, it might be possible to an attacker to predict future token values. If this is the case, however, all it means is that a session can be established. This is no different than how the world currently works, so it’s not that big of a deal. Standard security measures should still be used as they currently are with all other types of verification such as SSL/TLS, etc.

And, to be 100% clear, the sequence number on the SYN/ACK from the server should still remain completely random as it currently is. This will prevent old school sequence number prediction attacks as was used in the infamous Kevin Mitnick attack against Tsutomu Shimomura.

(http://wiki.cas.mcmaster.ca/index.php/The_Mitnick_attack)

The time window for token generation should be small

Given enough time, an attacker could brute-force every possible ISN value or Flow Label number possible. Of course you would see this coming a mile away as it would appear like a DoS attack, only you would be dropping every packet instead of holding multiple TCP sessions half-open.

Even if successful, the attacker has at most, established a three-way handshake. Again, this is no different than the currently wide-open ports all over the world — but I mention it here for clarity.

In Conclusion:

I hope by now I have convinced you that low level identity verification is possible even before a connection is established between a client and a server. IP addresses, as we know, are not a trustworthy way to know who is attempting to connect to your systems.

Using this method, you can not only verify who is trying to connect, you can have complete control of who is allowed to connect to your systems, without the risk of abuse from DDoS attacks, port scanning or IP spoofing.

Prototypes of this method should be easily and quickly built by those who are used to writing proxy software. We really need someone to come along and build a token generation method for both TCP and IPv6, and we can change things fundamentally. If you agree with this idea, please share it with your firewall/networking/cyber security friends and maybe we can start a community conversation about it.

Happy hacking!