---
title: Status codes from pentester's perspective
modified: 1678576834091
description: A quick take on HTTP status codes from a pentester's perspective. Answers are highly sublective.
---


In this post we'll take a dive to HTTP status codes by answering a few questions
from the [Web Application Penetration testing Study Plan][study-plan].

[study-plan]: https://github.com/jassics/security-study-plan/blob/main/web-pentest-study-plan.md#basics

## What if you get 200 when you try something malicious?

When you are trying to impersonate someone, perform unwanted actions or elevate
your privileges, the system should try its best to prevent it from happening and
return a status code from the 400s or from the 500s. So if you get a 200
response, congratulations! That means that you have a high probability in
succeeding in your attack – you probably did something right.

## What can we do if we get a 403 - Forbidden

The important difference between 403 Forbidden and 401 Unauthorized is that you
found a resource that is exists, but you just don't have the correct privileges
to access that.

I've seen that sometimes developers implement 403 Forbidden as 404 Not Found as
a security measure to prevent that information from leaking the system. I think
that could be a good practice to give the least amount of information out that
you need to, because from the end user's perspective, that resource shouldn't
exist.

To get around 403 Forbidden you have a few possibilities:

* SSRF in case of local requests having elevated privileges
* Have somebody else do it, e.g. through XSS
* Impersonate someone that has access e.g. via weak JWT configuration

## Let's try to get a 500 status code, why so? What will it reveal?

I think the best way of remembering what's the difference between 400s and 500s is:

* 400s = you fucked up (as the consumer)
* 500s = we fucked up (as the server/developer)

So 500 means that the system got into that kind of a situation that wasn't
expected. From the penetration testers perspective, this is always a
good thing, because then you found some kind of an edge case that the developers
didn't think about; there's a high chance that there is something to
exploit in that situation.

For example, finding SQL injection by adding an extra `"` to your form field
probably yields a 500 error. In that case the developers didn't know that kind
of behaviour was possible, so they didn't build the system to withstand it, and
the system crashed in an unpredictable way.

I think the best kind of 500s as a penetration tester are the ones that include
a *stack trace*. Stack traces are beautiful sources of information that can leak
mutliple pieces of information like:

* The underlying programming language
* Server components
* What kind of libraries they are using
* Detailed information about where the error was in the system

Especially if the 500 error originates from an open source library; you can
probably trace back the exact version of the library that they were using and
find the source code that caused the crash.

So as a penetration tester: 500 errors means that you're getting close.

## Try to understand each status code which as a pentester you would love to see

There are a ton of different status codes, ranging from common ones to those you
don't really see in the wild. I've tried to list the most important ones here
that have some kind of a meaning to the penetration tester.

### 101 – Upgrade the what now?

It can scare you the first time you see a 101 Switching Protocols response, but
don't worry. It probably means you've hit a websocket API.

A practical thing to look for is [Websocket smuggling][websocket-smuggling]: If
you can trick the server to send you a 101 without when it shouldn't be, then
you can trick an intermediate server to create a persistent connection that can
give you access to restricted internal API endpoints.

[websocket-smuggling]: https://book.hacktricks.xyz/pentesting-web/h2c-smuggling#websocket-smuggling

### 200s range – the A-OKs

The best thing to see in Burp when you're chasing for IDORs. If the system works
correctly, you should be always getting a response from the 400s. You do have
different responses depending on the effect you're chasing: 200 OK (Update), 201
Created (Create), and even 204 No Content (in case of a DELETE request).

### 300s – show me the way

Response code in the 300s means you're dealing with redirects. Most frequently you'll bump into one of the following:

* 301 Moved Permanently
* 307 Temporary Redirect
* 308 Permanent Redirect

In these cases you'll want to be looking out for open redirects. Make sure to
map all 300s out when you're doing reconnaissance and try out the open redirects
to them at some point.

300s are also handy with tesing out HTTP smuggling; you want to have some
responses where you get consistent 300s or 400s to be able to distinguish
successful response smugglings.

### 429 – I tried too hard and only got so far

Sometimes you suddenly start getting weird status codes, and it's probaby a rate
limit or WAF that you've managed to trigger. 429 Too Many Requests is a good
example of that.

In that case you have a few options:

* Wait for the rate limit to cool down and throttle your requests
* Change your IP address
* Use a server farm to distribute your requests

### 503 – Whoops, did I do that?

503 Service Unavailable can be a dangerous response code to have when you're
doing penetration testing of a live environment. It can mean that you have hit
the server so hard that it crashed completely, and may either be completely down
or rebooting.

The good news is that you may have found a DoS attack! If the server recovers
after a reboot, see if you have something you can reproduce.

### 418 – will definitely lighten up your day

418 - originally a April Fool's Day RFC for "I'm a teapot". If you ever run into
that, just high five yourself, because you just hit some kind of an Easter egg
that the developers have left for you.

Unless of course if we are talking about testing actual Internet connected
"smart" teapot. In that case, I would be worried as much as [Mikko](https://blog.f-secure.com/hypponens-law-smart-vulnerable/).