📜 ⬆️ ⬇️

Critical bug in CoreGraphics on iOS

In this article we are looking for (and, characteristically, we find!) A critical bug in CoreGraphics in iOS. I’ll say right away that this bug certainly doesn’t pull into full-fledged vulnerability - its operation does not lead, for example, to arbitrary code execution. However, this bug allows you to crash applications that use WebKit: Mobile Safari, Google Chrome for iOS, all mail clients, etc., which can also be useful for a hacker in some situations. So, let's start the search.

Find a bug


For the search we will use this sandbox:


We will search for a bug in WebKit or in the system libraries that WebKit uses. Without further ado, let's follow a well-known path:
')
  1. Find some ancient multimedia format that is currently in very little use, but still supported by WebKit.
  2. Write a fuzzer for this format, run on some application that uses WebKit (for example, Mobile Safari) and leave to drink tea.
  3. ...
  4. Profit?! .. If not, go back to step 1.

Let's start with the first item. Having rummaged in Wikipedia and having looked at what formats of images supports WebKit, we will pay attention to XBM . This is a text format for black and white images, as old as a mammoth shit, but WebKit still supports it. Since XBM has not been used by anyone in the web for many years, the WebKit developers most likely have long since scored for testing and licking the corresponding code in the engine. So you can search for in this code some old-stop error.

Well, with the format decided. We turn to the second paragraph of our plan to search for a bug. Read the description of the XBM format , then find some .xbm file on the network and try to “spoil” it so that it would cause an error in WebKit or in some system library that WebKit uses. After a brief search, I got this file:

  #define test_width 16
 #define test_height 16
 static unsigned char test_bits [] = {
      0xff, 0xff, 0x01, 0x80, 0xfd, 0xbf, 0x05, 0xa0, 0xf5, 0xaf, 0x15, 0xa8,
      0xd5, 0xab, 0x55, 0xaa, 0x55, 0xaa, 0xd5, 0xab, 0x15, 0xa8, 0xf5, 0xaf,
      0x05, 0xa0, 0xfd, 0xbf, 0x01, 0x80, 0xff, 0xff};

If we open this file in Mobile Safari, we will see a small (16 by 16 pixels) image from concentric squares:


To “spoil” this file is of course better than a fuzzer specially written for this purpose, but fuzzer is too lazy to write, so we will first try to “spoil” the file in the old-fashioned way, with our hands. Let's play with test_width and test_height - all of a sudden, when rendering a picture, WebKit doesn’t check these values ​​and do we have something to fill up somewhere? Attempts to assign zero or negative values ​​of test_width and test_height unfortunately do not lead to anything. However, very soon we find out that for large values, test_width Mobile Safari crashes! For example, when trying to open such a file

  #define test_width 123456
 #define test_height 16
 static unsigned char test_bits [] = {
      0xff, 0xff, 0x01, 0x80, 0xfd, 0xbf, 0x05, 0xa0, 0xf5, 0xaf, 0x15, 0xa8,
      0xd5, 0xab, 0x55, 0xaa, 0x55, 0xaa, 0xd5, 0xab, 0x15, 0xa8, 0xf5, 0xaf,
      0x05, 0xa0, 0xfd, 0xbf, 0x01, 0x80, 0xff, 0xff};

Mobile Safari just closes without any messages. Google Chrome for iOS behaves the same way. Considering that both browsers use WebKit, it looks like we found a bug either in WebKit itself or in some system library that WebKit uses to render images.

Bug analysis


So where exactly does our bug live and how does it work? Why applications fall? Open our “spoiled” file in Mobile Safari under the debugger and see the backtrace:


Let's take a closer look at the argb32_image_mark function in CoreGraphics more closely, because judging by the backtrace, it is the one that causes the memset that is dropping the application. Run Mobile Safari again under the debugger and see what happens in the argb32_image_mark function if the browser .xbm an .xbm file with an image width of 123456 . And the following happens (please take into account that the code that is not related to the bug is omitted, and the addresses differ from those in the backtrace screenshot because of ASLR):

  CoreGraphics`argb32_image_mark (at 0x2f96a970):
 ...
 0x2f96a97a: mov r6, sp;  r6 = sp
 0x2f96a97c: mov r5, r0;  r5 = first argument argb32_image_mark
 ...
 0x2f96a9a0: ldr r0, [r5, # 4];  r0 = [first argument + 4] = image width
 ...
 0x2f96a9b0: str r0, [r6, # 100];  save the width of the image to a local variable
 ...
 0x2f96a9d2: ldr r3, [r1, # 12];  r3 = [second argument + 12]
 ...
 0x2f96a9ea: ldr r1, [r6, # 100];  get the width of the image from a local variable in r1
 ...
 0x2f96a9f6: adds r0, r3, # 6;  r0 = r3 + 6
 0x2f96a9f8: muls r0, r1, r0;  r0 = r1 * r0
 0x2f96a9fa: add.w r2, r0, # 96;  r2 = r0 + 96
 ...
 0x2f96aa04: adds r0, r2, # 3;  r0 = r2 + 3
 0x2f96aa06: bic r0, r0, # 3;  r0 = r0 & 0xfffffff8
 0x2f96aa0a: sub.w r11, sp, r0;  r11 = sp - r0
 0x2f96aa0e: mov sp, r11;  sp = r11

After following these instructions, the new sp value is set to

  sp = sp - (([second argument + 12] + 6) * image width + 99) & 0xfffffff8

However, whatever image I opened, [ + 12] was always zero. Given this fact, we can assume that

  sp = sp - (6 * image width + 99) & 0xfffffff8

The function argb32_image_mark poorly controls the parameter and if the width is too large, sp “leaves” far beyond the bounds of the selected stack. Then the memset call immediately follows and an attempt to fill the memory with zeros far behind the stack leads to the crash of the application:

  0x2f96aa10: mov r0, r11;  the new sp is the address for memset
 0x2f96aa12: movs r1, # 0;  memory reset starting from this address
 0x2f96aa14: blx 0x2fa339cc;  memset call
 ...

Actually this is a critical bug in CoreGraphics which was discussed in the title of the article.

Where does it work?


I have a bug playing on Mobile Safari and Google Chrome for iOS on


I did not try other devices / iOS versions, since I don’t have them. In the comments and personal messages they also write that the bug is reproduced on


If anyone wants to try to crash Safari on his iOS device, here is the link:

codedigging.com/test.xbm

findings


The bug is of course critical, but from a security point of view, not particularly scary for users. The most that happens is an application that uses WebKit will not be able to chew .xbm image and .xbm . Unpleasant but not fatal.

I told Apple, I hope that everything will be fixed in the next iOS update.

Happy debugging!

Update Jun 20, 2014: Today I received an email from Apple sec team. They write that the error has been reviewed, CVE will be assigned to it and it will be fixed in the nearest iOS update. "Half a year will not pass ..." (c)

Update Jun 30, 2014

  APPLE-SA-2014-06-30-3 iOS 7.1.2

 iOS 7.1.2 is now available and addresses the following:

 ...

 CoreGraphics
 Available for: iPhone 4 and later,
 iPod touch (5th generation) and later, iPad 2 and later
 Impact: Viewing randomly crafted XBM file may lead to an
 unexpected application termination or arbitrary code execution
 Description: An unbounded stack allocation issue
 handling of XBM files.  This issue was addressed through improved
 bounds checking.
 CVE-ID
 CVE-2014-1354: Dima Kovalenko of codedigging.com 

Hmm, well, ok, fixed in iOS 7.1.2. Well done, cho :)

Source: https://habr.com/ru/post/154301/


All Articles