Monday, July 8, 2019

Malformed iMessage Could Cause iPhone Boot Loop

Project Zero (via Hacker News):

The method -[IMBalloonPluginDataSource individualPreviewSummary] in IMCore can throw an NSException due to a malformed message containing a property with key IMExtensionPayloadLocalizedDescriptionTextKey with a value that is not a NSString. This method calls [IMBalloonPluginDataSource _summaryText] which returns the property assuming it is a string, but this is not checked. The calling method then calls -[IMBalloonPluginDataSource _replaceHandleWithContactNameInString:] which calls im_handleIdentifiers on the NSString which is really an NSNumber, which throws an exception as the selector does not exist in that class.

On a Mac, this causes soagent to crash and respawn, but on an iPhone, this code is in Springboard. Receiving this message will case Springboard to crash and respawn repeatedly, causing the UI not to be displayed and the phone to stop responding to input. This condition survives a hard reset, and causes the phone to be unusable as soon as it is unlocked. The only way I could find to fix the phone is to reboot into recovery mode and do a restore. This causes the data on the device to be lost though.

The bug is fixed in macOS 10.13.4 and iOS 12.3, but what about customers on previous OS versions? Now that the bug is known, they could be targeted. And it doesn’t seem like Apple could intercept the bad messages at the server level without decrypting private messages.

NSSecureCoding can’t really protect against this kind of mistake. Maybe Swift could have, depending on how the code was written.

I recently ran into a similar bug with AVPlayer, where using the scroll wheel calls an internal method with the wrong data type where a number was expected, causing an exception and alert window. I’m sure sort of thing happens all the time, throughout the iOS/macOS and apps, but rarely are the potential consequences so dire.


2 Comments RSS · Twitter

Will people ever learn to sanitize all data coming over the network?

The design of exceptions in Objective-C was one of its few really bad points. In Scheme. Java, Python, or anything else sane, you'd catch the exception at the run loop, print an error, carry on. Fault-tolerant. Having no exception handling except death in critical systems like Springboard is just asking for trouble.

Sören Nils Kuklau

Leaving aside the type safety discussion, this also seems like a poor architecture:

On a Mac, this causes soagent to crash and respawn, but on an iPhone, this code is in Springboard.

Springboard in iOS is way more a single point of failure than Dock on macOS (which at least used to host all sorts of random stuff like Exposé, rather than just, y’know, the Dock). It takes on WindowServer, loginwindow, and more. Crash it, and the entire login session is gone.

I assume they originally did this kind of design due to performance/resource reasons (the original iPhone only having 128 MiB RAM). Around 6.0, they started moving some stuff to backboardd or whatever, but by version 12.3, with the average device having 2 GiB RAM, having Messages code in this monolithic process just seems a really bad design.

The only explanations I can find is:

backwards compatibility hacks
they haven’t gotten around to modernizing this

Neither of which is very flattering.

(I’m also not sure why soagent is called soagent, and why Apple couldn’t give it a more descriptive name, but at least it’s part of MessagesKit where it belongs.)

Leave a Comment