2

Please see the upload code below. the method is called within a try, catch. If the code for the image utilities is needed, just say. Basically, everything is handled in raw bytes and then stored to the DB. I currently render images as base 64 but am moving towards using the bottom snippet in web api.

My main thoughts are:

  • The image is uploaded in raw bytes. While it could contain a virus it wouldn't run
  • The server has a max file size set, and prior to this method the user is authenticated, and are checked they are not concurrently downloading any other files (one at a time) with a max upload of 100 images an hour. This would, I hope, stop a specific image DoS.
  • Because the image is modified to be a certain size (100 x 100) then if it's not a valid image type this would throw an exception and everything is binned
  • I could add a white list on file extensions before this if you can see any potential issues?
  • I believe Image.FromStream is safe from an overflow attack

    public string StoreProfileImage(ImageViewModel model, string userId)
    {
            var postedImg = model.Image;
            var image = Image.FromStream(postedImg.InputStream, true, true);
            if (image != null)
            {
                Rectangle rect = new Rectangle();
                rect.X = (int)Math.Floor(model.x / model.scale);
                rect.Y = (int)Math.Floor(model.y / model.scale);
                rect.Width = (int)Math.Floor(model.width / model.scale);
                rect.Height = (int)Math.Floor(model.height / model.scale);
    
                // crop the image
                var croppedImg = ImageUtilities.CropImage(image, rect.Height, rect.Width, rect.X, rect.Y);
                // resize to max pic size
                var resizedImg = ImageUtilities.ResizeImage(100, 100, croppedImg);
                // convert to bytes
                byte[] imageData = ImageUtilities.ImageToByteArray(resizedImg);
    
                using (var db = new DbContext())
                {
                    var userImage = new UserImage
                    {
                        ImageBytes = imageData,
                        ImageName = postedImg.FileName,
                        UserId = userId,
                        IsProfileImage = true
                    };
    
                    // add new users image
                    db.UserImage.Add(userImage);
                    db.SaveChanges(); 
                }
                return ImageUtilities.BytesToBase64(imageData);
            }
            return null;
        }
    

Rendering snippet

 HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
 result.Content = new ByteArrayContent(image.ImageBytes);
 result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
 return result;

2 Answers 2

3

While sanitizing the image by resizing it is a good idea there were several critical bugs in image processing libraries in the past. Which means that the process of resizing the image itself could trigger such a bug and thus cause DOS with a complexity attack against the image manipulation library or even remote code execution. That's why the process of resizing should be done within some kind of VM or sandbox and should be also limited in CPU and memory usage.

And then there are several ways of resizing. I'm not familiar with the implementation you use but it might be that the meta data of the image are preserved (i.e. comments, flags, creation time etc) and thus might still be used later inside an attack. So you better convert the image first into some format like PPM which has no ability to store meta data to remove any kind of potential harmful meta data.

I'm also not familiar what your code of storing the image in the database really does in the implementation. Hopefully it uses parameter binding or similar techniques, because otherwise a malicious image might also be used for an SQL injection attack.

As for reading the image you should be aware that browsers often ignore the content-type you send depending on the context. This means if the URL is used as the source for the script tag the image will be interpreted as script, even if the content type is image/png (Chrome does not allow this but others do). Similar context enforcement can be done with a forced download. For example you could sent malware hidden by an image type with <a href=image.png download=malware.zip> and it might even have the correct magic bytes for the image type at the front because extraction of ZIP files often ignores junk at the beginning of the ZIP file. But if you removed the meta data like I've recommended you are probably safe against this kind of misuse.

2
  • Hi Staffan, thanks for your time. I use System.Drawing so I would have thought it's secure by now (or as well as any library would be). The meta data stripping is a very valid point, thanks. The db storage is linq so yes it uses parameters. I will look further into stripping meta data Commented Mar 19, 2016 at 21:03
  • 1
    @user2330270: I would not be sure that it is safe. Image and video handling functions are often heavily optimized and usually are not hardened to deal with (maliciously) broken input. Commented Mar 19, 2016 at 21:09
0

So you have a HTTP file upload for images, and some code to resize the image on the server, and you're asking if it is "secure" (against all things)?

No, nothing is secure.

The image is uploaded in raw bytes. While it could contain a virus it wouldn't run.

Why do you think that? With a bug in the web server, and specific byte patterns made to use this bug, it could get executed before it even reaches your processing code. Having code to resize images can't prevent that.

...max file size...stop...DoS

There are many kinds of DOS/DDOS attacks. Resizing images won't help.

Because the image is modified to be a certain size (100 x 100) then if it's not a valid image type this would throw an exception and everything is binned

Files which are both valid image and malware are no problem.
Images which keep their malware part unchanged while resizing, ie. the malware is not part of the pixel/color data, are no problem either.

I could add a white list

What for? This won't help.

I believe Image.FromStream is safe from an overflow attack

And if it is not like you believe? Right.

That aside, you listed your thoughts about some specific attacks, but what's about the huge rest?

Resizing, or better converting, images certainly helps against some things in some cases,
but it's no magic bullet.

7
  • Thank you for your time. Please can you expand and re-evaluate: 1. "There are many kinds of DOS/DDOS attacks. Resizing images won't help." my point wasnt the resizing, it was the limitation of the number of uploads per user in a time frame 2. "What for? This won't help" why not? file extension white list is normally recommended. do you mean it wont in this example? 3. "With a bug in the web server, and specific byte patterns made to use this bug, it could get executed before it even reaches your processing code" what exactly will be run ? any example or useful links? Commented Mar 19, 2016 at 20:31
  • @user2330270 DOS/DDOS: With your upload number limitation for a registered user, how do you prevent millions of HTTP requests by unregistered users to drain your bandwidth?
    – deviantfan
    Commented Mar 19, 2016 at 20:35
  • They fail to be authenticated and so fail. My usage of "specific" dos meant yes, they CAN dos me, but it's not image related. They could do it on any authenticate method in my application Commented Mar 19, 2016 at 20:36
  • @user2330270 Filename extension: Ah, you mean that (that's why I asked). But no, this won't help at all. To start with, why does the attacker need to use the right extension? Calling a program .mp3 is no problem.
    – deviantfan
    Commented Mar 19, 2016 at 20:37
  • @user2330270 Web server bug etc.: what exactly will be run This depends on the bug and the data ... depending on the bug "just everything the attacker wants". There are no specific links, because this is a huge topic.
    – deviantfan
    Commented Mar 19, 2016 at 20:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .