About 0x00
This article mainly analyzes PHP's use of the GD Library's imagecreatefrompng () function to reconstruct a PNG image may result in a local file inclusion vulnerability.
When the system exists the point that the file contains, can contain the picture file; In addition, the system exists image upload, uploaded images using the Imagecreatefrompng () function to reconstruct the picture and save it locally, it is likely that the file contains a vulnerability.
Usually, the system in the implementation of the image upload function, in order to prevent users to upload images containing malicious PHP code, you can use the GD library to reconstruct the picture, GD Library to reconstruct a series of functions imagecreatefrom*, will check the image specification, verify the legitimacy of the picture, in order to resist the image contains malicious PHP Code of attack.
So, can the imagecreatefrom* series function completely resist the attack of inserting PHP code in the picture, this article takes the Imagecreatefrompng () function as the research object, explores the possibility of implementing the malicious PHP code in the image reconstructed in PNG format, And the conditions that need to be met.
PNG file format, Imagecreatefrompng function parsing, modify picture, upload, file contains ...
0x01 PNG Picture format
The PNG image to be rebuilt still contains malicious PHP code, first of all to have a basic understanding of the PNG image format. PNG supports three image types: indexed color images (INDEX-COLOR images), grayscale images (grayscale images), True color images (True-color images), where indexed color images are also known as palette-based images ( palette-based images).
The standard PNG file structure consists of a PNG header that joins multiple PNG data blocks, such as PNG signature | PNG Chunk | PNG Chunk | ... | PNG Chunk.
PNG identity
The PNG is identified as the head of the PNG image as a fixed 8-byte, as follows
4E OD 0A 1 a 0A
PNG data block
PNG defines two types of data blocks, one is called the key data block (critical chunk), the standard data block; The other is called the auxiliary data Block (ancillary chunks), an optional data block. Critical data blocks define 3 standard blocks, each of which must contain them. 3 standard data blocks are: IHDR, IDAT, Iend.
Here are 4 pieces of data: IHDR, Plte, IDAT, iend
PNG data block structure
PNG file, each chunk consists of 4 parts length | Type (name) | Data | CRC, described below
Length:4 bytes, just length of the data, not include type and CRC type:4 bytes, ASCII letters ([a-z,a-z]) crc:4bytes
The values in the CRC (cyclic redundancy check) field are computed for the data in the chunk Type code domain and the chunk database domain. The CRC-specific algorithm is defined in ISO 3309 and ITU-T v.42, and its value is calculated according to the following CRC code generation polynomial: X +x, +x, +x 4 +x +x +x 7 +x 5 +x +x 2 +x+1
Header chunk: It contains basic information about the image data stored in the PNG file and is to appear in the PNG data stream as the first block of data, and only one file header block in a PNG data stream. IHDR
The file header data block consists of 13 bytes, which are shown below
name of the domain |
Number of bytes |
Description |
Width |
4 bytes |
Image width, in pixels |
Height |
4 bytes |
Image height, in pixels |
Bit depth |
1 byte |
Image depth. Indexed color images: 1,2,4 or 8 grayscale images: 1,2,4,8 or 16 True Color images: 8 or 16 |
ColorType |
1 byte |
Color type. 0: Grayscale image, 1,2,4,8 or 162: True color image, 8 or 163: Indexed color image, 1,2,4 or 84: Grayscale image with alpha channel data, 8 or 166: True color image with alpha channel data, 8 or 16 |
Compression method |
1 byte |
Compression method (LZ77 derivation algorithm) |
Filter method |
1 byte |
Filter method |
Interlace method |
1 byte |
Interlaced scanning method. 0: Non-interlaced 1:adam7 (7 times interlaced method developed by Adam M. Costello) |
Palette Data Block Plte (palette chunk) contains color transform data related to indexed color images (indexed-color image), which is only relevant to indexed color images and is placed before image data chunk.
Plte data blocks are palette information that defines an image, and Plte can contain 1~256 palette information, each of which consists of 3 bytes:
Color |
bytes |
meaning |
Red |
1 byte |
0 = black, 255 = red |
Green |
1 byte |
0 = black, 255 = Green |
Blue |
1 byte |
0 = black, 255 = Blue |
Therefore, the length of the palette should be a multiple of 3, otherwise it would be an illegal palette. Number of colors = LENGTH/3
For indexed images, palette information is required, the color index of the palette is numbered starting with 0, then 1, 2 ..., the color of the palette cannot exceed the number of colors specified in the color depth (as deep as 4, the number of colors in the palette may not exceed 2^4=16), otherwise this will result in the PNG image being illegal.
Image data Block Idat: It stores the actual data, which can contain multiple sequential sequential image blocks in the data flow. Idat stores the real data information of the image
Image end Data iend (Image trailer Chunk): It is used to mark a PNG file or the data stream has ended and must be placed at the end of the file.
Under normal circumstances, the PNG file ends with the following 12 characters:
4E (42 60 82) for the XX
Due to the definition of the block structure, the length of the iend data block is always 0 (00 00 00 00, unless the information is added artificially), the data identification is always iend (4E 44), so the CRC is always AE 42 60 82
0x02 php imagecreatefrompng () function
Having a basic understanding of the PNG image format can help us to better understand the underlying implementation of the Imagecreatefrompng () function. Analysis of PHP source code (PHP 5.6.20), the PHP imagecreatefrompng () function to reconstruct the image, the core is the Gdimagecreatefrompngctx () function of the GD library.
The analysis of the GDIMAGECREATEFROMPNGCTX () function in the GD library shows that the function first detects the PNG signature, and the non-rule returns null. Then read the original PNG image file to Png_ptr, and then read the picture information from the png_ptr to Info_ptr, and then to get IHDR information, read IDAT data, etc., not discussed here. Only the validation processing of the read Plte database in the Png_read_info () function is discussed here.
#!cgd_png.c/gdimagecreatefrompngctx{...if (png_sig_cmp (SIG, 0, 8)! = 0) {/* Bad signature */ return NULL; /* Bad signature */} ... png_set_read_fn (png_ptr, (void *) infile, Gdpngreaddata);p ng_read_info (png_ptr, info_ptr); / * Read all PNG info up to image data */...}
To understand the internal implementation of Png_read_info (), you can read the Libpng source code (libpng 1.6.21). When the picture type is an indexed image, Png_read_info () calls the Png_handle_plte function for CRC checking when it reads to Plte Chunk
#!cpngread.c/png_read_info{...else if (chunk_name = = Png_plte) png_handle_plte (png_ptr, info_ptr, length); ...} Pngrutil.c/png_handle_plte {... #ifndef png_read_opt_plte_supported if (png_ptr->color_type = = PNG_COLOR_TYPE _palette) #endif { png_crc_finish (png_ptr, (int) length-num * 3); } ...}
Analysis of the underlying source, PNG signature is impossible to insert PHP code, IHDR storage is a PNG image information, a fixed length and format, the program will extract the image information data to verify, it is difficult to insert PHP code, and Plte mainly for CRC checksum color number A simple check such as a legal check, it is possible to insert PHP code in the data field.
From the analysis of Plte chunk verification, when the original image format to the index picture, Plte data block in the case of meeting the PNG format specification, the program will also do CRC check. Therefore, in order to write the PHP code to the Plte data block, not only to modify the contents of the database domain as PHP code, and then modify the CRC to the correct CRC checksum value, when the code to be populated too long, you can change the length field value, to meet the length of a multiple of 3, and the number of colors does not exceed the color depth The number of colors specified in the For example, if the Bit depth in the IHDR data block is 08, the maximum number of colors is 2^8=256, then the length of the Plte data block does not exceed 3*256=0x300. This length is sufficient for writing PHP a word trojan or creating a backdoor file.
So are all PNG images able to insert PHP code into the Plte data block? The following is illustrated by experiments.
0X03 Experimental Verification
PNG supports indexed color images (INDEX-COLOR images), grayscale images (grayscale images), True color images (True-color images) Three types of pictures, and plte data blocks are required for indexed images, Therefore, it is very possible for an indexed image to insert PHP code into the Plte data block.
Excerpt from the Gdimagecreatefrompng () function in the GD library is described below.
If the PNG image being loaded is a truecolor image, the resultinggdimageptr would refer to a truecolor image. If the PNG image beingloaded is a palette or grayscale image, the resulting gdimageptrwill refer to a palette image.
The function converts indexed color images and grayscale images into indexed color images, converting true color images to true color images. Below to convert the three types of pictures, test picture address: Picture. The PHP code is as follows
#!php
Read IHDR data block information, color deep 8bits, color type=0x03, for the index image type, change its plte data block as follows, modify the data to
The CRC process is calculated as follows
Imagecreatefrompng () reconstructed pictures are as follows
As you can see, the plte blocks in the reconstructed image retain the PHP code, and the rebuild also adds the PHYs data block, which has no effect on the results we care about. Instructions to insert PHP code successfully.
Original image with no plte data block as shown below
Insert the PLTE data block and write the PHP code
After the reconstructed picture is as follows
You can see that the reconstructed picture is converted to an indexed image type, and the Plte data block is rewritten, and writing to the PHP code fails
Original image with no plte data block as shown below
Insert the PLTE data block and write the PHP code
After the reconstructed picture is as follows
Can see the true color type picture reconstructed picture does not contain the PLTE data block, writes the PHP code to fail
0X04 Summary
The above analysis and experiment shows that the imagecreatefrompng () function does not completely prevent the insertion of PHP code in the image, and when the image type is indexed, the PHP code can be inserted successfully in Plte chunk, while other types of images do not implement Plte Chu Insert the PHP code into NK. Finally, thanks to the following references for my research help.
Attached, modify the index image to insert the address of the PHP code GitHub
The accompanying code implements the Plte data block that is rewritten when the payload length is greater than the Plte data length. However, in the experimental process found that the imagecreatepng () function reconstruction of the image Plte data block length is still the original length, that is, and can not arbitrarily expand the length of the Plte data block, the specific reasons need to further analyze the source code, that is, to load the payload can not exceed Plte The length given by the data block.
Usually, the length of the Plte data block can satisfy us to insert basic PHP backdoor code, there is a point, is it possible to pry the Earth?
Of course, there are many shortcomings in this article, I hope you criticize correct
0x05 Data Reference
1. GitHub LIBGD
2. gd2.0.33 Manual
3. LIBGD Home
4. PNG book
5. PNG Chunk
6. png file Format parsing