特殊的文件上传漏洞(一)
# 特殊的文件上传漏洞(一)
我们来讲讲特殊的文件上传漏洞(一)。
# GET-00 截断绕过
Pass-11
抓包,看到在请求的 url 上出现了敏感的字符,save_path=…/upload/
出现这样的字样,我们首先需要想想,这个上传保存路径是否可控?
首先为了上传成功首先得把 backdoor.php 改成
filename="backdoor.jpg" |
接下来我们猜想,save_path 可以指定某个路径存储,我们可以让它存在别的地方嘛?
save_path=../ |
上传成功
确实生成了
那也就是说,控制 save_path 是可行的,但想到如果 save_path 变成一个文件路径的话,应该会报错。果不其然
如果 能有这么一种方法
,能让 save_path 直接成为最后保存的文件路径该多好,比如 save_path=../upload/11.php
虽然上传的是 backdoor.jpg,但存储的时候直接就成了 php 格式。有办法做到么?有!答案就是 GET-00 截断、
只需要修改:
save_path=../upload/11.php%00 |
成功上传不报错
upload/11.php 也生成了
菜刀正常连接。搞定!
除了在 url 里加 %00 之外,有些时候,也可以在 filename 里加
比如这样改
filename="backdoor.jpg+" |
然后在 hex 里找到 + 的位置(十六进制为 2b),将其替换成 00
其实用到的原理就是: 00截断
就是借 php 解析字符串的时候 遇到00截断停止,不再解析
的特点,把文件路径提前 错误地识别成了文件
(本应该是路径才对)。
这就衍生出了,post-00 截断
# POST-00 截断绕过
Pass-12
save_path 出现在了 POST 请求的参数区
那么我们可以这样构造
../upload/123.php+ |
然后在 hex 中修改 + 的十六进制 0x2b 为 00
上传成功
菜刀也可以成功连接 123.php 文件
# 图片马绕过 (白名单绕过)
Pass-13
本题考察对于文件头解析 + 图片马合成
# 绕过文件头解析
常用文件头:
.jpeg
;.jpe
;.jpg
,"JPGGraphic File"
.gif
,"GIF 89A"
.zip
,"Zip Compressed"
.doc
;.xls
;.xlt
;.ppt
;.apr
,"MS Compound Document v1 or Lotus Approach APRfile"
JPEG(jpg),文件头:FFD8FF |
有些 web 程序会根据传上来文件的头几个字节来判断是属于什么类型,比如 GIF 的魔术字是 GIF 89A
我们尝试在一句话木马前面增加 GIF 89A
:
GIF 89A |
可以看到成功被识别成了 gif 而上传给了服务器
我们将此路径 ./upload/5020221003232644.gif
拷贝,注意只拷贝一个点
发现题目还给了一个文件包含的链接
|
当前 http://www.upload_lab.com/include.php
页面,可以接收一个 GET型参数
file,我们如下构造:
http://www.upload_lab.com/include.php?file=./upload/5020221003232644.gif |
可以发现,只显示了 GIF 89A,一句话木马没有显示在页面,说明成功解析成了 php。
菜刀连接,成功:
# 绕过 unpack 头两字节
使用 windows 的 copy 命令
copy /? |
我们准备两个文件,一个是正常的 png 图片 webshell.png
,一个是一句话木马的 php 文件 backdoor.php
copy webshell.png /b + backdoor.php /b backdoor.png |
那么可以上传这个文件,可以看到成功上传
菜刀成功连接:
回过头来看源码:
function getReailFileType($filename){ |
其中,isset 函数通过下面的会很好理解:
- 就是一个变量已声明,且不为 NULL(可以是’ ')时,会返回真。
// 结果为 TRUE,所以后边的文本将被打印出来。 |
# 绕过 getimagesize
Pass-14 和 Pass-13 绕过方式一样,同样 上传图片copy拼接马
即可。
我们直接来看源码
function isImage($filename){ |
其中,getimagesize () 函数将测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型及图片高度与宽度。
|
返回结果说明
- 索引 0 给出的是图像
宽度
的像素值 - 索引 1 给出的是图像
高度
的像素值 - 索引 2 给出的是图像的
类型
,返回的是数字,其中 1 = GIF,2 = JPG,3 = PNG,4 = SWF,5 = PSD,6 = BMP,7 = TIFF (intel byte order),8 = TIFF (motorola byte order),9 = JPC,10 = JP2,11 = JPX,12 = JB2,13 = SWC,14 = IFF,15 = WBMP,16 = XBM - 索引 3 给出的是一个
宽度和高度的字符串
,可以直接用于 HTML 的 image 标签 - 索引 bits 给出的是图像的
每种颜色的位数
,二进制格式 - 索引 channels 给出的是图像的
通道值
,RGB 图像默认是 3
- 索引 mime 给出的是图像的
MIME 信息
,此信息可以用来在 HTTPContent-type
头信息中发送正确的信息,如: header (“Content-type: image/jpeg”);
stripos () 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
stripos(string,find,start)
参数 | 描述 |
---|---|
string | 必需。规定被搜索的字符串。 |
find | 必需。规定要查找的字符。 |
start | 可选。规定开始搜索的位置。 |
# 绕过 exif_imagety
exif_imagetype () 函数是 PHP 中的内置函数,用于确定图像的类型。
int exif_imagetype( string $filename ) |
参数:该函数接受单个参数 $filename,该参数保存图像的名称或 URL。
返回值:此函数返回与 IMAGETYPE 常量之一相对应的整数,如下所示:
- IMAGETYPE_GIF(1)
- IMAGETYPE_JPEG(2)
- IMAGETYPE_PNG(3)
- IMAGETYPE_SWF(4)
- IMAGETYPE_PSD(5)
- IMAGETYPE_BMP(6)
- IMAGETYPE_TIFF_II(7)
- IMAGETYPE_TIFF_MM(8)
- IMAGETYPE_JPC(9)
- IMAGETYPE_JP2(10)
- IMAGETYPE_JPX(11)
- IMAGETYPE_JB2(12)
- IMAGETYPE_SWC(13)
- IMAGETYPE_IFF(14)
- IMAGETYPE_WBMP(15)
- IMAGETYPE_XBM(16)
- IMAGETYPE_ICO(17)
- IMAGETYPE_WEBP(18)
查看源码:
function isImage($filename){ |
其中,如果要使用内置函数 exif_imagetype 的话,一定需要先开启 php_exif 模块
开启方法如下:
找到 C:\phpStudyB\PHP\php.ini
文件
服务器配置说明:
1. 在 php.ini 文件中找到 ;extension=php_exif.dll
,去掉前面的分号
2. 在 php.ini 文件中找到 ;extension=php_mbstring.dll
,去掉前面的分号,并将此行移动到 extension=php_exif.dll 之前,使之首先加载。
- 去掉分号、移动到前面后:
3. 找到 [exif]
段,把下面语句的分号去掉。
;exif.encode_unicode = ISO-8859-15 |
-
去掉分号后:
开启后,如果还想再次验证是否开启 exif 模块的话,在 WWW 目录下放置 phpinfo.php
然后直接访问 http://www.upload_lab.com/phpinfo.php
, 并在页面 Ctrl+F
搜索 exif
即可。(不开启是搜索不到的)