Exploit-DB #24562
Description: PHP-Fusion 7.02.05 - Multiple Vulnerabilities
Type: webapps
Platform: php
Date: 2013-03-01
Author: waraxe

Exploit:
[waraxe-2013-SA#097] - Multiple Vulnerabilities in PHP-Fusion 7.02.05
===============================================================================

Author: Janek Vind "waraxe"
Date: 27. February 2013
Location: Estonia, Tartu
Web: http://www.waraxe.us/advisory-97.html


Description of vulnerable software:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

PHP-Fusion is a light-weight open-source content management system (CMS)
written in PHP 5. It utilises a MySQL database to store your site content and
includes a simple, comprehensive administration system. PHP-Fusion includes the
most common features you would expect to see in many other CMS packages. 

http://www.php-fusion.co.uk/news.php
http://sourceforge.net/projects/php-fusion/

Vulnerable is version 7.02.05 and possibly older versions.

New, patched version 7.02.06 available here:

http://www.php-fusion.co.uk/news.php?readmore=569
http://www.php-fusion.co.uk/downloads.php?cat_id=23&download_id=264


###############################################################################
1. Local File Inclusion in "maincore.php"
###############################################################################

Reason: insufficient sanitization of user-supplied data
Attack vector: user-supplied POST parameter "user_theme"
Preconditions:
 1. Logged in as valid user
 2. "Allow users to change theme" option must be activated (it is by default)
 3. PHP must be < 5.3.4 for null-byte attacks to work
 
PHP-Fusion users can edit their profile and by default there is possibility to
change the theme. There is no sufficient sanitization of the POST parameter
"user_theme":

Php script "includes/user_fields/user_theme_include" line 41:
------------------------[ source code start ]----------------------------------
} elseif ($profile_method == "validate_insert"  || $profile_method == "validate_update") {
    if ($settings['userthemes'] == 1 || iADMIN) {
        // Get input data
        if (isset($_POST['user_theme']) && $_POST['user_theme'] != "") {
            // Set update or insert user data
            $this->_setDBValue("user_theme", stripinput(trim($_POST['user_theme'])));
------------------------[ source code end ]------------------------------------

We can see, that user-supplied parameter "user_theme" goes through the
function "stripinput()":

Php script "maincore.php" line 332:
------------------------[ source code start ]----------------------------------
// Strip Input Function, prevents HTML in unwanted places
function stripinput($text) {
    if (!is_array($text)) {
        $text = stripslash(trim($text));
        $text = preg_replace("/(&)+(?=\#([0-9]{2,3});)/i", "&", $text);
        $search = array("&", "\"", "'", "\\", '\"', "\'", "<", ">", "&nbsp;");
        $replace = array("&", """, "'", "\", """, "'", "<", ">", " ");
        $text = str_replace($search, $replace, $text);
    } else {
        foreach ($text as $key => $value) {
            $text[$key] = stripinput($value);
        }
    }
    return $text;
}
------------------------[ source code end ]------------------------------------

This function works against XSS and SQL Injection attacks, but not against
file inclusion attacks. Attacker can submit user theme value as one below:

../images/avatars/waraxe.jpg\0z

Directory traversal symbols "../" and null byte will pass through the
function "stripinput()" and whole string will be saved to the database.
All subsequent requests by attacker will use this malicious theme string
and as result, previously uploaded avatar picture with PHP payload gets
included and executed.

Most front-end scripts start with this:
------------------------[ source code start ]----------------------------------
require_once "maincore.php";
require_once THEMES."templates/header.php";
------------------------[ source code end ]------------------------------------

Php script "maincore.php" line 264:
------------------------[ source code start ]----------------------------------
// Set theme
if (!theme_exists($userdata['user_theme'])) {
...
// Check that site or user theme exists
function theme_exists($theme) {
    global $settings;
...
    } elseif (file_exists(THEMES.$theme."/theme.php") && file_exists(THEMES.$theme."/styles.css")) {
        define("THEME", THEMES.$theme."/");
------------------------[ source code end ]------------------------------------

We can see, that malicious theme string from database will be used in theme path
definition and later is used in "require_once".

This security vulnerability was tested by using Burp Proxy and exploitation
succeeded.

###############################################################################
2. Local File Inclusion in "administration/user_fields.php"
###############################################################################

Reason: insufficient sanitization of user-supplied data
Attack vector: user-supplied GET parameter "enable"
Preconditions:
 1. Logged in as admin with user field administration privileges
 2. PHP must be < 5.3.4 for null-byte attacks to work
 
 
Php script "administration/user_fields.php" line 84:
------------------------[ source code start ]----------------------------------
} elseif (isset($_GET['enable'])
        && file_exists(INCLUDES."user_fields/".stripinput($_GET['enable'])."_include_var.php")
        && file_exists(INCLUDES."user_fields/".stripinput($_GET['enable'])."_include.php")
) {
    $user_field_api_version = "1.00.00";
    if (file_exists(LOCALE.LOCALESET."user_fields/".stripinput($_GET['enable']).".php")) {
        include LOCALE.LOCALESET."user_fields/".stripinput($_GET['enable']).".php";
------------------------[ source code end ]------------------------------------

Test (parameter "aid" needs to be valid):

Upload avatar picture with PHP payload and then issue request:

http://localhost/p