This article from Feng Libin's blog, the original address: http://www.fenglibin.com/use_java_to_check_images_type_and_security.html
I. Generally, you can verify whether a file is an image in the following three ways:
1) Determine whether the file extension is the required image Extension
This kind of judgment is a lot of method, but this method is very inappropriate. Others slightly change the extension of a file that is not an image to the image extension, this verification is bypassed. If the uploaded file is shell, PHP, or JSP, then your website can be basically put in the hands of others.
However, this method is not completely useless. We can place it in the outermost layer of the image. If the extension name of a file is not the image extension we require, therefore, we do not need to check the subsequent content format. To a certain extent, this helps reduce the pressure on servers, otherwise, all the files will be determined by the server after being uploaded, which will waste some resources.
2) based on the first few bytes of the file, that is, the magic number, you can determine the first several bytes of different file types. You can check my other website introduction: the magic number of different file types.
However, this method is very unreliable because it can only verify the first few bytes of the file. If someone modifies the extension of an executable PHP file to PNG, then add the "89 50" two bytes in front, and then bypass this authentication method.
The following is an example program that uses Java code to obtain the first two bytes of a file:
[Java]
View plaincopyprint?
- Import java. Io. file;
- Import java. Io. fileinputstream;
- Import java. Io. ioexception;
- Import java. Io. inputstream;
- Public class imagetypecheck {
- Public static string bytestohexstring (byte [] SRC ){
- Stringbuilder = new stringbuilder ();
- If (src = NULL | SRC. Length <= 0 ){
- Return NULL;
- }
- For (INT I = 0; I <SRC. length; I ++ ){
- Int v = SRC [I] & 0xff;
- String HV = integer. tohexstring (v );
- If (HV. Length () <2 ){
- Stringbuilder. append (0 );
- }
- Stringbuilder. append (HV );
- }
- Return stringbuilder. tostring ();
- }
- Public static void main (string [] ARGs) throws ioexception {
- String ImagePath = "C:/favicon.png ";
- File image = new file (ImagePath );
- Inputstream is = new fileinputstream (image );
- Byte [] bt = new byte [2];
- Is. Read (BT );
- System. Out. println (bytestohexstring (BT ));
- }
- }
import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream; public class ImageTypeCheck { public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } public static void main(String[] args) throws IOException { String imagePath = "c:/favicon.png"; File image = new File(imagePath); InputStream is = new FileInputStream(image); byte[] bt = new byte[2]; is.read(bt); System.out.println(bytesToHexString(bt)); }}
However, this method is the same as the extension, and is not completely useless. At least you can perform a simple check in the early stage to pave the way for the next check.
3) obtain the width and height attributes of an image.
If we can get the width and height attribute of an image normally, it must be an image. We cannot get the width and height attribute of a non-image file, the following is a Java code used to determine whether an image can be obtained based on the image width and height attribute:
[Java]
View plaincopyprint?
- /**
- * Read the file and obtain its width and height to determine whether the current file is an image. This is a very simple method.
- *
- * @ Param imagefile
- * @ Return
- */
- Public static Boolean isimage (File imagefile ){
- If (! Imagefile. exists ()){
- Return false;
- }
- Image IMG = NULL;
- Try {
- IMG = ImageIO. Read (imagefile );
- If (IMG = NULL | IMG. getwidth (null) <= 0 | IMG. getheight (null) <= 0 ){
- Return false;
- }
- Return true;
- } Catch (exception e ){
- Return false;
- } Finally {
- IMG = NULL;
- }
- }
/*** It is very easy to judge whether the current file is an image by reading the file and obtaining its width and height. ** @ Param imagefile * @ return */public static Boolean isimage (File imagefile) {If (! Imagefile. exists () {return false;} image IMG = NULL; try {IMG = ImageIO. read (imagefile); If (IMG = NULL | IMG. getwidth (null) <= 0 | IMG. getheight (null) <= 0) {return false;} return true;} catch (exception e) {return false;} finally {IMG = NULL ;}}
Ii. security check and handling of image files
Now, we can finally determine whether a file contains images. However, what if some illegal code is added to an image file that can be browsed normally:
This is some IFRAME code added at the end of a normal image. I tried to open this image separately and put it on a webpage. Although this will not be executed, however, it does not mean that other code will not be inserted. Anti-virus software (such as avast) reports a virus for such modifications.
So how should we prevent this kind of thing, that is, it can be opened normally, it has the correct image file extension, and it can also get its width and height attributes? Oh, we can rewrite this image at this time, add a watermark to it or resize it, so that the newly generated image will no longer contain such malicious code, the following is a Java implementation for adding Watermarks:
[Java]
View plaincopyprint?
- /**
- * Add an image watermark
- *
- * @ Param srcimg target image path, for example, C: \ kuku.jpg
- * @ Param waterimg watermark image path, for example, C: \ kuku.png
- * @ Param x the offset between the watermark image and the left side of the target image. If X is less than 0, it is in the middle.
- * @ Param y the offset between the watermark image and the target image. If y is less than 0, it is in the middle.
- * @ Param Alpha transparency (0.0 -- 1.0, 0.0 is completely transparent, and 1.0 is completely opaque)
- * @ Throws ioexception
- */
- Public final static void addwatermark (string srcimg, string waterimg, int X, int y, float alpha) throws ioexception {
- // Load the Target Image
- File file = new file (srcimg );
- String ext = srcimg. substring (srcimg. lastindexof (".") + 1 );
- Image image = ImageIO. Read (File );
- Int width = image. getwidth (null );
- Int Height = image. getheight (null );
- // Load the target image to the memory.
- Bufferedimage = new bufferedimage (width, height, bufferedimage. type_int_rgb );
- Graphics2d G = bufferedimage. creategraphics ();
- G. drawimage (image, 0, 0, width, height, null );
- // Load the watermark image.
- Image waterimage = ImageIO. Read (new file (waterimg ));
- Int width_1 = waterimage. getwidth (null );
- Int height_1 = waterimage. getheight (null );
- // Set the transparency of the watermark image.
- G. setcomposite (alphacomposite. getinstance (alphacomposite. src_atop, alpha ));
- // Set the position of the watermark image.
- Int widthdiff = width-width_1;
- Int heightdiff = height-height_1;
- If (x <0 ){
- X = widthdiff/2;
- } Else if (x> widthdiff ){
- X = widthdiff;
- }
- If (Y <0 ){
- Y = heightdiff/2;
- } Else if (Y> heightdiff ){
- Y = heightdiff;
- }
- // "Draw" the watermark image from the original image.
- G. drawimage (waterimage, X, Y, width_1, height_1, null );
- // Close the paint brush.
- G. Dispose ();
- // Save the target image.
- ImageIO. Write (bufferedimage, ext, file );
- }
/*** Add an image watermark ** @ Param srcimg target image path, for example, C: \ kutuku.jpg * @ Param waterimg watermark image path, for example, C: \ kutuku.png * @ Param x the offset between the watermark image and the left side of the target image. If X is <0, the offset between * @ Param Y and the top side of the target image is displayed, if y is <0, * @ Param Alpha transparency (0.0 -- 1.0, 0.0 is completely transparent, 1.0 is completely opaque) * @ throws ioexception */public final static void addwatermark (string srcimg, string waterimg, int X, int y, float alpha) throws ioexception {// load the target image file = new fi Le (srcimg); string ext = srcimg. substring (srcimg. lastindexof (". ") + 1); image = ImageIO. read (File); int width = image. getwidth (null); int Height = image. getheight (null); // loads the target image to the memory. Bufferedimage = new bufferedimage (width, height, bufferedimage. type_int_rgb); graphics2d G = bufferedimage. creategraphics (); G. drawimage (image, 0, 0, width, height, null); // load the watermark image. Image waterimage = ImageIO. read (new file (waterimg); int width_1 = waterimage. getwidth (null); int height_1 = waterimage. getheight (null); // sets the transparency of the watermark image. G. setcomposite (alphacomposite. getinstance (alphacomposite. src_atop, alpha); // set the position of the watermark image. Int widthdiff = width-width_1; int heightdiff = height-height_1; If (x <0) {x = widthdiff/2;} else if (x> widthdiff) {x = widthdiff;} If (Y <0) {Y = heightdiff/2;} else if (Y> heightdiff) {Y = heightdiff ;} // "Draw" the watermark image from the original image. G. drawimage (waterimage, X, Y, width_1, height_1, null); // close the paint brush. G. Dispose (); // Save the target image. ImageIO. Write (bufferedimage, ext, file );}
Through the above methods, we should be able to avoid the security issues of malicious code in most of the images. However, due to my poor personal skills, there may be some considerations. Please kindly advise.