Pwnage 2.0

This exploit in the S5L8900 bootrom is really the ultimate exploit, since it allows unsigned code to be run at the lowest level. It is available in all devices that use the S5L8900 - the iPhone, iPod Touch and iPhone 3G. It is also available on some non-iOS iPods, including the iPod nano (4th generation) and the iPod shuffle (3rd generation).

Exploit
After performing header validation (SHA1 & AES), the bootrom parses the certificates present at the footer of an uploaded IMG1. These certificates are plain DER-encoded ASN.1 X.509 certificates, and thus their parsing logic is quite complex.

The bootrom has a few complex structures used to handle the parsing, most notably every ASN.1 type parsed (X.509 Certificate/TBSCertificate and X.509 Name). Each one of the types is parsed based on a common function called with a different   array.

A  looks as follows:

With flags being a bitmap of:

streams (linearly) every DER tag/field present in the given blob, and in parallel walks through the array of. It matches the tag from the blob against the asn1_tag field of the. If they don't match (and  isn't set), the whole parse fails. If they do match, the following action is taken:


 * If  is set, the content of the streamed field is compared against   interpreted as a byte array of   bytes. If the content doesn't match, the parse fails.
 * If  is set,   is interpreted as a function pointer and called with the content of the ASN.1 field being currently visited. If the visitor returns an error, the parse fails.
 * If  is set,   is interpreted as a function pointer and called with the entire ASN.1 field (including tag and length bytes). If the visitor returns an error, the parse fails.

Then, an ASN.1 field tree traversal action is performed:


 * If, the current field extents and current step are pushed on an internal stack, and the inner contents of the field continue being parsed starting at der::steps[step_depth]. If the internal stack overflows, the parse fails.
 * If, the current field is skipped and the next field continues to be parsed by der::steps[step_breadth].
 * Otherwise (both  and  ), the internal stack is 'popped' and both the DER streaming and   is restored to whatever was saved on the internal stack. The   that was pushed has its   consulted for the next step to be executed, if that is also -1 then the stack continues to be popped. The parse fails if the stack underflows.

As the parse continues through the DER byte stream and the, a structure is constructed and populated with information retrieved from the certificate by the visitors. For example, the  field is recorded, the entire TBSCertificate structure extents are recorded, etc. After the parse of the certificate is done, two more   executions happen: on the   and   as recorded by the certificate visitors.

Certificate Parsing Bug
Most of the visitors in  take care to never trust the lengths specified in the DER stream. However, one visitor (Certificate ) is an exception - it copies over data from the expected signatureValue field in Certificate into the structure holding parsed certificate data without checking for maximum length.

Exploiting the bug
Offsets are those of the iPod nano (4th generation) S5L8720 bootrom. Every bootrom will likely have slightly different offsets.

The target structure looks as follows:

The signatureValue is copied to ;   looks as follows:

Now, certobj in  is a pointer. Where is the data actually held? It's in yet another object,, which is the overarching structure used to parse the entire certificate chain (three certificates):

For every certificate in the chain,  is called on , whose   is populated by one of   (each one after the other as the chain is parsed). Due to earlier checks, three certificates must be present in the footer for them to be parsed at all.

Finally, where is  stored? On the stack! In fact, directly after  there are 0x24 bytes of saved registers, with the last 4 bytes being the saved LR.

Thus, to mount the attack, we need to do the following:


 * 1) Present the BootROM with a valid image header with some certificates after the body. The body never gets to be checked or decrypted, so we can write anything we want there (as long as the sizes match the sizes in the header).
 * 2) Provide three certificates in the chain that match the bare minimum required by the certificate DER parse steps.
 * 3) Make the last certificate's   overflow into the saved LR. The original buffer is 256 bytes, we need to overflow it by 308 bytes (256 + 52) to leave the   structure, then by 0x20 more bytes to reach the saved LR, then provide 4 bytes of PC to override. Since the   is an ASN.1 BIT STRING, we need to prefix the tag value with a zero. This gives us in total 344 or 345 bytes to fill   with.

If we can't generate arbitrary image headers to set arbitrary footer certificate sizes we need to pad all certificates involved so that the  of the last cert is exactly the size we want to overflow (or at least not too long so that the copy doesn't cause a write to unmapped memory). Afterwards, with code exec, we can use the hardware AES engine to sign arbitrary headers to not have to worry about sizes.

Crafting the certificates is an exercise left to the reader. Maybe the exact constraints and process will be listed here at some point, but starting out with certificates from a legitimate WTF file and mangling the last certificate to overflow by exactly 344 bytes is a good start (possibly adjusting previous certs to make some space for the longer ).

Payload
The easiest place to stuff the payload is in the body of the image. The bootrom never gets to checking or decrypting it, so we can easily just put some executable code there. Depending on the bootrom, the image body will be placed somewhere in the beginning of SRAM ( for iPod nano (4th generation)). Then, our stack smash can simply point to that address and we get code execution.

Implementations

 * PwnageTool
 * QuickPwn
 * WinPwn
 * redsn0w
 * Iran