Archive

Archive for the ‘Information Security’ Category

Keychain Dumper Updated for iOS 5

January 25, 2012 7 comments

I am also the editor of the Neohapsis Labs blog. The following is reprinted with permission from
http://labs.neohapsis.com/

By Patrick Toomey

Direct link to keychaindumper (for those that want to skip the article and get straight to the code)

Last year I pushed a copy of Keychain Dumper to Github to help audit what sensitive information an application stores on an iOS device using Apple’s Keychain service.  I’ve received a few issue submissions on github regarding various issues people have had getting Keychain Dumper to work on iOS 5. I meant to look into it earlier, but I was not able to dedicate any time until this week. Besides a small update to the Makefile to make it compatible with the latest SDK, the core issue seemed to have something to do with code signing.

Using the directions I published last year the high level steps to dump keychain passwords were:

  1. Compile
  2. Push keychain_dumper to iOS device
  3. Use keychain_dumper to export all the required entitlements
  4. Use ldid to sign these entitlements into keychain_dumper
  5. Rerun keychain_dumper to dump all accessible keychain items
Steps 1-3 continue to work fine on iOS 5.  It is step 4 that breaks, and it just so happens that this step was the one step I completely took for granted, as I had never looked into how ldid works.  Originally, signing the entitlements into keychain_dumper was as simple as:
./keychain_dumper -e > /var/tmp/entitlements.xml

ldid -S/var/tmp/entitlements.xml keychain_dumper

However, on iOS 5 you get the following error when running ldid:

codesign_allocate: object: keychain_dumper1 malformed object

(unknown load command 8)

util/ldid.cpp(582): _assert(78:WEXITSTATUS(status) == 0)

Looking around for the code to ldid, I found that ldid actually doesn’t do much of the heavy lifting with regard to code signing, as ldid simply execs out to another command, codesign_allocate (the allocate variable below):

execlp(allocate, allocate, "-i", path, "-a", arch, ssize, "-o", temp, NULL);

The Cydia code for codesign_allocate looks to be based off of the odcctools project that was once open-source from Apple.  I am unclear, but it appears as though this codebase was eventually made closed-source by Apple, as the  code does not appear to have been updated anytime recently.  Digging into the code for codesign_allocate, the error above:

unknown load command 8

makes much more sense, as codesign_allocate parses each of the Mach-O headers, including each of the load commands that are part of Mach-O file structure.  It appears that load command 8 must have been added sometime between when I first released Keychain Dumper and now, as the version of codesign_allocate that comes with Cydia does not support parsing this header.  This header is responsible for determining the minimum required version of iOS for the application.  If someone knows a compile time flag to prevent this (and possibly other) unsupported header(s) from being used let me know and I’ll update the Makefile.  The other options to get the tool working again were to either update odcctools to work with the new Mach-O structure and/or figure out an alternative way of signing applications.

Historically there have been three ways to create pseudo-signatures for Cydia based applications (you can see them here).  The third uses sysctl, and is no longer valid, as Apple made some changes that make the relevant configuration entries read-only  The second option uses ldid, and was the approach I used originally.  The first uses the tools that come with OS X to create a self-signed certificate and use the command line development tools to sign your jailbroken iOS application with the self-signed certificate.  It appears as though the tools provided by Apple are basically the updated versions to the odcctools project referenced earlier.  The same codesign_allocate tool exists, and looks to be more up to date, with support for parsing all the relevant headers.  I decided to leverage the integrated tools, as it seems the best way to ensure compatibility going forward.  Using Apple’s tools I was able to sign the necessary entitlements into keychain_dumper and dump all the relevant Keychain items as before.  The steps for getting this to work are as follows:

  1. Open up the Keychain Access app located in /Applications/Utilties/Keychain Access
  2. From the application menu open Keychain Access -> Certificate Assistant -> Create a Certificate
  3. Enter a name for the certificate, and make note of this name, as you will need it later when you sign Keychain Dumper.  Make sure the Identity Type is “Self Signed Root” and the Certificate Type is “Code Signing”.  You don’t need to check the “Let me override defaults” unless you want to change other properties on the certificate (name, email, etc).
  4. Compile Keychain Dumper as instructed in the original blog post(condensed below):
ln -s /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/ sdk

ln -s /Developer/Platforms/iPhoneOS.platform/Developer toolchain

make
  1. scp the resulting keychain_dumper to your phone (any file system reference made here will be in /tmp)
  2. Dump the entitlements from the phone
./keychain_dumper -e > /var/tmp/entitlements.xml
  1. Copy the entitlements.xml file back to your development machine (or just cat the contents and copy/paste)
  2. Sign the application with the entitlements and certificate generated earlier (you must select “Allow” when prompted to allow the code signing tool to access the private key of the certificate we generated)
codesign -fs "Test Cert 1" --entitlements entitlements.xml keychain_dumper
  1. scp the resulting keychain_dumper to your phone (you can remove the original copy we uploaded in step 5)
  2. you should now be able to dump Keychain items as before
./keychain_dumper
  1. If all of the above worked you will see numerous entries that look similar to the following:
Service: Vendor1_Here

Account: remote

Entitlement Group: R96HGCUQ8V.*

Label: Generic

Field: data

Keychain Data: SenSiTive_PassWorD_Here

Now, the above directions work fine, but after dumping the passwords something caught my eye.  Notice the asterisk in the above entitlement group.  The Keychain system restricts access to individual entries according to the “Entitlement Group”, which is why we first dumped all of the entitlement groups used by applications on the phone and then signed those entitlements into the keychain_dumper binary.  I thought that maybe the asterisk in the above entitlement group had some sort of wildcarding properties.  So, as a proof of concept, I created a new entitlements.xml file that contains a single entitlement

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

 <dict>

     <key>keychain-access-groups</key>

     <array>

         <string>*</string>

     </array>

 </dict>

</plist>

The above file lists a single entitlement defined by “*”, which if the assumption holds, might wildcard all Entitlement Groups.  Using the above file, I recompiled Keychain Dumper and proceeded to resign the application using the wildcard entitlements.xml file.  Surprise….it works, and simplifies the workflow.  I have added this entitlements.xml file to the Git repository.  Instead of first needing to upload keychain_dumper to the phone, dump entitlements, and then sign the app, you can simply sign the application using this entitlements.xml file.  Moreover, the binary that is checked in to Git is already signed using the wildcard entitlement and should work with any jailbroken iOS device (running iOS 5), as there is no need to customize the binary for each user’s device/entitlements.

The consolidated directions can be found on the Github repository page, found here.   A direct link to the binary, that should hopeful work on any jailbroken iOS 5 device can be found here.

Categories: Information Security
Follow

Get every new post delivered to your Inbox.