Fixing ImageTragick in Rails

Ashkan PK
Primer Engineering
Published in
4 min readMay 13, 2016

Originally released 26 years ago, ImageMagick has become the de facto open-source solution for image processing. So what happens when something so widely used suffers a major exploit?

And the internet caught fire.

The vulnerability received its own branding and spread through developer communities very quickly, and for good reason. It is easy to exploit and gives an attacker the ability to execute arbitrary code on your server (full control). Exact numbers are hard to find, but there are likely a large amount of sites that still have this vulnerability given ImageMagick’s widespread use. Let’s fix that!

Why should I care?

You are vulnerable if you process user uploaded images with ImageMagick. Note that gems such as RMagic, MiniMagick, and Paperclip all use ImageMagick to do their processing.

If you don’t think that this is a big deal, you should take into account that:

  1. The vulnerability is trivial to exploit. Take a look at the very simple proof of concepts.
  2. CloudFare and Sucuri blog have found exploits being used in the wild to search for vulnerable systems.

Recommended Mitigations

Given how serious the issue is, our engineering team at Primer quickly identified and mitigated the vulnerabilities. This post covers how we made the recommended changes to a Ruby on Rails application. We’ll keep it updated as the situation develops.

Testing Magic Bytes of Untrusted Files

Some of the exploits rely on the fact that ImageMagick relies on the file’s extension to determine the file type. Since extensions can be changed, this is not at all reliable. A more resilient way to check the file type is to inspect the magic bytes, which are the first or last few bytes of a file. These bytes are consistent in all files of a given format; for example, JPEG files always start with the bytes FF D8 (hex representation).

Testing an untrusted file for the magic bytes in Ruby is simple. We can open a file stream using Ruby’s File class, and read the first X bytes with the stream’s readpartial method. With that, if we want to only allow PNG, GIF, JPEG files to be uploaded, we can pass the file to a new method, file_is_image, before passing it to ImageMagick for processing.

Example method for checking Magic Bytes for GIF, PNG, and JPEG files in Ruby.

Disabling Vulnerable Coders

ImageMagick uses many coders for reading and writing to file formats, as well as extending other functionality such as opening URLs. Nine of these coders were found to contain security flaws. Thus, the next mitigation is to ensure that ImageMagick doesn’t use them.

We can disable coders using an ImageMagick policy file, usually found at /etc/ImageMagick/policy.xml on a linux server. The recommended policy can be found here, and bans nine coders. As far as we can tell, most of these coders aren’t used very widely, but you should make sure you don’t use their functionality before disabling them. Specifically, if you open image URLs with ImageMagick, you’re using the URL encoder.

At Primer, we use Elastic Beanstalk on AWS to deploy to our Rails instances, so we wrote an EBExtension configuration file to deploy this policy to our EC2 instances.

An Elastic Beanstalk extension to update our ImageMagick policy in our EC2 instances.

ImageMagick Alternatives

It has been noted that part of the reason that ImageMagick has this vulnerability (and had many others in the past) is due to the sheer amount of flexibility it provides. It tries to work with many file types and support a lot of features across all of them. Due to this, it seems that many code paths can be insecure, and there may be more undiscovered vulnerabilities.

Many applications use ImageMagick for generating icons and other simple use cases. If your use case isn’t very complex, consider switching to a simpler, more specific library.

Sandboxing Image Processing

Others have noted that processing untrusted images is inherently unsafe and recommend sandboxing any processes serving this purpose. One possible method is using seccomp-bpf.

Another method we’re exploring is using AWS Lambda for all of our image processing. This will ensure that any insecure image processing is isolated from our EC2 server instances. Since image processing is a memory hog, another advantage here is the decreased memory usage on our servers. One method for using Lambda with Rails can be found here.

Closing

At Primer, the security of our customer data is a top priority. As such, we watched this issue very closely and mitigated it within hours of the exploit being disclosed. We’ll keep this guide updated as the situation progresses and better solutions become available.

Have any questions or thoughts on the situation? Let us know in the comments!

--

--

Ashkan PK
Primer Engineering

Mixed bag of identities. Currently Engineer @Lyft.