文件上传
上传文件练习,
对后台代码进行修改,限制上传格式为png.
对后台代码进行修改,限制上传文件大小为2m以内
第一步,编写上传文件的代码:(可以任意上传文件)
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--multipart/form-data 对上传的文件进行不编码处理-->
<form action="fileupload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="uploadfile">
<input type="submit">
</form>
</body>
</html>
PHP代码:
<?php
//如果文件存在,进行文件上传处理
//接收文件时用$_FILES接收,不用$_POST接收
if (isset($_FILES["uploadfile"])){
$uploadfile = $_FILES["uploadfile"];
//var_dump($uploadfile);
//array(5) { 上传的文件数据是数组的形式
// ["name"]=> string(5) "1.PNG" 文件的名字
// ["type"]=> string(9) "image/png" 文件类型,对于不同的文件类型"image/png" 会不同
// ["tmp_name"]=> string(53) "C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp" 上传到一个临时文件,不处理会市场删除
// ["error"]=> int(0) 0上传没有错误
// ["size"]=> int(196406) } 文件大小
//将上传的文件移动到当前web目录(当前目录下的upload目录)
//参数:
//文件的名字(临时目录的名字:"C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp")
//移动文件到什么地方 假设上传的文件是PNG格式 那么将文件复制到"upload/1.png"
$filename = $uploadfile["tmp_name"];
//上传的文件是1.txt aaa.jpg那么就保存到路径是什么名字
$destnation = "upload/".$uploadfile["name"];
//将文件名转换为gbk编码,否则上传一些文件会报错
$destnation = iconv("utf-8","gbk",$destnation);
move_uploaded_file($filename,$destnation);
}
第二步,编写限制文件代码:(只需更改PHP代码)
PHP代码:
<?php
header("Content-type: text/html; charset=utf-8");
//如果文件存在,进行文件上传处理
//接收文件时用$_FILES接收,不用$_POST接收
if (isset($_FILES["uploadfile"])){
$uploadfile = $_FILES["uploadfile"];
//var_dump($uploadfile);
//array(5) { 上传的文件数据是数组的形式
// ["name"]=> string(5) "1.PNG" 文件的名字
// ["type"]=> string(9) "image/png" 文件类型,对于不同的文件类型"image/png" 会不同
// ["tmp_name"]=> string(53) "C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp" 上传到一个临时文件,不处理会市场删除
// ["error"]=> int(0) 0上传没有错误
// ["size"]=> int(196406) } 文件大小
//将上传的文件移动到当前web目录(当前目录下的upload目录)
//参数:
//文件的名字(临时目录的名字:"C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp")
//移动文件到什么地方 假设上传的文件是PNG格式 那么将文件复制到"upload/1.png"
$filename = $uploadfile["tmp_name"];
//1.限制文件后缀名为PNG
$name = $uploadfile["name"];
//a.获取后缀名 如果不是PNG直接结束程序
//获取"点"后面的字符数(+1是不要"点")
$extpos = strpos($name,".")+1;
//截取后缀名
$ext = substr($name,$extpos);
if ($ext!="PNG"){
echo "上传文件失败,类型错误!";
die();
}
//2.限制文件大小2M
$fileseze = $uploadfile["size"];
if ($fileseze > 1024*1024*20){
echo "文件过大,上传失败!";
}
//上传的文件是1.txt aaa.jpg那么就保存到路径是什么名字
$destnation = "upload/".$uploadfile["name"];
//将文件名转换为gbk编码,否则上传一些文件会报错
$destnation = iconv("utf-8","gbk",$destnation);
move_uploaded_file($filename,$destnation);
}
前端JS检测
HTML代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--multipart/form-data 对上传的文件进行不编码处理-->
<!--当表单点击提交时,会激发表单激发时间-->
<!--onclick当表单被点击时会激发的事件-->
<!--onmouseover当鼠标移入表单的时候会激发的事件-->
<form action="fileupload1.php" οnsubmit="return checkupload()"; method="POST" enctype="multipart/form-data">
<input type="file" name="uploadfile" id="uploadfile">
<input type="submit">
</form>
<script type="text/javascript">
<!--函数作用,检测文件上传是否符合规则-->
function checkupload() {
//判断文件类型
//如果文件类型不是PNG就不让上传
//1.获取文件名 js中一般用id来获取标签,文件名就是对应file类型input的值 value
//document.getElementById() 在html中通过id获取标签
//document指的是整个html文档
// getElementById() 通过id属性获取元素(标签)
var filetag = document.getElementById("uploadfile");
var filename = filetag.value;
//2.从文件名上截取后缀名
//a.获取最后一个点出现的位置
var lastpos = filename.lastIndexOf(".")+1;
//b.通过点截取文件名
var ext = filename.substring(lastpos);
//3.判断后缀名,如果不是PNG阻止表单提交
//想要阻止表单的提交
// 在表单提交时事件函数中添加返回值 return false
if (ext != "png"){
alert("文件类型错误,上传失败!");
return false;
}
}
</script> </body> </html>
PHP代码:
<?php
header("Content-type: text/html; charset=utf-8");
//如果文件存在,进行文件上传处理
//接收文件时用$_FILES接收,不用$_POST接收
if (isset($_FILES["uploadfile"])){
$uploadfile = $_FILES["uploadfile"];
//var_dump($uploadfile);
//array(5) { 上传的文件数据是数组的形式
// ["name"]=> string(5) "1.PNG" 文件的名字
// ["type"]=> string(9) "image/png" 文件类型,对于不同的文件类型"image/png" 会不同
// ["tmp_name"]=> string(53) "C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp" 上传到一个临时文件,不处理会市场删除
// ["error"]=> int(0) 0上传没有错误
// ["size"]=> int(196406) } 文件大小
//将上传的文件移动到当前web目录(当前目录下的upload目录)
//参数:
//文件的名字(临时目录的名字:"C:\Users\Administrator\AppData\Local\Temp\php8DF8.tmp")
//移动文件到什么地方 假设上传的文件是PNG格式 那么将文件复制到"upload/1.png"
$filename = $uploadfile["tmp_name"];
//上传的文件是1.txt aaa.jpg那么就保存到路径是什么名字
$destnation = "upload/".$uploadfile["name"];
//将文件名转换为gbk编码,否则上传一些文件会报错
$destnation = iconv("utf-8","gbk",$destnation);
move_uploaded_file($filename,$destnation);
}
前端JS检测的绕过方式
判断该上传逻辑是前端验证还是后端验证
F12,查看网络 提交一个上传不了的文件是没有流量的,如果上传一个成功的文件有流量说明是前端验证
1.禁用JS
如果通过ajax上传文件,禁用了JS,则ajax的JS代码不能执行,也就是说无法上传文件
使用火狐浏览器,输入about:config 搜索Javascript.enabled 把他的值改为false
2.通过bp装包
修改上传的文件名为png(可上传的格式)
通过bp抓包(抓到的数据包已经通过了前端的验证)
修改上传的文件名为php文件,就可以上传了
上传成功!
upload-labs-master闯关
第一关:
用bp抓包绕过前端验证
修改1.php为1.png
再修改文件名为1.php
上传成功
第三关
黑名单绕过
通过修改1.php的后缀名为1.phtml
上传成功,访问图片路径查看是否能够执行
成功
第五关
修改后缀名大小写
修改1.php为1.PHP
上传成功
复制图片地址查看是否能够执行
成功
第六关
利用文件后缀加空格来绕过
上传1.php然后用bp抓包
在文件后缀增加空格( )
上传成功
第七关
利用文件后缀加点绕过
依然是1.php上传然后bp抓包
在文件后缀增加点(.)
成功
第八关
利用Windows文件流绕过在文件后缀增加::$DATA
上传1.php通过bp抓包,增加后缀
成功
第九关
用点空格混用绕过
用bp抓包,修改文件名为1.php. .
成功
第十关
双写后缀名绕过
上传文件,通过bp抓包修改文件名为1.pphphp
成功
第十一关
利用%00截断绕过
上传1.png通过bp抓包修改文件名为1.php%00
需要注意的是这个方式在php版本小于5.3.4,php的magic_quotes_gpc为OFF状态才可应用。