当前位置: 首页 > news >正文

File Upload(文件上传)

File Upload(文件上传),由于对上传文件的内、类型没有做严格的过滤、检查,使得攻击者可以通过上传木马文件获取服务器的webshell文件。

low

这关需要我们上传一个图片文件,但我们明确了文件上传漏洞的定义,知道他是由于没有严格检查文件内容

因此我们试着上传一个并非图片的文件,如下(用于显示php的配置信息)

可以看到上传成功了,并给我们指出了路径,试着访问一下

确实给我们返回了php的配置文件

源码分析
<?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? //文件的目标路径hackable/uploads/,也就是文件上传的位置 $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; // basename(path,suffix) //函数返回路径中的文件名部分,如果可选参数suffix为空,则返回的文件名包含后缀名,反之不包含后缀名。 $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // Can we move the file to the upload folder? //移动用户上传文件至目标路径 if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // No echo '<pre>Your image was not uploaded.</pre>'; } else { // Yes! echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } ?>

从源码中可以看到对上传文件的类型、内容没有做任何的过滤与检查,同时告诉了我们文件上传的路径,存在明显的文件上传漏洞。

Medium

我们还是先试试上传一个php文件

失败了,告诉我们只能上传JPEG或者PNG的图片文件

那我们抓个包看看

可以看到我圈出了Content-Type这个元素,它用于告诉服务器:"我这个请求体里的数据是什么格式"

常见文件对应的 Content-Type

文件类型

Content-Type 值

.php

application/x-phptext/plain

.jpg/.jpeg

image/jpeg

.png

image/png

.gif

image/gif

.html/.htm

text/html

.txt

text/plain

.exe

application/x-msdownload

.zip

application/zip

回到原题中,要求我们要上传图片格式,那我们就改变其content-type值(改为所需要的图片类型值)再上传试试

能看到上传成功了

源码分析
<?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // File information $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; // Is it an image? //文件类型必须是image/jpeg 或者 image/png,大小不能超过100000B(约为97.6KB) if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) && ( $uploaded_size < 100000 ) ) { // Can we move the file to the upload folder? if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { // No echo '<pre>Your image was not uploaded.</pre>'; } else { // Yes! echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { // Invalid file echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>

对文件上传的类型做了限制,要求必须是image/jpeg 或者 image/png 类型的,但我们依旧可以抓包改包绕过

High

到了这个级别一般都会有点难度,我们先看看源代码

<?php if( isset( $_POST[ 'Upload' ] ) ) { // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); // File information $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; // Is it an image? // strtoLower把所有字符转换为小写 getimagesize(string filename) 函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。 可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”*.jpg”、”*.jpeg” 、”*.png”之一。同时,getimagesize函数更是限制了上传文件的文件头必须为图像类型。 if( ( strtoLower( $uploaded_ext ) == "jpg" || strtoLower( $uploaded_ext ) == "jpeg" || strtoLower( $uploaded_ext ) == "png" ) && ( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) { // Can we move the file to the upload folder? if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { // No echo '<pre>Your image was not uploaded.</pre>'; } else { // Yes! echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { // Invalid file echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>

这里用到了getimagesize($uploaded_tmp)这个函数,强制要求上传图片

我们可以制作一个图片马

首先需要准备一个图片,一个脚本文件(我用的还是最简单的读取php配置文件)

在命令行里,使用copy合并两个文件(这是制作图片马最常用的方式)

这里需要说明一下

  • /b表示以二进制方式复制(图片文件用二进制)
  • /a表示以ASCII方式复制(PHP文件用文本)
  • image_shell.png是最终生成的文件名

合并后大家可以看到新文件大小应该 ≈phpinfo.png+phpinfo.php的大小之和

并且我们用记事本打开这个图片文件,可以在末尾看到这样的字符,这说明我们的图片马制作成功了

有关其他方式制作图片马可以参考大佬写的这篇文章做一个图片马(图片木马)的四种方法 小白也能看会(详细步骤 ) 需要.htaccess等执行图片内代码_图片马制作-CSDN博客

然后选择一手上传,成功了,还告诉了我们文件路径

接下来我们回到文件包含漏洞中验证一下,在URL中输入刚刚上传成功的图片马路径,回车

页面顶部出现的乱码,是图片马中PNG图片的二进制数据被浏览器/服务器误当作文本字符进行渲染时产生的。这并不影响其后的PHP代码被成功执行,也恰好证明了该图片马已通过了getimagesize()的图片头检测,成功给我们返回了php配置信息

Impossible

<?php if( isset( $_POST[ 'Upload' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // File information $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/'; //$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-'; //上传文件的文件前缀md5加密 $target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; //in_get(varname) 函数返回相应选项的值 $temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) ); $temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; // Is it an image? if( ( strtoLower( $uploaded_ext ) == 'jpg' || strtoLower( $uploaded_ext ) == 'jpeg' || strtoLower( $uploaded_ext ) == 'png' ) && ( $uploaded_size < 100000 ) && ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) && getimagesize( $uploaded_tmp ) ) { // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD) if( $uploaded_type == 'image/jpeg' ) { //imagecreatefromjpeg ( filename ) 函数返回图片文件的图像标识,失败返回false $img = imagecreatefromjpeg( $uploaded_tmp ); //imagejpeg ( image , filename , quality) 从image图像以filename为文件名创建一个JPEG图像,可选参数quality,范围从0(最差质量,文件更小)到100(最佳质量,文件最大)。 imagejpeg( $img, $temp_file, 100); } else { $img = imagecreatefrompng( $uploaded_tmp ); imagepng( $img, $temp_file, 9); } // imagedestroy( img ) 函数销毁图像资源 imagedestroy( $img ); // Can we move the file to the web root from the temp folder? if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) { // Yes! echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>"; } else { // No echo '<pre>Your image was not uploaded.</pre>'; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } // Generate Anti-CSRF token generateSessionToken(); ?>

这个级别的文件上传对上传的文件进行了重命名(搞了一个MD5的加密),还增加了token值的校验,对文件的内容也做了严格的检查。

http://www.jsqmd.com/news/1138599/

相关文章:

  • 从噪音困扰到静音享受:TPFanCtrl2如何重塑你的ThinkPad使用体验
  • 2026年理工科论文写作AI测评:5款工具公式生成支持
  • YOLO26 改进 - 注意力机制 CAFM (Convolutional Block Attention Module) 卷积块注意力模块:轻量级设计优化特征提取流程,提升小目标感知
  • AIGC检测是什么?2026年论文AI率检测全攻略与工具推荐
  • CTF Writeup 逆向工程实战:从 DASCTF 2022 赛题看 PHP 反序列化 Fast Destruct 漏洞利用
  • 优测接口超时监控告警配置流程解析
  • 先看一个模式匹配的Case
  • NSK RNFTL5016A5 超重载滚珠丝杠技术详解
  • JESD204B 与 LVDS/CMOS 接口对比:5 大维度实测与 PCB 布局优化指南
  • AI落地页生成实战:从代码片段到生产就绪页面的技术演进
  • Okbiye|开题报告 AI 一键生成,告别熬夜改框架,科研起步零内耗
  • Minimax Hub实战指南:从环境配置到AI工作流自动化
  • 面向AI应用的后端架构设计:协议选型、服务治理与可观测性
  • 2026好用的视频去水印工具:电脑手机在线免费软件优缺点对比
  • 程序员就业:2026 年还能靠什么拿到,用真实案例讲清边界
  • 政务类仿冒网络钓鱼攻击的作案路径与全域安全防控研究
  • TensorBoard 日志解析与自定义插件开发:从 tfevents 文件到 3 种数据提取方法
  • C 语言猜数字小游戏完整实现(附带 8 次机会限制 + 菜单选择)(作业考试学习必备系列001)
  • Claude偷改了你一行代码
  • 智能车越野组技术解析:环境感知、决策规划与运动控制
  • Redis集群模式深度对比:主从、哨兵与Cluster的工程选型指南
  • 国产AI编程助手合规实践指南:通义灵码、CodeGeeX等落地应用
  • TDengine RSMA — 时间维度的滚动预聚合
  • AI 时代架构师:转型成长路线图
  • 华为Met基于您提供的《Oracle EBS FA事务处理底层表数据字典》,我将为您构建一个专注于EBS FA资产模块智能查询的AI模型。这个模型的核心思想是:将结构化的数据字典转化为AI可以理解的领
  • iPhone 6 原理图设计规范解析:51页图纸中的5项专业标注与布局技巧
  • AI视频生成技术在游戏特效制作中的应用实践
  • CO2激光与UV激光钻孔对比:3种PCB基材成孔质量与效率实测分析
  • 2026前端最新八股文最新前端笔试题面试题ai基础入门知识题,开放题,场景题,15项面试真题 ,实战题,源码解析,面试题基础理论都有
  • 竞争存在论:存在的投影法则——三连续统框架下的认知与本质