Saturday, 14 January 2012

BMP and the ICC standard - A Tale in Vulnerability Research Failure

For every vulnerability, blog post, whitepaper or conference presentation there are numerous dead ends, blind alleys and wasted hours that don’t bare fruit. However researchers rarely talk about these expeditions even though the workings and thought processes might be interesting. Instead the findings are consigned to a notes.txt in a folder somewhere to be forgotten about. However, when these failures do get discussed, they can be insightful; a good example is the now infamous Ben Nagy e-mail ‘How to FAIL at Fuzzing’ from December 2010.

While we don’t promise to be as amusing or insightful as Ben, this is our story from Friday 13th January, 2012. In the middle of the afternoon I tweeted:

This tweet prompted a private response, asking for more information. So join us on a tale that started with reading a totally unrelated set of guidelines, then a Friday morning spent digging, to come out with nothing. This is our notes.txt for ‘BMP and ICC’.

The story starts with the reading of the ‘Secure Coding Guidelines for the Java Programming Language, Version 4.0’ from the morning twitter roll (good read) where we tripped across this guideline:

Say what? Bitmap (BMP) images able to access local files? This has got to be interesting. The low hanging fruit bell goes off. The initial theory this would be a good way to trace when files where opened via UNC paths. With a hop skip and a jump off to Google we went looking for details. Turns out that Oracle are a bit anxious about this attack as they've suffered a couple of bloody noses in the past:
CVE2007-2789 states:
The BMP image parser in Sun Java Development Kit (JDK), when running on Unix/Linux systems, allows remote attackers to cause a denial of service (JVM hang) via untrusted applets or applications that open arbitrary local files via a crafted BMP file, such as /dev/tty.
It turns out that Chris Evans found this vulnerability in 2006, released an advisory in 2007 titled ‘JDK image parsing library vulnerabilities (ICC parsing, BMP parsing)’ and even released a test case.

But how does it work? It turns out that ICC color profiles are not limited to BMP images. Instead they’re a high-level graphics standard which provide the following functionality:
Profiles describe the color attributes of a particular device or viewing requirement by defining a mapping between the device source or target color space and a profile connection space (PCS).
OK, so? Well back to BMP. First we dug into the BMP file header (who knew there were five versions). Thankfully Microsoft provide a clean structure for working with BMP headers.  The key part of the header is:
bV5CSType - PROFILE_LINKED. This value implies that bV5ProfileData points to the file name of the profile to use (gammas and endpoints are ignored).
OK great, so a quick tool got hacked together to set bV5CSType to PROFILE_LINKED and bV5ProfileData to 0xFFFFFFFF (theory being any application parsing this field would either crash or throw a first chance exception at least). And... drum roll... nothing in any of the BMP parsers on our Windows 7 machines other than some colour in what was a completely white image previously.

So we ran our new BMP header tool on Chris’s test case from 2007, hmmm the output sort of looks correct (red text) but not exactly compared to the Microsoft specification:

DIBPlay.exe "c:\Data\!Research\ICC\evil2.bmp"
[i] File size   : 264
[i] BMP C Size  : 14
[i] Size        : 256
[i] Offset      : 254
[i] BMP v5 Size : 124
[i] Size        : 124
[i] Width       : 1
[i] Height      : 1
[i] CS Type     : 00000003
[i] CS Size     : 00000008
[i] CS Prof Data: 0000007e

So what’s going on here then? So we had to check the v4 BMP header. Again Microsoft provides a nice clean header for v4 of the BMP specifcation which states:
bV4CSType (Recx note: also known as ColorSpaceType) - The color space of the DIB. The following table lists the value for bV4CSType. LCS_CALIBRATED_RGB - This value indicates that endpoints and gamma values are given in the appropriate fields. See the LOGCOLORSPACE structure for information that defines a logical color space.
Sure enough the LOGOCOLORSPACE structure has what we’re after:
lcsFilename - A null-terminated string that names a color profile file. This member is typically set to zero, but may be used to set the color space to be exactly as specified by the color profile. This is useful for devices that input color values for a specific printer, or when using an installable image color matcher. If a color profile is specified, all other members of this structure should be set to reasonable values, even if the values are not completely accurate.
But it looked more like a v5 than a v4 header. The reason we say this is that Microsoft defines PROFILE_LINKED is as 'LINK' in WinGDI.h. compared to '3' in Java and ImageMagick. So it looks valid for Java but not Microsoft although the size indicates a v5 header.

Got it, now we realised there are no CRC checks on any of this. Take Chris’s original evil2.bmp change the path contained within it (to c:\Moooo instead of /dev/tty). Fire up ProcessMonitor from Microsoft Sysinternals, load the BMP file in every installed application that can parse BMPs and... drum roll... nothing...

At which point we came to the conclusion this is an obscure feature that basically no one supports. So how did Java get rolled? Off to the code we went. Sure enough we find where Java had it's issues:

So we can see the code, understand how it came about in the Java implementation and the patches they've put in. We also had a quick look at a number of BMP parsers and none seemed to support this external file feature for ICC colour maps.  But alas a vulnerability that had promise didn't yield anything, during our three hour investigation at least.

We don't think all is lost if someone wants to pick up the baton, there may be mileage in other formats that support similar ICC features, or high-end graphics applications we don't have access to. For example some quotes we found during our investigation regarding other formats that appear a little interesting.

PDF/VT-2 is designed for multi-file exchange and based on one of PDF/X-4p, PDF/X-5g, or PDF/X-5pg. PDF/VT-2 documents can reference external ICC profiles, external page contents, or both. A PDF/VT document and all its referenced PDF files and external ICC profiles are collectively called a PDF/VT-2 file set.
ICC profile part names SHOULD contain four segments, using ?/Documents/n/Metadata/? as the first three segments, where n is the fixed document that uses these parts [S2.30]. If an ICC profile part is shared across documents, the part name SHOULD contain two segments, using ?/Metadata/? as the first segment and a second segment that is a string representation of a globally unique identifier, followed by an extension [S2.30]. ICC profiles SHOULD use an appropriate extension for the color profile type. [S2.30] [Example:  ?.icm? end example]
For us, for now at least, it's time to save and close our BMP ICC notes.txt file.

Note: Updated 3 hours after the original post to add a little more information and correct a few small errors.

No comments:

Post a Comment