Last active
July 10, 2016 14:24
-
-
Save kfriend/5272308 to your computer and use it in GitHub Desktop.
OS X Keychain dumping script written in PHP. Dumps keychains to JSON.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/php | |
<?php | |
/** | |
* OS X Keychain Dump to JSON | |
* | |
* Big thanks to Romeo for outlining the initial steps for this: | |
* http://romeotheriault.blogspot.com/2009/01/exporting-mac-os-x-keychain-access.html | |
* | |
* Notes: | |
* - Dump files will be stored in the cwd. | |
* - You'll need to hit "Allow" for every entry in a keychain during the dumping stage. | |
* - This script will dump only the current user's keychains. | |
* - This script has only been tested with OS X 10.7 (Lion) and PHP 5.3 and 5.4. | |
* | |
* Future to do: | |
* - Somehow work in Applescript to click "Allow" during the keychain dumping phase. | |
* | |
* @author Kevin Wood-Friend | |
*/ | |
// Backward compatibility for PHP < 5.4 | |
if (!defined('JSON_PRETTY_PRINT')) define('JSON_PRETTY_PRINT', 0); | |
// Get user's keychains | |
$keychains = explode("\n", `security list-keychains | grep \`whoami\``); | |
// Clean up entries | |
$keychains = array_map(function($keychain) { | |
return trim(trim($keychain), '"'); | |
}, $keychains); | |
// Filter out empty values | |
$keychains = array_filter($keychains); | |
foreach ($keychains as $keychain) | |
{ | |
$keychainName = pathinfo($keychain, PATHINFO_BASENAME); | |
$keychainPassword = prompt_silent("Enter password for {$keychainName}. Leave blank to skip: "); | |
if ($keychainPassword === '') | |
{ | |
puts("Skipping {$keychainName}"); | |
continue; | |
} | |
puts('Unlocking '.$keychainName); | |
// If incorrect password used, OS X will prompt for password | |
`security unlock-keychain -p {$keychainPassword} $keychain`; | |
unset($keychainPassword); | |
$saveTo = getcwd().'/'.pathinfo($keychainName, PATHINFO_FILENAME).'.json'; | |
puts("Dumping {$keychainName} to {$saveTo}"); | |
$export = `security dump-keychain -d {$keychain}`; | |
$parts = explode('keychain:', $export); | |
$passwords = array(); | |
foreach ($parts as $key => $part) | |
{ | |
if ($part === '') continue; | |
preg_match('/0x00000007 <blob>="(.*)"/', $part, $name); | |
preg_match('/"acct"<blob>="(.*)"/', $part, $username); | |
preg_match('/data:\s*"(.*)"/', $part, $password); | |
preg_match('/"svce"<blob>="(.*)"/', $part, $address); | |
$passwords[] = array( | |
'name' => isset($name[1]) ? $name[1] : null, | |
'username' => isset($username[1]) ? $username[1] : null, | |
'password' => isset($password[1]) ? $password[1] : null, | |
'location' => isset($address[1]) ? $address[1] : null, | |
); | |
} | |
file_put_contents($saveTo, json_encode($passwords, JSON_PRETTY_PRINT)); | |
} | |
/** | |
* Prompt silent | |
* | |
* Interactively prompts for input without echoing to the terminal. | |
* Requires a bash shell or Windows and won't work with | |
* safe_mode settings (Uses `shell_exec`) | |
* | |
* Source: http://www.sitepoint.com/interactive-cli-password-prompt-in-php/ | |
* Edits: Stripped unneeded Windows check | |
*/ | |
function prompt_silent($prompt = "Enter Password:") | |
{ | |
$command = "/usr/bin/env bash -c 'echo OK'"; | |
if (rtrim(shell_exec($command)) !== 'OK') { | |
trigger_error("Can't invoke bash"); | |
return; | |
} | |
$command = "/usr/bin/env bash -c 'read -s -p \"" | |
. addslashes($prompt) | |
. "\" mypassword && echo \$mypassword'"; | |
$password = rtrim(shell_exec($command)); | |
echo "\n"; | |
return $password; | |
} | |
function puts($string) | |
{ | |
echo $string.PHP_EOL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment