パスワードマネージャー

Program

パスワードをブラウザに保存するとセキュリティ的に危ない

近年最も警戒されているのが、

PCに侵入してブラウザの保存データを狙う「InfoStealer(インフォスティーラー)」と呼ばれるマルウェア

不審なファイルやソフトなどを通じてPCがウイルスに感染すると、このマルウェアがバックグラウンドで動き出す

ブラウザは利便性のために、保存されているパスワードを「ユーザーがログインするとき」に復号(もとの文章)する必要がある

マルウェアは、ブラウザが復号した瞬間あるいはOSのユーザー権限を使って暗号化されたデータベースファイルそのものと復号の鍵を丸ごと盗み、別の端末でパスワードをすべて暴いてしまう

USBで保存する意味

ブラウザに保存せずUSBに保存するメリットは、

USBをパソコンに刺さっていなければ、データがメモリ上に存在しないため、盗まれない

USBメモリのシリアル番号やハードウェアID(UUID)をアプリ側に登録し、そのUSBでなければ起動・復号できないようにする

パスワードの自動生成

最近、情報漏洩事件が多いので、使いまわししているパスワードを変えたいと思って、自動生成機能を実装することにした。

ウェブサイトによってパスワードの条件(大文字NG、記号NGなど)があるので、以下のオプションボタンを用意し、デフォルトはONにした

・ 大文字(A-Z)

・ 小文字(a-z)

・ 数字(0-9)

・ 記号(使える記号が限られているパターンもあるので、標準記号すべて使えるOR記号制限の選択肢を用意した)

・ 文字数制限:スライダー(4~64文字)と直接入力できる数値ボックス

USBを紛失しても他人にパスワードを読まれないように暗号化

・ アプリ初回起動時に、アプリがランダムで復号鍵(32バイトの暗号キーなど)を生成し、PCのOS標準の安全な領域(Windows Hello / Mac Keychain など)に保存する

・ 暗号化したパスワードデータをUSBに保存

・ アプリを起動すると、アプリがOSの安全な領域にアクセスし、保存されていた復号鍵をOSがアプリに渡すことで、暗号化されたパスワードが復号される(つまり、アプリに復号鍵のデータはない)

・ PCが壊れると復号鍵が取り出せなくなってパスワードが復号できなくなるので、この対策として、初回設定時に1回だけ「非常用リカバリーキー(長いランダム文字列)」を発行して紙にメモさせる(または印刷させる)。PCが壊れたときだけ、その紙のキーを入力して新しいPCに鍵を再構築する。非常用リカバリーキー自体が復号鍵になっているため、PCが壊れてもパスワードを復号できる

つまり、PCが壊れた時に、新しいパソコンでパスワードを復号するために、ユーザーが非常用リカバリーキーを入力するボタンもアプリに入れる必要がある → アプリ初回起動時に復号鍵を自動生成せず、「新しい復号鍵を作成」と「非常用リカバリーキーを入力」を選べるようにした

※ アプリ(プログラム)の中に直接復号鍵を埋め込むのは非常に危険といわれている

バックアップ機能(別のUSBにデータを複製)

・ カテゴリの入力欄の下に「別のUSBにパスワードデータをバックアップするボタン」をつけた

・ 別のUSBにバックアップすると「どのUSBにバックアップしただけの古いデータが入っていて、どのUSBに最新のデータが入っているのか」がわからなくなるので、バックアップされてまだデータが更新されていないものが表示されるときは、画面上部に「バックアップした履歴」が表示されるようにした

パスワードの使いまわしチェック

AIによって「個人情報は漏洩するもの」になったので、「破られることを前提とした防御術」を身に着ける必要がある。そのひとつとして「同じパスワードを使いまわさない」がある。

・ 「重複パスワードチェックボタン」を用意し、クリックすると「同じパスワードが〇件の場所で使用されています」という重複パスワードの警告表示が出て、重複している場所をリスト表示し、リストをクリックすると、その場所に飛べるようにする

・ パスワードでないものも入力する場合があるので、reuseチェックボックスをつけて、チェックが外れている場合は、「reuse check」ボタン(パスワード使いまわしチェックボタン)をクリックしたときの重複対象から外れるようにした

過去に情報漏洩事件で流出したパスワードかどうかをチェック

・ 世界で最も信頼されている流出データベース「Have I Been Pwned(HIBP)」が提供しているAPIを利用する

・ パスワード自体のチェックではなく、ドメイン(ウェブサイト)ごとのチェックをBreaches APIで行う。(完全無料でできる)

・ サイト名(AmazonやSBI証券など)で行うと精度が下がるらしいので、ドメイン名で我慢

・ 「過去1年間で情報漏洩したサービスや会社」も調べたくなったので、グローバル企業はHIBPで調べ、日本国内企業はHIBPだと弱いので、SecurityNEXTのRSSで調べることにした(初回はRSSを複数ページ読むため、少し時間がかかる)

USBメモリの書き込み中に、USBが急に抜かれた場合

USBメモリの書き込み中に、USBを抜くとdatファイルが壊れて、パスワード事読めなくなることがある

一時ファイルとしてvault.dat.bakなどの直前版を残すことで、datファイルが壊れても元に戻せるようにした

IDやパスワードの自動入力(ブラウザ拡張機能による)

・ 市販のパスワードマネージャーと同じ仕組み

・ ユーザーがログイン画面を開くと、Chrome拡張機能(Javascript)がページのDOM(HTML)を解析して、<input type=”password”>等を発見し、拡張機能が現在表示中のURLを取得し、WebSocketやNative Messagingという通信手段を使って、バックグラウンドで動いているTauri アプリ(Rust)にURLを送信する→Tauri側でURLに紐づいたパスワードとIDを取得し、拡張機能にその値を渡すと、拡張機能が受け取った値をJavascriptで各<input>要素に入力する

・ type=”email”, type=”text” autocomplete=”username”, type=”password”, nameやidやplaceholder属性にuser,login,email,idなどの文字列が含まれているか を見て、どこに入力すればいいのか判断する

・ USBを刺すだけでなく、パスワードマネージャーアプリを開いた状態でないと自動入力できない

・ アプリで発行されるトークンを拡張機能のポップアップに張り付けて接続テストすれば、トークンはchrome.storage.localに保存されるため、ブラウザを閉じたりパソコンを再起動しても残る。アプリ側のトークンもOSのセキュアストレージに保存されるため、一度ペアリングすれば毎回トークンを張りなおす必要はない。

・ Chrome拡張機能でBraveで成功したが、ほかのブラウザでの拡張機能も作る必要がある

【メリット】正確なURL判定と完全自動化が可能

【デメリット】

・ ブラウザごとの仕様差への対応が必要で少し大変

・ 拡張機能の仕様変更(Manifest V3への移行)が数年に一度行われるため、自動変更ができなくなる場合がある(レア)

・ ブラウザのセキュリティポリシーの強化が年に数愛行われるが、

・ アクセスするウェブサイトのデザインやログインフォームのHTML構造が勝手に変わることが原因で、拡張機能がフォームを見失い、自動入力できなくなることがある(パスワードマネージャーの拡張機能は、「input[type="password"] や name="email" などの要素を探して自動入力する」という仕組みが多い)(大手パスワードマネージャーは開発元が迅速にセレクタ(要素の指定方法)のパターンをアップデートして対応している)

※ ちなみに、ブラウザでパスワードを保存していても、時々自動入力されなくなるのは、Webサイト側のHTML構造が変更されたことが原因。大手サービスのログイン画面はセキュリティ対策のため、頻繁に裏側のプログラムやHTMLの書き方を変えている

IDやパスワードの自動入力(ブラウザ)の完全自動化

・ 現状はブラウザの右下にパスワードとユーザー名の候補が出て選択して自動入力する形だが、アプリ内で「このURLが来たらこのパスワードとユーザー名を自動入力する」というふうに紐づけておけば、完全な自動入力ができると思った

【クリックジャッキング・フィッシング対策】「ドメインの一部が一致している」という判定方法だと、github.com.attacker.comのような偽ドメインに引っかかってしまうので、サブドメインまで完全一致しないとダメ

・ Tauriアプリ側で「このサイトで全自動入力を許可する」というトグルボタンをつけておく

・ Tauriアプリ側で「パスワードを完全自動入力するためのサイトURL」を紐づけておく(ユーザーが冗長なURLを貼り付けてもアプリ側でドメインだけを抽出するようにする)

・ 自動入力するのは「パスワード、ユーザー名、ID、メールアドレス」の4つから選べるようにする(ゆくゆくはクレカ決済(カード番号、カード名義人、有効期限、セキュリティコード)、会員登録(姓名、ふりがな、郵便番号、住所、電話番号、生年月日、性別)も選べるようにしたい)

アプリ起動時のウィンドウサイズを変える

src-tauriフォルダのtauri.conf.jsonファイルを開いて、以下の部分を変えるだけ

{
  "app": {
    "windows": [
      {
        "title": "My Desktop App",
        "width": 1200,
        "height": 800,
        "resizable": true
      }
    ]
  }
}

拡張機能を他のブラウザでも作る

GoogleChromeやMicrosoft EdgeやBraveやVivaludi

Chromium系のエンジンなのでブラウザの拡張機能のページでChrome拡張機能フォルダをそのまま読み込ませるだけ

Firefox

Chromium系ではなくGeckoという独自エンジンだが、WebExtensionsAPI Manifest v3の規格をサポートしているため、微調整で動く

Safari

Safari Web Extensionという独自エンジン。全く別の拡張機能を作る必要がある。

生成AIに指示してつくらせた拡張機能フォルダを「Safariブラウザの拡張機能ページ」でそのまま読み込ませても動かない

自分のパソコンで使う場合は、

Cursorが生成した YourAppName.xcodeproj ファイルをダブルクリックして Xcode で開く。

左上の再生ボタン(Run)をクリック。

ビルドが成功するとアプリが起動し、自動的にSafariの内部に拡張機能が登録される。

あとはパターンAと同様に、Safariの 開発 ➔ 「未署名の拡張機能を許可」 にチェックを入れて有効化する。

しかし、他人のパソコンで使わせる場合は、実質、AppleDeveloper Program(年額100ドル)に登録するしかない

GmailやスマホSMSと連携してワンタイムパスワード(2段階認証用)をTauriアプリで取得し自動入力したい

調査中

MacbookでBraveで拡張機能のパッケージを読み込もうとすると以下のポップアップが出る

MacBookのログインパスワードを入力して「常に許可」をクリックすること

PassMangerは復号鍵をキーチェーン(画像の黒く塗りつぶした部分)に保存しているため、その鍵を読むためにmacOSが許可を求めてくる

付け加えなかった機能

× アプリを起動するときにマスターパスワードが必要にする(二要素認証)(マスターパスワードを忘れそう)

× 長期間変更していない古いパスワードがあるかチェックする機能(米国NISTや総務省による現在のセキュリティ基準では、パスワードの定期変更は不要と考えられている。なぜなら、定期的に変更すると推測しやすいパターンになったり、パスワードの使いまわしが増えるから)

× 非常リカバリーキーや復号鍵の総当たり攻撃(ブルートフォース攻撃)対策(非常リカバリーキーは256BITのランダム鍵であり、総当たりで当てるのは現実的に不可能なので、対策する必要はない、との回答だった)

補足:IDやパスワードの自動入力(ブラウザ)の不採用方法

ショートカットで検索ウィンドウを表示する

・ 1PasswordやBitwardenのデスクトップアプリ版が採用している方法

・ ユーザーが Ctrl + Shift + L を押すと、バックグラウンドで動くRust側がイベントを検知し、最前面画面中央に小さな検索ダイアログが表示され、「amazon」とタイプしてEnterすると、直前にマウスカーソルが当たっていた場所に対して、Tauriが該当するパスワードを自動打ち込みしてくれる

【メリット】OSの高度な権限取得が不要、ブラウザの拡張機能を開発する必要がない

【デメリット】使い勝手が悪すぎ

アクティブウィンドウのタイトルから推測する

・ RustからOSのネイティブAPI(WindowsならGetForegroundWindow)を叩き、現在アクティブになっているアプリの「ウィンドウタイトル」を取得し、タイトルが「Amazon.co.jp – Chrome」だったら、データベースからAmazonに合致する候補を自動抽出する。

【デメリット】ブラウザのURLが取れるわけではないので、精度が悪

BACK