1

I would like to allow users of my app to upload images in different formats that other users can view (including webm videos).
But I would also like to make sure that the images are actual images and not harmful to display.
So heres my 3 concrete question:

  • Is it enough to check the magic number and the file size to ensure an image is safe to display?
  • should I convert the images into a uniform format or can I just safely use the same format again?
  • are there certain formats I should avoid because of possible vulnerabilites?
user2741831
  • 155
  • 1
  • 5

1 Answers1

1

should I convert the images into a uniform format or can I just safely use the same format again?

Quite probably, you will want to crop/resize the image anyway, and possibly add a watermark (which could be visible or not), it is common practice to trace stolen pictures.

So attempting conversion is one way of validating that the uploaded file is a valid image. It goes without saying, but check the extension too. There should be a whitelist of allowed extensions (mainly jpg, jpeg, gif, png). Keep in mind that the file name including extension may be uppercase or even mixed case. Convert the file name to lowercase before extracting the extension.

Do not use the original file name (which could be malicious, contain special characters, or path names like ../../.., or be simply too long for your file system), instead you will probably want to use an ID which could be the ID of the user but it would be better to derive a random string like a UUID, so as not to expose the user ID to the outside world.

Even if a hacker succeeds in uploading a webshell, the directory that stores the images should not allow execution of scripts like php files or whatever. You address this by setting appropriate default file permissions (umask for example) and some additional directives, that will depend on the type of webserver you run.

Obviously hackers will try to bypass the extension check so here is a check list for you. Tampering with the magic number is mentioned, so that alone is not a guarantee that the file will be sound. But the resulting uploaded file may very well be unexploitable anyway.

Is it enough to check the magic number and the file size to ensure an image is safe to display?

There should be a limit to the file size, that it is up to you to determine. But in itself limiting the file size provides no security. A webshell can be a one-liner.

are there certain formats I should avoid because of possible vulnerabilites?

The concern is not about the image format, but rather the library you will be using to process that image. For example, the popular ImageMagick package suffered a serious flaw a few years ago. If you're using PHP you could use the builtin functions like imagefromjpeg or the GD library (but it's been a while I haven't touched them so my references may be outdated).

When you've made your choice, do an Internet search for past/present vulnerabilities affecting the particular function/package you intend to use. Even if previous reported flaws have been patched, you still have to make sure that your own version is sufficiently recent (some distros provide old packages, which could still be vulnerable).

Kate
  • 7,092
  • 21
  • 23
  • I would argue that checking the extension is just a waste of time and resources. That's *literally* just a text string. The magic number at least prevents someone from uploading *obviously* bogus data. – vidarlo Jul 14 '21 at 20:00
  • @vidarlo so even if someone tampers with the magic number, the worst I have to expect is that the image won't display anything? – user2741831 Jul 14 '21 at 20:35
  • @user2741831 no, but if the magic number is not a valid image format, you can safely throw it away and stop further processing. The worst is obviously a 0-day that gives an attacker a remote shell, or infects popular image viewers with malware while being valid image... – vidarlo Jul 14 '21 at 20:38
  • I meant if the magic number indicated an image but the image data was something potentially dangours that I shouldn't serve to users. The main reason I made this thread because I thought perhaps it might be dangerous to echo arbitrary images to users of an app – user2741831 Jul 14 '21 at 20:40
  • If the file has an extension like .jpg or .png then the webserver will render it to the browser as-is, even if the file is corrupted or garbage, because the extension matches a known MIME type and the webserver knows how to handle it. On the other hand a file ending in .php .asp could potentially be executed by a remote call. In fact you don't have to store images in a folder, you can also store them in a database and display them on demand with a URL like http://test.com/picture/12345. All your endpoint has to do is send the binary data back along with appropriate headers. – Kate Jul 14 '21 at 20:50
  • Yeah I'll probably use the database approach for this, especially since modern databases can cache recent results automatically. I'll probably use a seperate database from the other data or even database cluster to store the images to ensure I can still efficiently do snapshots of it. – user2741831 Jul 14 '21 at 21:00