Today we’ll look at one of the external penetration tests that I carried out earlier this year. Due to the confidentiality agreement, we will use the usual domain of REDACTED.COM
So, to provide a bit of context to the test, it is completely black box with zero information being provided from the customer. The only thing we know is that we are allowed to test redacted.com and the subdomain my.redacted.com
I’ll skip through the whole passive information gathering process and will get straight to the point.
I start actively scanning and navigating through the website to discover potential entry points. There are no ports open other than 80 & 443.
So, I start directory bruteforcing with gobuster and straightaway, I see an admin panel that returns a 403 — Forbidden response.
Seeing this, we navigate to the website to verify that it is indeed a 403 and to capture the request with Burp Suite for potential bypasses.
In my mind, I am thinking that it will be impossible to bypass this, because there is an ACL for internal IP addresses. Nevertheless, I tried the following to bypass the 403:
- HTTP Methods fuzzing (GET, POST, TRACE, HEAD etc.)
- HTTP Headers fuzzing (X-Originating-IP: 127.0.0.1, X-Forwarded-For: 127.0.0.1 etc.)
- Path fuzzing/force browsing (https://redacted.com/admin/index.html, https://redacted.com/admin/./index.html and more)
- Protocol version changing (From HTTP 1.2, downgrade to HTTP 1.1 etc.)
- String terminators (%00, 0x00, //, ;, %, !, ?,  etc.) — adding those to the end of the path and inside the path
Long story short, none of those methods worked. So, I remember that sometimes the security controls are built around the literal spelling and case of components within a request. Therefore, I tried the ‘Case Switching’ technique — probably sounds dumb, but it actually worked!
To sum it up:
- https://redacted.com/admin -> 403 Forbidden
- https://redacted.com/Admin -> 200 OK
- https://redacted.com/aDmin -> 200 OK
Swiching any of the letters to a capital one, will bypass the restriction.
Voila! We get a login page to the admin panel.
We get lucky with this one, nevertheless, we are now able to try different attacks (password spraying, brute forcing etc.). The company that we are testing isn’t small and we had collected quite a large number of employee credentials from leaked databases (leak check, leak peek and others). However, this is the admin panel and therefore we go with the usual tests:
- See if there is username enumeration
- See if there are any login restrictions
- Check for possible WAF that will block us due to number of requests
To keep it short, there is neither. We are unable to enumerate usernames, however there is no rate limiting of any sort.
Considering the above, we load rockyou.txt and start brute forcing the password of the ‘admin’ account. After a few thousand attempts, we see the below:
We found valid credentials for the admin account. Navigate to the website’s admin panel, authenticate and we are in!
Now that we are in, there isn’t much more that we need to do or can do (without the consent of the customer). The admin panel with administrative privileges allows you to change the whole configuration — control the users & their attributes, control the website’s pages, control everything really. So, I decided to write a Python script that scrapes the whole database of users (around 39,300 — thirty nine thousand and three hundred) that contains their names, emails, phones & addresses. The idea to collect all those details is to then present them to the client (victim) — to show the seriousness of the exploited vulnerabilities. Also, due to the severity of those security weaknesses, we wrote a report the same day for those specific issues, which were fixed within 24 hours.
Ultimately, there wasn’t anything too difficult in the whole exploitation process, however the unusual 403 bypass is really something that I see for the first time and I thought that some of you might weaponize this or add it to your future 403 bypass checklists.
If you enjoyed the read, please consider supporting me: https://firstname.lastname@example.org/membership