Denial of Service


Web Security.

Servers have limits. CPU, memory, bandwidth, open connections, file descriptors. A Denial of Service (DoS) attack doesn't steal anything or run code, it just burns those limits until the service stops keeping up with real users.

Sometimes that's a flood of traffic. Other times it's one cheap request that costs the server a lot. When many machines pitch in, it becomes a Distributed Denial of Service (DDoS).

This module walks through how availability breaks and how small inefficiencies turn into full outages.


A Denial of Service attack doesn't always need a flood of traffic. Sometimes one well-placed request is enough to keep a server from doing anything else.

In this challenge, the server runs one worker with one thread. While that worker is busy with a request, no one else gets in.

Your goal is to keep the server from responding to its own watchdog. After enough failed health checks in a row, the watchdog will print the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

The obvious fix for a busy server is more workers, so this one runs 32 of them, each its own process, handling requests in parallel.

But each worker is still synchronous: one request at a time, start to finish. More lanes don't help if every lane is single-file.

Same goal as before: knock the server offline long enough that the watchdog gives up and prints the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

This server has a new endpoint: POST /log. It accepts JSON, and the handler reads the entire body before doing anything with it.

There's no cap on the request size. Whatever you send, the server has to hold somewhere, and memory isn't infinite. When a process runs out, it can't keep responding.

Push the server past what it can hold, and the watchdog will hand you the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

The server now runs one worker with 64 threads. Threads share the same process, so requests can be handled concurrently without spinning up new processes for each one.

But concurrency only goes as far as the resources behind it. Threads still share the same disk, the same file descriptors, the same I/O. If the underlying work is expensive enough, more threads just means more contention.

The same POST /log endpoint is here. When the server can't keep up with its own watchdog, you get the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

Last challenge showed that threads can be defeated by shared I/O. This one removes I/O from the picture entirely.

The body size is capped at 4 KB, the handler doesn't touch the disk, and the input is just a string. No tempfiles, no buffers to fill.

What's left is pure computation. Threads only help when there's something to wait for, and there's nothing to wait for here. Every request the server accepts has to take CPU time from something else, including the watchdog.

The endpoint here is POST /match. It runs a regex on whatever string you send. Find an input that makes the regex expensive, and a few requests are enough to pin the server.

When the watchdog can't get a turn, you get the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

The earlier challenges all assumed the size of the request was a meaningful signal. Cap the body, and you cap the damage.

This server caps the body too. Content-Length is limited to 2 MB. But it also accepts gzip-encoded bodies, and decodes them with a streaming decompressor. As soon as the decompressed total crosses 1 GB, the server kills itself rather than let things go further.

A small, well-crafted compressed payload can decompress into something thousands of times its size. The lesson: a length cap on the wire doesn't tell you anything about the cost of what's inside.

The endpoint here is POST /upload. Get the server to detect a 1 GB+ payload, and the watchdog will hand you the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

The compression bomb showed how a tiny payload can decompress into something gigantic. This is the same idea, but the amplification comes from the parser, not the encoding.

The server has a small template language. Send {"$repeat": [n, inner]} and the server expands inner n times. Nest a few of these and the output grows multiplicatively. Three layers of $repeat: [1024, ...] produces over a billion characters from a few hundred bytes of input.

Body size is capped at 16 KB. The compression-bomb defense doesn't catch this one. The request really is small. Only the result of parsing it is huge.

The endpoint here is POST /render. Get the server to detect a 1 GB+ expansion, and the watchdog will hand you the flag.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

Up until now, every challenge gave you something to make the server do: parse a body, decompress, run a regex, write to disk. This one doesn't.

The server runs one worker with 4 threads. The only endpoint is /health. There's no body, no parsing, no computation. From inside the handler, there is nothing slow to trigger.

But every connection still has to be read before it can be served. While a thread is waiting on bytes from the socket, it can't do anything else.

You don't need to ask the server to do anything. You just need to refuse to finish talking.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

Every challenge before this one gave you a way to talk to the server. This one doesn't.

The server is up. The watchdog can reach it. You can't. Your traffic on port 443 is dropped before it ever leaves your shell. There is no payload to send, no body to oversize, no header to drip. The HTTP attack surface is closed to you.

But you and the server are still roommates. You share the same CPU, the same memory, the same disk, the same kernel. You can run whatever you want as your own user.

You don't need to attack the service. You need to be a bad neighbor.

Connect with SSH

Link your SSH key, then connect with: ssh [email protected]

30-Day Scoreboard:

This scoreboard reflects solves for challenges in this module after the module launched in this dojo.

Rank Hacker Badges Score