pass21-源码分析和提示
提示:
源码:
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
//检查MIME
$allow_type = array('image/jpeg','image/png','image/gif');
if(!in_array($_FILES['upload_file']['type'],$allow_type)){
$msg = "禁止上传该类型文件!";
}else{
//检查文件名
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
if (!is_array($file)) {
$file = explode('.', strtolower($file));
}
$ext = end($file);
$allow_suffix = array('jpg','png','gif');
if (!in_array($ext, $allow_suffix)) {
$msg = "禁止上传该后缀文件!";
}else{
$file_name = reset($file) . '.' . $file[count($file) - 1];
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$msg = "文件上传成功!";
$is_upload = true;
} else {
$msg = "文件上传失败!";
}
}
}
}else{
$msg = "请选择要上传的文件!";
}
这一关对于学习知识来说,已经意义不大了,但是出题人故意把这一关设计的弯弯绕绕。
代码解析:
首先检查MIME类型。
规定了白名单:‘image/jpeg’,‘image/png’,‘image/gif’
然后检查文件名,这个也是可以抓包修改的,因为是从POST请求中修改文件名的。
注意这里有一句三目运算符:
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
如果保存名称是空的,那就保存名称直接赋值成文件的名字。
然后判断保存名称是不是数组:(这一步貌似很奇怪,所以说这一关是为了出题而出题)
如果不是数组,就分割。
然后是下面这一句:
$ext = end($file);
是从数组中拿到最后一项。
然后:
$allow_suffix = array('jpg','png','gif');
又做了一次白名单 的判断。—》所以save_path中的最后一项(save_path是一个数组)也确定了,是白名单的其中一个。
然后是else:
先看这一句:
$file_name = reset($file) . '.' . $file[count($file) - 1];
reset($file)
和end($file)
两者相反,reset($file)拿的是数组的第0个元素。
$file[count($file) - 1]
是数组 的最后一项,所以$file_name
是数组第一个元素.数组最后一个元素
说白了,$file_name
是数组第一个元素(文件名)+数组最后一个元素(扩展名)
然后最后再注意一下PHP的move_uploaded_file函数的特性,在pass20的那一关已经碰到过了。不了解的可以去看一下pass20
pass21-思路
首先准备上传shell.php(一句话木马)
然后先抓包:
修改:
上传成功了:
pass21-连接webshell
21关也过了