Cloud file storage providers such as Box and DropBox will typically thumbnail uploaded images for purposes of showing icons and previews. Predictably, both providers appear to use ImageMagick for thumbnailing. So what happens if we come knocking with the ImageMagick 1-day CESA-2017-0002?
CESA-2017-0002 is a vulnerability in the RLE image decoder, where the allocated render canvas memory is not initialized under some conditions. This leads to the server generated thumbnail and preview being based on uninitialized memory. The pixels of the resulting preview can be used to reconstruct chunks of server memory.
The vulnerability itself is not particularly complicated, and will be fully described in a future post that describes a scenario where it has more bite.
Sandboxing and isolation
This vulnerability has interesting interactions with sandboxes and process boundaries. While sandboxes can do wonders to mitigate vulnerabilities such as remote code execution and filesystem leaks, they do little for bugs that leak memory content, such as this one.
On the other hand, good use of process boundaries can help against bugs that leak memory content. In a one-process-per-thumbnail model, the virtual address space of the process is only going to contain the attacker's data, and likely not the private data of anyone else.
In the case of Box and DropBox, I've not seen any indications of leaking anyone else's private data. It's likely that they are both using a one-process-per-thumbnail model. Certainly, one "easy" way to integrate ImageMagick would be to use the convert binary to run individual image transform jobs. This would give a one-process-per-thumbnail model.
Trying to get a bounty
Let's face it, getting a bug bounty is kind of cool. Given that we don't think we can leak someone else's data, might there be anything else in the address space that we could leak that is worthy of a bounty? Unfortunately, most bounty programs exclude minor leaks such as precise versioning information or configuration details.
But one idea does occur to us: since we're leaking the content of free'd memory chunks, we're very likely to see pointer values for things like malloc() freelist entries. The specific values of these pointers will tell us what level of ASLR exists in the process. If the level of ASLR is anything other than "full ASLR", would that be worth a bounty? Maybe. Let's proceed to try and leak some pointer values.
Exfiltrating bytes of memory
To exfiltrate bytes of memory, we will upload a color RLE file of 16x8 dimensions and download the resulting PNG file from the file preview panel. For both Box and DropBox, the preview has the following useful traits:
- Produces a PNG download. PNG is a lossless format, so the PNG pixel values should correspond exactly with raw memory bytes.
- Leaves image dimensions alone for smaller image sizes. This is useful because any downscaling would result in information loss.
pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
Bytes highlighted in red appear to be pointers to "low" locations in virtual memory, such as 0x00000000021839f0. Running the test again, we get 0x0000000001cc19f0.
For DropBox, we dump out the following values of interest, with the same rules for highlights, and similar results:
0000000 30 76 38 02 00 00 00 00 00 00 00 00 00 00 00 00
0000020 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00
0000040 00 00 00 00 00 00 00 00 00 07 2c c9 5a 7f 00 00
0000060 00 00 00 00 00 00 00 00 54 52 53 54 ff ff ff ff
0000100 70 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00
0000120 70 75 38 02 00 00 00 00 00 00 00 00 00 00 00 00
0000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000220 00 00 00 00 00 00 00 00 61 02 00 00 00 00 00 00
0000240 d0 66 38 02 00 00 00 00 c0 75 38 02 00 00 00 00
So, can we conclude what ASLR situation exists in the processes we dumped data from? Yes. At first glance, the ASLR may appear reasonable because all of the pointers are bouncing around between invocations. But there are at least 4 possible Linux ASLR setups that we should try and distinguish between. Here are some examples of these four setups for Linux x86_64:
1) Position independent executable, no system ASLR (/proc/sys/kernel/randomize_va_space)
555555554000-555555580000 r-xp 00000000 fc:01 659830 /usr/bin/curl
55555577f000-555555782000 r--p 0002b000 fc:01 659830 /usr/bin/curl
555555782000-555555783000 rw-p 0002e000 fc:01 659830 /usr/bin/curl
555555783000-555556f4b000 rw-p 00000000 00:00 0 [heap]
4) Statically positioned executable, and system ASLR
00400000-00401000 r-xp 00000000 fc:01 931015 /usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16/display
00600000-00601000 r--p 00000000 fc:01 931015 /usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16/display
00601000-00602000 rw-p 00001000 fc:01 931015 /usr/lib/x86_64-linux-gnu/ImageMagick-6.8.9/bin-Q16/display
0242d000-024bd000 rw-p 00000000 00:00 0 [heap]
Box vs. DropBox
When the same vulnerability crops up in two different places, the opportunity arises to perform comparisons. Both Box and DropBox appeared to have a one-process-per-conversion model and both responded to the report promptly by performing the most important action, which was to firmly curtail the number of ImageMagick decoders on the attack surface. Further to my previous post about a likely ancient ImageMagick on Box, no evidence of ancient ImageMagick was found on DropBox.
Determining whether ASLR is correctly enabled or not on the server is usually opaque to web application security testing. But by finding a vector to leak the content of server memory, we can match up pointer values to the status of ASLR on the server.
For my trouble, DropBox awarded me a $343 bounty. Box does not have a bounty program at this time.
Lack of ASLR on the ImageMagick conversion process could be a useful foot in the door to a memory corruption attack. One-shot exploitation of image decoding is fairly hard, because you have to defeat ASLR and also land the corruption exploit within the context of a single image decode, where you typically don't have scripting available. If, however, the binary is at a fixed location due to missing ASLR, exploitation is a much more tractable problem.