Mac OSX のChromeのパスワードを取り出すツールを書いた。
takuya/chrome-storage · GitHub
なぜ書いたのか
OSX版Chromeが、Keychains.app に同期しなくなったので、インポートするために仕方なく書きました。
いままではKeychainを見ればパスワードを回収できたのですが、Opera・Safari・Firefox・Chromeがそれぞれ別管理になって、別々にアカウント同期でパスワードを持っていくのですが、どれが新しくてドレが古いか全くわからなくなりそうでした。
Chromeの管理からパスワード取り出せば良いのですが、chrome://settings/passwords
のパスワードチェックがめんどくさい。ちょっと視認性の悪いUIですよね。
いままではローカルKeychainにパスワードつくってiCloudに移動すればよかったのに・・・Windowsの悪夢に逆戻りだ・・・
Opera/chrome のクッキーとパスワードのデコード
Chromium のパスワードは $PROFILE_PATH/Login Data
のファイルに保存されています。ファイルはSqlite3のデータベースになっています。そのファイルの中身でパスワードは暗号化されて保存されています。
暗号化されたパスワードは、Keychain.app にあるsafe storage
に保存された文字列で復号化出来ます。
ダウンロード先
safe storage が幾つかある。
Opera(stable/beta) とChromeがそれぞれ使っています。
ここに保存されたパスフレーズでブラウザ中の暗号化データをデコード出来るようになっています。
暗号化・復号化処理も含めたブラウザのソースコードは公開されてるので、わたしたちはブラウザから平文でパスワードを得ることが可能になります。これからも安心して使える。ソース公開って素晴らしい
Firefoxはどうしてるんだろう・・・
パスワード・クッキーのデータベースの構造
パスワードとクッキーのデータベースは、次の通りのテーブル構造に格納されていました。
パスワードテーブル
CREATE TABLE "logins" ( origin_url VARCHAR NOT NULL , action_url VARCHAR , username_element VARCHAR , username_value VARCHAR , password_element VARCHAR , password_value BLOB , submit_element VARCHAR , signon_realm VARCHAR NOT NULL , ssl_valid INTEGER NOT NULL , preferred INTEGER NOT NULL , date_created INTEGER NOT NULL , blacklisted_by_user INTEGER NOT NULL , scheme INTEGER NOT NULL , password_type INTEGER , possible_usernames BLOB , times_used INTEGER , form_data BLOB , date_synced INTEGER , display_name VARCHAR , icon_url VARCHAR , federation_url VARCHAR , skip_zero_click INTEGER , generation_upload_status INTEGER , UNIQUE ( origin_url , username_element , username_value , password_element , signon_realm ) ) ;
クッキーテーブル
CREATE TABLE cookies ( creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY , host_key TEXT NOT NULL , name TEXT NOT NULL , value TEXT NOT NULL , path TEXT NOT NULL , expires_utc INTEGER NOT NULL , secure INTEGER NOT NULL , httponly INTEGER NOT NULL , last_access_utc INTEGER NOT NULL , has_expires INTEGER NOT NULL DEFAULT 1 , persistent INTEGER NOT NULL DEFAULT 1 , priority INTEGER NOT NULL DEFAULT 1 , encrypted_value BLOB DEFAULT '' , firstpartyonly INTEGER NOT NULL DEFAULT 0 ) ;
データベースからデータを取り出して、復号化
復号化はそんなに難しいものではなく、WEBを探したら色々出てきます。WindowsはWin32を使っていて、linux/osxはキーチェンに保存したパスフレーズとhmacを使ったOpensslを使っているようだ
次の例は、ruby で復号化を試みた箇所です。 引数 passの部分は、Keychainから拾ってきます。
def decrypt(encrypted_value, pass ) iter = 1003 key_len = 16 salt = "saltysalt" iv = " " * 16 return if encrypted_value.size < 3 key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len) cipher = OpenSSL::Cipher::AES.new(128,:CBC) cipher.decrypt cipher.iv = iv cipher.key = key data = encrypted_value data = data[3,data.size] return cipher.update(data) + cipher.final end
取り出したID/PASSはKeychainに
security コマンド
を使うことで、パスワードをKeychainに書き込むことが出来ます
security add-internet-password -a ユーザー名 -s サーバー -w パス -p 対象のフルURL -U
これで、しばらくは生き延びられそうです。
関連記事
ChromeのCookieをプログラムから使う - それマグで!
chrome のCookieを取り出す。(暗号化Cookieの複合化でデコード済テキストを取り出す) - それマグで!