me.mello Posted June 13, 2011 Report Posted June 13, 2011 IntroductionSafari is one of the top 5 browsers known for its innovative look and feel reflected in every product of Apple! It offers one of the best ways to read online, greater support for HTML5, and other new features that make the web even better.Like other browsers, Safari also comes with built-in password manager feature for securely storing and managing the user's web login passwords. This article is set to expose - in first ever public disclosure - password secrets of Safari including the stored password location, encryption algorithm and code for decryption of stored passwords !Safari Password Storage LocationSafari features good password manager with better security model and encryption algorithms to keep it as much as secure as possible. Unlike other browsers such as Firefox, Chrome, you cannot see the stored passwords in Safari. You can enable or disable the Safari password manager by toggling the option through "Settings -> AutoFill -> Usernames & Passwords" (as shown below). Once enabled Safari will prompt to save the password for every website login for the user. Upon confirmation, website URL along with username & password are saved to secret password file.Safari stores all such web login passwords at a secret file named 'keychain.plist' at following location (based on platform)[Windows XP]C:\Documents and Settings\<username>\Application Data\Apple Computer\Preferences[Windows Vista & Windows 7]C:\Users\<username>\AppData\Roaming\Apple Computer\PreferencesSafari stores the contents of 'keychain.plist' in 'Binary Property List' file format - variation of Property List format used by Apple for storing binary data. Here is how typical 'keychain' file will look like,Decoding the Safari 'Keychain' Secrets !Looking at above 'keychain file' content, there is hardly anything you can make out. Only hint that you get here is the 'bplist' keyword at the beginning of file.After long search hours on 'bplist' keyword, I finally figured out the way to decode its content to plain XML file. Apple provides the tool called 'plutil.exe' for playing with these 'Property List' files. You can find this console tool at following location[Windows x86]C:\Program Files\Common Files\Apple\Apple Application Support[Windows x64]C:\Program Files (x86)\Common Files\Apple\Apple Application SupportHere is the command to covert cryptic 'keychain.plist' file to easily readable 'keychain.xml' fileplutil.exe -convert xml1 -s -o c:\keychain.xml "c:\users\administrator\appdata\roaming\apple computer\preferences\keychain.plist"This is how it will look like after decoding to XML fileInternals of Safari Encryption AlgorithmThe generated XML file (as shown above) contains encrypted password data along with website URL and username information. This stored password data is encoded using BASE64 algorithm. Note that original password data stored in 'keychain.plist' file is not encoded with BASE64. When we convert it to XML using Plutil tool, the encrypted password data is further encoded with BASE64 format.Once you decode the password using BASE64 you will see original encrypted password data. Safari uses standard 'Windows Data Protection' mechanism (DPAPI) to encrypt the password data with user isolation layer. Windows DPAPI provides functions like CryptProtectData/CryptUnprotectData for easy encryption/decryption of user oriented sensitive data such as passwords. Safari uses CryptProtectData along with static entropy (salt) to securely encrypt all website login passwords. Finally it is stored in the 'keychain.plist' file with other user login information.Decoding & Decryption of Safari PasswordAs mentioned in previous section, successful password recovery will require following 2 steps 1. Base64 Decoding of password data from XML file 2. Windows DPAPI decryption of encrypted dataFirst you have to use standard Base64 decoder algorithm to get original password data from encoded password bytes in XML file. After that we have to perform decryption of this encrypted password data. In order to decrypt this encrypted password data we need to figure out salt data used in CryptUnprotectData. Here is the salt data that I found during my reverse engineering work,Entire salt generation algorithm and decryption functions are within the Apple shared library 'CFNetwork.dll' which is present at following location,[Windows x86]C:\Program Files\Common Files\Apple\Apple Application Support[Windows x64]C:\Program Files (x86)\Common Files\Apple\Apple Application SupportHere is the disassembly of CFNetwork.dll from IDA Pro showing the location of salt generation & decryption functionInitially salt generation algorithm appeared to be dynamic but after few reversing session on different systems my doubts cleared and it was just static data. Salt data is of 144 byte size and ends with standard signature pattern as 'com.apple.Safari' as shown in the above screenshot.Once you get hold of the salt data, the encrypted password can easily be decrypted using CryptUnprotectData function as shown belowBYTE salt[] = { 0x1D, 0xAC, 0xA8, 0xF8, 0xD3, 0xB8, 0x48, 0x3E, 0x48, 0x7D, 0x3E, 0x0A, 0x62, 0x07, 0xDD, 0x26,0xE6, 0x67, 0x81, 0x03, 0xE7, 0xB2, 0x13, 0xA5, 0xB0, 0x79, 0xEE, 0x4F, 0x0F, 0x41, 0x15, 0xED,0x7B, 0x14, 0x8C, 0xE5, 0x4B, 0x46, 0x0D, 0xC1, 0x8E, 0xFE, 0xD6, 0xE7, 0x27, 0x75, 0x06, 0x8B,0x49, 0x00, 0xDC, 0x0F, 0x30, 0xA0, 0x9E, 0xFD, 0x09, 0x85, 0xF1, 0xC8, 0xAA, 0x75, 0xC1, 0x08,0x05, 0x79, 0x01, 0xE2, 0x97, 0xD8, 0xAF, 0x80, 0x38, 0x60, 0x0B, 0x71, 0x0E, 0x68, 0x53, 0x77,0x2F, 0x0F, 0x61, 0xF6, 0x1D, 0x8E, 0x8F, 0x5C, 0xB2, 0x3D, 0x21, 0x74, 0x40, 0x4B, 0xB5, 0x06,0x6E, 0xAB, 0x7A, 0xBD, 0x8B, 0xA9, 0x7E, 0x32, 0x8F, 0x6E, 0x06, 0x24, 0xD9, 0x29, 0xA4, 0xA5,0xBE, 0x26, 0x23, 0xFD, 0xEE, 0xF1, 0x4C, 0x0F, 0x74, 0x5E, 0x58, 0xFB, 0x91, 0x74, 0xEF, 0x91,0x63, 0x6F, 0x6D, 0x2E, 0x61, 0x70, 0x70, 0x6C, 0x65, 0x2E, 0x53, 0x61, 0x66, 0x61, 0x72, 0x69 };//now decrypt the dataDATA_BLOB DataIn;DATA_BLOB DataOut;DATA_BLOB OptionalEntropy;DataIn.pbData = byteEncBuffer; //encrypted password dataDataIn.cbData = dwEncBufferSize; //encrypted password data sizeOptionalEntropy.pbData = (unsigned char*)&salt;OptionalEntropy.cbData = 144;if(CryptUnprotectData(&DataIn, 0, &OptionalEntropy, NULL, NULL,0, &DataOut) == FALSE ){printf("CryptUnprotectData failed = 0x%.8x", GetLastError());return FALSE;}//Decrypted data is in following format//Password Length [4 bytes] + Pass Data []BYTE *byteData = (BYTE *) DataOut.pbData;DWORD dwPassLen = byteData[0];memcpy(strPassword, &byteData[4], dwPassLen);strPassword[dwPassLen] = 0;printf("Decrypted Password %d - %s", dwPassLen, strPassword); Above program initializes the salt data and then passes it to CryptUnprotectData along with decoded password data to finally get the decrypted data. First 4 bytes of this decrypted data contains length of the ascii password and then follows the password in clear text !That is all it takes to successfully decrypt the Password from Safari store ! Quote