文件上传基础

文件上传

原理

网站Web应用都有一些文件上传功能,比如文档、图片、头像、视频上传,当上传功能的实现代码没有严格校验上传文件的后缀和文件类型,此时攻击者就可以上传一个webshell到一个Web可访问的目录上,并将恶意文件传递给如PHP解释器去执行,之后就可以在服务器上执行恶意代码,进行数据库执行、服务器文件管理,服务器命令执行等恶意操作。还有一部分是攻击者通过Web服务器的解析漏洞来突破Web应用程序的防护。

基础知识

MIME:定义:MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,是描述消息内容类型的因特尔标准。MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
意义:MIME设计的最初目的是为了在发送电子邮件时附加多媒体数据,让邮件客户程序能根据其类型进行处理。然而当它被HTTP协议支持之后,它的意义就更为显著了。它使得HTTP传输的不仅是普通的文本,而变得丰富多彩。

一些常用类型的MIME:

文件类型	                   后缀名	           MIME

超文本标记语言文本	         .html	             text/html
xml文档	                   .xml	              text/xml
普通文本	                  .txt	              text/plain
PDF文档	                  .pdf	               application/pdf
Microsoft Word文件	       .word	            application/msword
PNG图像	                  .png	              image/png
GIF图形	                    .gif	               image/gif
JPEG图形	                  .jpeg,.jpg	      image/jpeg
au声音文件	                  .au	                audio/basic
MIDI音乐文件	            .mid, .midi	         audio/midi, audio/x-midi
RealAudio音乐文件	       .ra, .ram	          audio/x-pn-realaudio
MPEG文件	                  .mpg,.mpeg	       video/mpeg
AVI文件	                     .avi	               video/x-msvideo
GZIP文件	                   .gz	               application/x-gzip
TAR文件	                     .tar	               application/x-tar

js前端绕过

存在js前端判断,通过return checkfile()判断上传的文件类型是否正确;

解决办法:1、删除前端代码中的checkfile(),使前端无法对上传的文件进行判断。

​ 2、先上传一个符合条件的文件,然后使用burp抓包,修改文件类型为php,放包,这样就可以绕过js的前端检测。less-1

MIME检测与绕过

检测:如果服务端代码是通过Content-Type的值来判断文件的类型,那么就存在被绕过的可能,因为Content-Type的值是通过客户端传递的,是可以任意修改的 。

会检测文件的MIME类型,然后判断是否符合条件;

绕过;使用burp抓包,修改请求的Content-Type类型从而绕过检测,上传php文件。less-2.。

黑名单检测与绕过

1、一些会进行黑名单检测,符合数据库里面黑名单的文件类型,将不允许上传;

但是我们可以上传那些没有被过滤的文件类型。

asp,asxp,php,jsp

phtml,php3,php4,php5,pht

大小写绕过

 $file_ext = strtolower($file_ext); //转换为小写 这个函数会将文件后缀名转化为小写
如果没有这类型的函数进行黑名单的检测,我们可以考虑使用大小写绕过的方式进行文件上传。
    例如php--pHP、PHP、PHp。
    less-6
   

空格绕过

$file_ext = trim($file_ext); //首尾去空   会将文件后缀名前后的空格去除
在没有这种函数的情况下,我们可以使用在后缀名后面加空格的方法绕过黑名单检测 less-7

加点绕过

 $file_name = deldot($file_name);//删除文件名末尾的点
在没有这类型函数的情况下,我们可以在文件名后加.绕过黑名单检测。

::$DATA绕过

$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
在没有这类型函数的情况下我们可以在文件名后加字符串::$DATA绕过黑名单检测
补充:    Windows本地文件系统中的文件流(File Streams):

当从 Windows shell 命令行指定创建文件时,流的完整名称为 "filename:stream name:stream type",如示例中所示: "myfile.txt:stream1:$DATA"

流类型

下面是 NTFS 流类型(也称为属性类型代码)的列表。 某些NTFS 内部的流类型 ,格式未记录。

流类型	说明
::$ATTRIBUTE_LIST	包含组成文件的所有属性的列表,并标识每个属性的位置。
::$BITMAP	索引用于管理目录的B-Tree空间的位图。B-Tree以4 kB块管理(无论群集大小),此用于管理这些块的分配。每个目录都存在此流类型。
::$DATA	数据流。 默认数据流没有名称。 可以使用 FindFirstStreamW 和 FindNextStreamW 函数枚举数据流。
::$EA	包含扩展的属性数据。
::$EA_INFORMATION	包含有关扩展属性的支持信息。
::$FILE_NAME	文件的名称,采用 Unicode 字符。 这包括文件的短名称以及任何硬链接。
::$INDEX_ALLOCATION	目录的流类型。用于实现大目录的文件名分配。这个流表示目录本身,并包含目录的所有数据。对这种类型流的更改将被记录到NTFS更改日志中。$INDEX_ALLOCATION流类型的默认流名是$I30,所以“DirName”、“DirName::$INDEX_ALLOCATION”和“DirName:$I30:$INDEX_ALLOCATION”都是等价的。
::$INDEX_ROOT	该流表示索引的B-Tree的根。每个目录都存在此流类型。
::$LOGGED_UTILITY_STREAM	类似于::$DATA,但是操作被记录到NTFS更改日志中。用于EFS和Transactional NTFS (TxF)。":StreamName:$StreamType"对EFS是":$EFS:$LOGGED_UTILITY_STREAM",对TxF是":$TXF_DATA:$LOGGED_UTILITY_STREAM"。
::$OBJECT_ID	用于标识链接跟踪服务的文件的16字节 ID。
::$REPARSE_POINT	重新 分析点 数据。
对NTFS格式下的一个文件而言,至少包含一个流,即data流(其stream type为$DATA),data流是文件的主流,默认的data流其stream name为空。默认一个文件如果被指定了流,而该流没有stream type的话会在存储时自动添加$DATA。例如上面看到的例子myfile.txt:stream1:$DATA在存储时实际上是为myfile.txt:stream1,但在查询结果中需要去除:$DATA,否则会出现参数错误,这个是notepad不能很好的支持流所导致的。

对文件夹而言,没有data流,其主流是directory流(stream type为$INDEX_ALLOCATION),directory流默认的stream name是$I30。尽管文件夹默认没有data流,但用户可为其指派data流。

点空格点绕过黑名单检测

$file_name = deldot($file_name);//删除文件名末尾的点
 $file_ext = trim($file_ext); //首尾去空
当这两个函数同时使用时我们可以通过点空格点绕过
    例如1.php. .我们最终上传的文件是1.php.

双写绕过

 $file_name = str_ireplace($deny_ext,"", $file_name);
str_ireplace函数会将$deny_ext黑名单里面的文件名替换为空
 str_ireplace函数:
    str_ireplace(find,replace,string,count)
                  参数	描述
                  find	必需。规定要查找的值。
                  replace	必需。规定替换 find 中的值的值。
                  string	必需。规定被搜索的字符串。
                  count	可选。一个变量,对替换数进行计数。

%00截断(未能实验成功)

文件头检测绕过

有些服务器会对文件的头部进行简单的匹配,进行检测文件是否是符合条件的,我们可以在文件前追加合法的文件头,从而绕过服务器对文件头的检测,从而成功上传文件。

例如 :在头部加GIF 89a。

图片木马

一些服务器会对所上传文件内容进行检测,这时可以制作图片木马,绕过服务器的检测

图片马制作命令:copy 图片文件.jpg|png|gif/b +木马文件.php /a 生成的文件名.jpg|png|gif|

例:copy 1.jpg /b + 2.php /a 3.jpg

image-20220421134001359

常用的图片检测函数

getimagesize()

获取图片宽度高度、大小尺寸、图片类型、用于布局的img属性

原理:这个函数的意思是:会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求的

exif_imagetype()函数

原理:读取一个图像的第一个字节并检查其签名。

move_uploaded_file() (有这么一个特性,会忽略掉文件末尾的 /.)

函数将上传的文件移动到新位置。

若成功,则返回 true,否则返回 false。

补充知识:
explode(separator,string[,limit]) 函数,使用一个字符串分割另一个字符串,并返回由字符串组成的数组。
end(array)函数,输出数组中的当前元素和最后一个元素的值。
reset(array)函数,把数组的内部指针指向第一个元素,并返回这个元素的值
count(array)函数,计算数组中的单元数目,或对象中的属性个数
————————————————

文件二次渲染

​ 在我们上传文件后,网站会对图片进行二次处理(格式、尺寸,保存,删除 要求等),服务器会把里面的内容进行替换更新,处理完成后,根据我们原有的图片生成一个新的图片(标准化)并放到网站对应的标签进行显示。

绕过方法:配合文件包含漏洞

​ 将一句话木马插入到网站二次处理后的图片中,也就是将二次渲染后保留的图片和一句话木马制作成图片马,再配合文件包含漏洞解析图片马中的代码,获取webshell。

配合条件竞争漏洞(未能实验成功)

​ 竞争条件是指多个线程在没有进行锁操作或者同步操作的情况下同时访问同一个共享代码,变量,文件等,运行的结果依赖于不同线程访问数据的顺序

思路:我们可以上传一个有写文件功能的木马文件,后端会先将其放置在临时存放路径,然后才检验上传文件是否和要求的文件一致,如果不符合就会删除文件。那如果我们在 从文件上传成功到开始检验文件后缀 的 这一段时间,我们进行访问该文件,那么就会导致防护被绕过,那就是相当于重命名这一过程就会被绕过,那么只要在删除改木马文件之前访问该木马文件,我们就可以写入新木马。(打个比方就是 你打开一个文件,然后你要删除它,这个时候系统就会提示你该文件正在被访问或者占用,无法执行删除命令)

posted @ 2022-10-27 11:07  GTL_JU  阅读(163)  评论(0编辑  收藏  举报