(パート2)Kerberos認証への攻撃をログ分析の観点で理解してみる

2024.02.28

前回、Kerberos認証のセキュリティとして、SIEM製品の一つである Splunk を使って検知する方法について調べてみました。
前回に引き続き、Kerberos認証の代表的な攻撃パターンについてSplunkのブログ記事を基にさらに調べてみました。

前回紹介した攻撃パターンは以下になります。

  • Pass-the-Hash
  • Overpass-the-Hash
  • Pass-the-Ticket
  • Golden Tickets
  • Silver Tickets

今回は、以下の攻撃パターンについて見ていきます。

  • User Enumeration(ユーザー名列挙攻撃)
  • 無制限のKerberos委任の悪用
  • 制約付きKerberos委任の悪用
  • AS-REP Roasting
  • Kerberoasting

前回ブログ(参考):

Kerberos認証の仕組み

Kerberos認証への攻撃について理解するには、Kerberos認証の仕組みを理解しておく必要があります。
前回の記事で認証の仕組みをまとめていますので、確認しておきます。

User Enumeration(ユーザー名列挙攻撃)

User Enumerationとは、一般的にそのシステムにおいて特定のユーザー名が存在するかどうかを確認する攻撃になります。(実在することを確認した後、ブルートフォース(総当たり攻撃)などで認証情報を特定します。)
Kerberos認証においても、攻撃者はまずユーザー名の探索から行います。
攻撃者はよくありそうなユーザー名のリストを使って、しらみつぶしにそれらのユーザーのTGTを要求し、実在するユーザーを探します。
KDCは、実在するユーザーでパスワードから生成される事前認証を持たないTGT要求があった場合に、「KRB5KDC_ERR_PREAUTH_REQUIRED」という事前認証を要求するためのイベントを返します。
そのイベントが返ってきたユーザーは実在すると判断ができるため、攻撃者はその後の攻撃の情報として活用します。

SIEM製品で検知・分析するにはどうするか

Splunkのこちらの検知例について見ていきます。

https://research.splunk.com/endpoint/d82d4af4-a0bd-11ec-9445-3e22fbd008af/

KDCサーバーはTGTの要求を受けた時に、Windowsセキュリティイベントログのイベント ID4768 で記録します。
さらに事前認証が送られてこないTGT要求を受けた時、0x6 のエラーコードが記録されるのでこれらの条件にマッチするログを抽出します。
また、アカウント名の最後が「$」で終わるものを除外しています。これらのアカウントはコンピュータアカウントになります。
コンピュータアカウントに対するTGT要求のケースを除外しているようです。
(公式そうなドキュメントで自分では見つけられなかったのですが、コンピュータアカウントはコンピュータがドメインに参加する時に120文字のパスワードが自動生成されるようです。120文字長のパスワードから算出されるハッシュ値をクラッキングすることは現在のコンピュータでは不可能なようなので除外していると思われます。)
ただ当然、正当なアクセスの中にも不意にユーザー名を間違えて入力してしまう場合もあるため、False Positiveの検知を減らす工夫も必要です。
このサーチでは、標準偏差を使い、通常のイベント発生数とは異なる(外れ値)検出が行えるようになっています。

[分析するログ]
Windowsイベントログ(セキュリティログ)

[Splunkでのサーチ文]

`wineventlog_security` EventCode=4768 Result_Code=0x6 Account_Name!="*$"
| bucket span=2m _time
| stats dc(Account_Name) AS unique_accounts values(Account_Name) as tried_accounts by _time, Client_Address
| eventstats avg(unique_accounts) as comp_avg , stdev(unique_accounts) as comp_std by Client_Address
| eval upperBound=(comp_avg+comp_std*3)
| eval isOutlier=if(unique_accounts > 10 and unique_accounts >= upperBound, 1, 0)
| search isOutlier=1
| `kerberos_user_enumeration_filter`

バックスラッシュ部分はSplunkでいうマクロ関数になっていて、Settings > Advance search > Search macro で設定ができます。
設定する定義はこちらにもあるので、これを使って登録することも可能です。

無制限のKerberos委任の悪用

こちらは、標準機能の一つであるKerberos委任の仕組みを悪用した攻撃となります。

まずそもそもKerberos委任とは何か見ていきたいと思います。
よくある使われ方の例として、Webシステム(Windows環境)で(IIS -> MSSQL)のような2層構造における認証です。
このような認証構成を「ダブルホップ」と呼んだりするそうです。
(User -> IIS -> MSSQL)のアクセス時に、本来はUserのアクセス権限に基づいてSQLデータベースへアクセスしたいのですが、実質MSSQLからはIISがアクセスするので、通常のKerberosの認証シーケンスだと、IISの権限に基づくアクセスとなってしまいます。

そこで以下のように認証を委任することで、Userのアクセス権限に基づいたSQLデータベースへのアクセスを実現することができます。

User -- (認証) --> IIS --> (ユーザーの代わりに認証) --> MSSQL

またKerberos委任は以下の3種類あり、それぞれ若干動作や仕組みが異なります。

  • 無制限の委任
  • 制約付き委任
  • リソースベースの制約付き委任

無制限の委任の設定がされていた場合、特別な認証シーケンスになります。
まず、無制限の委任設定の方法です。
今回例として、IISのコンピュータアカウントに無制限の委任設定がされていると仮定します。

DC上の「Active Directoryユーザーとコンピューター」の設定のIISのコンピュータアカウントのプロパティを設定します。

次に無制限の委任設定におけるKerberos認証シーケンスを確認します。

==== シーケンスのステップ説明 =====

1. 入力したパスワードを元に生成したKeyでタイムスタンプを暗号し(事前認証)送信
2-1. KDCに保存されているUPNのKeyで事前認証を復号(復号可=UPNが正しいことを証明)
2-2. KDCはユーザー情報(PAC)などを含めTGTを作成
2-3. TGTの一部をKDCのサービスアカウント(KRBTGT)のKeyを使い暗号化、さらに一部をUPNのKeyで暗号化
3. TGTの一部をUPNのKeyで復号(復号可=KDCが正しいことを証明)
4. SPNへアクセスするためのTGSを要求
5-1. TGTを復号後、PACを検証、正しければTGSを作成
5-2. TGSはSPNのKeyで暗号化
※5-3. 無制限の委任設定がある場合、TGTをコピーしてTGSに埋め込む
6. アクセスを要求
7-1. TGSをSPNのKeyで復号(復号可=UPNが正しいことを証明)
※7-2. 無制限の委任設定がある場合、TGSに含まれているTGTはメモリに保存されシングルサインオンなどのために一定期間再利用される
※7-3. SPNへアクセスするためのTGSを要求
8-1. TGTを復号後、PACを検証、正しければTGSを作成
8-2. TGSはSPNのKeyで暗号化
9. アクセスを要求
10. TGSをSPNのKeyで復号(復号可=UPNが正しいことを証明)

===============================

このように、今回の例でいうと、IISサーバーにUPNのTGTをキャッシュするようになり(※7-2のフェーズ)、IISサーバーが攻撃者に乗っ取られていた場合、権限の高いユーザー(UPN)からIISサーバーにホストされたサービスを利用するように誘い込むと、アクセスしてきたUPNのTGTを窃取されてしまいます。
TGTにはUPNのNTLMハッシュが含まれているため、Pass-the-Ticketsなどに悪用することが可能となります。
アクセスしてきたユーザーがドメイン管理者の権限を持っていれば、その権限を奪取することができてしまいます。

一般的に以下のような手順で攻撃者は権限の昇格を行っていきます。

  1. 無制限の委任設定になっているコンピュータリソースを探索し発見
  2. そのコンピュータへの侵入を試みる
  3. 無制限の委任設定となっているコンピュータのサービスへ、DCアドミンアカウントなどの高い権限を持つリソースからアクセスさせるよう、ソーシャルエンジニアリングを試みる
  4. アクセスさせることができれば、Kerberos委任によりTGTが失効するまでの時間、アドミン権限を偽ってサービスにアクセスすることができる

ソーシャルエンジニアリングの手段として、Print Spoolerサービスを利用してDCからのネットワークアクセスを誘導する手法を用いる事例があるようです。

参考: https://adsecurity.org/?p=4056

SIEM製品で検知・分析するにはどうするか

Splunkのこちらの検知例について見ていきます。

https://research.splunk.com/endpoint/fbf9e47f-e531-4fea-942d-5c95af7ed4d6/

ドメイン内で最も高い権限を取得できる可能性があるため、攻撃者は積極的に無制限の委任設定がされたアカウントがないか探索を行います(その後そのアカウントにアクセスしようとします)。

攻撃者はPowershell製のオープンソースの攻撃ツールである(PowerSploit)を無制限の委任のアカウント探索に利用します。
Powershellログからイベントの種別 Script Block Logging EventCode=4104Get-DomainComputer -UnconstrainedGet-NetComputer -Unconstrainedなどのコマンド実行結果を探します。

[分析するログ]
Windowsイベントログ(セキュリティログ)

[Splunkでのサーチ文]

`powershell` EventCode=4104 (Message = "*Get-DomainComputer*" OR Message = "*Get-NetComputer*") AND (Message = "*-Unconstrained*") 
| stats count min(_time) as firstTime max(_time) as lastTime by EventCode Message ComputerName User 
| `security_content_ctime(firstTime)` 
| `security_content_ctime(lastTime)` 
| `windows_powerview_unconstrained_delegation_discovery_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/c8640777-469f-4638-ab44-c34a3233ffac//

Microsoft正規のActive DirectoryのPowershellモジュールのコマンドを使って行われる探索行為を検出します。
Powershellログからイベントの種別 Script Block Logging EventCode=4104Get-ADComputer TrustedForDelegationのコマンド実行結果を探します。

[分析するログ]
Windowsイベントログ(Powershell)
※PowershellのScript Block Loggingの有効化が必要なのでこちらなどで有効化の設定をしておく必要があります。

[Splunkでのサーチ文]

`powershell` EventCode=4104 (Message = "*Get-ADComputer*" AND Message = "*TrustedForDelegation*") 
| stats count min(_time) as firstTime max(_time) as lastTime by EventCode Message ComputerName User 
| `security_content_ctime(firstTime)` 
| `security_content_ctime(lastTime)` 
| `windows_get_adcomputer_unconstrained_delegation_discovery_filter`

その他の軽減処置や予防対策

無制限のKerberos委任を悪用した攻撃を受けないために予防措置を講じることも大切です。
以下のような対策を検討してください。

制約付き委任の悪用

次に制約付き委任はどういう仕組なのかを見ていきます。
制約付き委任では、委任するアカウントと委任を許可するサービスを特定することで権限を引き継ぐ範囲を限定します。
サービスの指定はSPN形式である必要があります。
委任するアカウントのプロパティの委任設定でSPNを指定します。

例として、(User -> IIS -> MSSQL)の構成でIISのサービスアカウントに制約付き委任(MSSQLのSPNへの)がされていると仮定します。

また、無制限の委任とは異なり、TGTの引き渡しは行わず、違う仕組みで委任を行います。
シーケンス図としては、無制限の委任と同じものを再掲していますが、ステップが若干異なります。

==== シーケンスのステップ説明 =====

1. 入力したパスワードを元に生成したKeyでタイムスタンプを暗号し(事前認証)送信
2-1. KDCに保存されているUPNのKeyで事前認証を復号(復号可=UPNが正しいことを証明)
2-2. KDCはユーザー情報(PAC)などを含めTGTを作成
2-3. TGTの一部をKDCのサービスアカウント(KRBTGT)のKeyを使い暗号化、さらに一部をUPNのKeyで暗号化
3. TGTの一部をUPNのKeyで復号(復号可=KDCが正しいことを証明)
4. SPNへアクセスするためのTGSを要求
5-1. TGTを復号後、PACを検証、正しければTGSを作成
5-2. TGSはSPNのKeyで暗号化
6. アクセスを要求
7-1. TGSをSPNのKeyで復号(復号可=UPNが正しいことを証明)
※7-2. 制約付き委任の設定がある場合、UPNから受け取ったTGSを送信
8-1. 「msDS-AllowedToActOnBehalfOfOtherIdentity」の属性をチェックして、委任が許可されているサービス(SPN)への要求であればTGSを生成
8-2. TGSはSPNのKeyで暗号化
9. アクセスを要求
10. TGSをSPNのKeyで復号(復号可=UPNが正しいことを証明)

===============================

このように、例でいうと、IISサーバーはTGTを受け取るのではなく、属性値から判断されSQLサーバーにアクセスするためのTGSを受け取ることで、許可されたサービスのみユーザーの権限でアクセスすることができます。

SIEM製品で検知・分析するにはどうするか

Splunkのこちらの検知例について見ていきます。

https://research.splunk.com/endpoint/86dc8176-6e6c-42d6-9684-5444c6557ab3/

攻撃者はPowershell製のオープンソースの攻撃ツールである(PowerSploit)を制限付き委任のアカウント探索に利用します。
Powershellログからイベントの種別 Script Block Logging EventCode=4104Get-DomainComputer -TrustedToAuthGet-NetComputer -TrustedToAuthなどのコマンド実行結果を探します。

[分析するログ]
Windowsイベントログ(Powershell)

[Splunkでのサーチ文]

`powershell` EventCode=4104 (Message = "*Get-DomainComputer*" OR Message = "*Get-NetComputer*") AND (Message = "*-TrustedToAuth*") 
| stats count min(_time) as firstTime max(_time) as lastTime by EventCode Message ComputerName User 
| `security_content_ctime(firstTime)` 
| `security_content_ctime(lastTime)` 
| `windows_powerview_constrained_delegation_discovery_filter`

AS-REP Roasting

Kerberos認証では、最初の認証プロセスとして、KDCへTGTを要求する時にアカウントのパスワードとタイムスタンプから生成される事前認証を送信します。
それをもとにKDCはアカウントの認証を行います。
ただし、アカウントの設定で、この事前認証がない場合においてもTGTを発行可能にする設定が存在しています。
この設定が有効化されていると、認証なしにTGTを入手することができるので、TGTの悪用や、TGTをオフラインでブルートフォースアタックすることで平文パスワードを復元が可能となります。

SIEM製品で検知・分析するにはどうするか

Splunkのこちらの検知例について見ていきます。

https://research.splunk.com/endpoint/114c6bfe-9406-11ec-bcce-acde48001122/

事前認証が無効化されているドメインアカウントを探索するためのコマンドが実行されたことを検出します。
攻撃者はPowershellのActive Directoryの管理ツールモジュールであるGet-ADUserを使って、事前認証が無効化されているドメインアカウントを探索する列挙攻撃を行います。
Powershellログからイベントの種別 Script Block Logging EventCode=4104Get-ADUser、「DoesNotRequirePreAuth」(事前認証なし)のプロパティであるユーザーの探索が行われたログ出力を検知します。

[分析するログ]
Windowsイベントログ(Powershell)

[Splunkでのサーチ文]

 `powershell` EventCode=4104 (ScriptBlockText = "*Get-ADUser*" AND ScriptBlockText="*4194304*") 
| stats count min(_time)  as firstTime max(_time) as lastTime by Opcode Computer UserID EventCode ScriptBlockText 
| rename Computer as dest 
| `security_content_ctime(firstTime)` 
| `disabled_kerberos_pre_authentication_discovery_with_get_aduser_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/b0b34e2c-90de-11ec-baeb-acde48001122/

同じく事前認証が無効化されているドメインアカウントを探索するためのコマンドが実行されたことを検出します。
攻撃者はPowershell製のオープンソースの攻撃ツールである(PowerSploit)を、事前認証が無効化されているドメインアカウント探索に利用します。
Powershellログからイベントの種別 Script Block Logging EventCode=4104Get-DomainComputer -PreauthNotRequiredのコマンド実行結果を探します。

[分析するログ]
Windowsイベントログ(Powershell)

[Splunkでのサーチ文]

`powershell` EventCode=4104 (ScriptBlockText = "*Get-DomainUser*" AND ScriptBlockText="*PreauthNotRequired*") 
| stats count min(_time)  as firstTime max(_time) as lastTime by Opcode Computer UserID EventCode ScriptBlockText 
| rename Computer as dest 
| `security_content_ctime(firstTime)` 
| `disabled_kerberos_pre_authentication_discovery_with_powerview_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/0cb847ee-9423-11ec-b2df-acde48001122/

攻撃者はバックドア設置や権限の昇格のために、ユーザーアカウントの事前認証を無効化することを試みます。
セキュリティイベントログからユーザーアカウントの事前認証を無効化するイベントが発生していないかを監視します。

[分析するログ]
Windowsイベントログ(セキュリティログ)

[Splunkでのサーチ文]

 `wineventlog_security` EventCode=4738 MSADChangedAttributes="*Don't Require Preauth' - Enabled*" 
|rename Account_Name as user 
| table EventCode, user, dest, Security_ID, MSADChangedAttributes 
| `kerberos_pre_authentication_flag_disabled_in_useraccountcontrol_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/59b51620-94c9-11ec-b3d5-acde48001122/

同じく、攻撃者はPowershellのActive Directoryの管理ツールモジュールであるSet-ADAccountControlを使って、特定のユーザーアカウントの事前認証を無効化を試みます。
Powershellのログからイベントの種別 Script Block Logging EventCode=4104Set-ADAccountControl DoesNotRequirePreAuth:$trueのコマンド実行結果を探します。

[分析するログ]
Windowsイベントログ(Powershell)

[Splunkでのサーチ文]

 `wineventlog_security` EventCode=4738 MSADChangedAttributes="*Don't Require Preauth' - Enabled*" 
|rename Account_Name as user 
| table EventCode, user, dest, Security_ID, MSADChangedAttributes 
| `kerberos_pre_authentication_flag_disabled_in_useraccountcontrol_filter`

Kerberoasting

Kerberoastingは、TGSを取得してTGSに含まれているSPNのセッションキーをオフラインブルートフォースすることによって平文パスワードに復元する攻撃です。
Kerberoastingは最終的なパスワードを得るまでに以下のような流れで攻撃を行います。

  1. 攻撃者はドメイン内のいずれかのローカルアカウントまたはドメインアカウントを乗っ取ります
  2. SPN(サービスプリンシパル名)に対応づけられたアカウントの探索を行います
  3. 乗っ取ったアカウントの権限でTGTを取得し、探索したSPNに対応づけられたアカウントのTGSをKDCに要求します
  4. KDCはTGSを渡します(乗っ取ったアカウントがSPNへの権限を持っているいないに関わらずTGSは渡されます。Kerberos認証シーケンス⑤)
  5. 攻撃者はTGSをオフラインまたは遠隔のサーバーにTGSを保存し、攻撃ツールを使ってブルートフォースによって、セッションキーから平文パスワードの復元を試みます(TGSのセッションキーの復元に成功するとSPNのアカウントのパスワードが手に入ります)

Kerberoastingは、権限昇格や水平移動を行う上で効率的かつ高確率で成功する攻撃の一つとして攻撃者によって頻繁に行われているようです。
その理由には、

  • SPNに対応付けられたアカウントはサービスアカウントの場合が多く、またサービスアカウントの多くは高い権限を付与されているケースが多い
  • サービスアカウントは同じパスワードで運用されてしまっているケースがあり、Kerberoastingで平文パスワードを復元された場合、それらのアカウント全てを一度に乗っ取ることができる
  • サービスアカウントは、10〜12文字程度のポリシーで設定された最小要件で設定されていることが多い
  • ブルートフォースはオフラインや遠隔のサーバーで行うことができるため、パスワードロックやロギングなどのセキュリティ対策から逃れながら侵害を続けることができる

SIEM製品で検知・分析するにはどうするか

Splunkのこちらの検知例について見ていきます。

https://research.splunk.com/endpoint/5cc67381-44fa-4111-8a37-7a230943f027/

攻撃者はRC4の暗号アルゴリズムのTGSを要求・取得して、パスワードクラッキングを試みます。
Kerberosの暗号アルゴリズムは現代のOSでは通常AESをデフォルトで選択するようになっていますが、下位互換のためRC4要求にも応答するようになっています。
RC4暗号化の脆弱性をついて解読し、セッションキーのブルートフォースアタックを実現可能にします。
Kerberoastingに利用される攻撃ツールが用いるTicket_OptionsのパターンのRC4暗号アルゴリズムのTGS要求イベントを監視します。

[分析するログ]
Windowsイベントログ(セキュリティログ)

[Splunkでのサーチ文]

`wineventlog_security` EventCode=4769 Service_Name!="*$" (Ticket_Options=0x40810000 OR Ticket_Options=0x40800000 OR Ticket_Options=0x40810010) Ticket_Encryption_Type=0x17 
| stats count min(_time) as firstTime max(_time) as lastTime by dest, service, service_id, Ticket_Encryption_Type, Ticket_Options 
| `security_content_ctime(lastTime)` 
| `security_content_ctime(firstTime)` 
| `kerberoasting_spn_request_with_rc4_encryption_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/13243068-2d38-11ec-8908-acde48001122/

攻撃者は、Kerberoasting攻撃の初期段階でSPNに対応づけられたアカウントを探索します。
Powershellのログからイベントの種別 Script Block Logging EventCode=4104のKerberosRequestorSecurityTokenのClassの呼び出しイベントを監視します。

[分析するログ]
Windowsイベントログ(Powershell)

[Splunkでのサーチ文]

`powershell` EventCode=4104 ScriptBlockText="*KerberosRequestorSecurityToken*" 
| stats count min(_time) as firstTime max(_time) as lastTime by ScriptBlockText Opcode Computer UserID EventCode 
| rename Computer as dest 
| rename UserID as user 
| `security_content_ctime(firstTime)` 
| `security_content_ctime(lastTime)` 
| `serviceprincipalnames_discovery_with_powershell_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/ae8b3efc-2d2e-11ec-8b57-acde48001122/

同じく、攻撃者はsetspn.exeを使って、SPNに対応づけられたアカウントを探索します。

[分析するログ]
EPP / EDR 製品ログ

[Splunkでのサーチ文]

| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where `process_setspn` (Processes.process="*-t*" AND Processes.process="*-f*") OR (Processes.process="*-q*" AND Processes.process="**/**") OR (Processes.process="*-q*") OR (Processes.process="*-s*") by Processes.dest Processes.user Processes.parent_process_name Processes.process_name Processes.original_file_name Processes.process Processes.process_id Processes.parent_process_id 
| `drop_dm_object_name(Processes)` 
| `security_content_ctime(firstTime)` 
| `security_content_ctime(lastTime)`
| `serviceprincipalnames_discovery_with_setspn_filter`

さらにSplunkのこちらの検知例も見ていきます。

https://research.splunk.com/endpoint/eb3e6702-8936-11ec-98fe-acde48001122/

Kerberoastingは、SPNに対応づけられたアカウントを特定できたら、次にパスワードクラッキングの対象となるTGSに含まれるNTLMハッシュを要求します。
通常と異なるRC4アルゴリズムのTGS要求を検知し、Kerberoastingに関連したイベントを特定します。

[分析するログ]
Windowsイベントログ(セキュリティログ)

[Splunkでのサーチ文]

`wineventlog_security` EventCode=4769 Service_Name!="*$" Ticket_Encryption_Type=0x17 
| bucket span=2m _time 
| stats dc(Service_Name) AS unique_services values(Service_Name) as requested_services by _time, Client_Address 
| eventstats avg(unique_services) as comp_avg , stdev(unique_services) as comp_std by Client_Address 
| eval upperBound=(comp_avg+comp_std*3) 
| eval isOutlier=if(unique_services > 2 and unique_services >= upperBound, 1, 0) 
| search isOutlier=1 
| `unusual_number_of_kerberos_service_tickets_requested_filter`

その他の軽減処置や予防対策

Kerberostingに対する予防策を講じることも大切です。
以下のような対策を検討してください。

まとめ

2回にわたって、Kerberos認証への攻撃とSplunkを使った検知方法について調べてみました。
Windows Active Directory環境で資産を管理されている場合に、インシデントレスポンスなどのセキュリティを検討されている場合、Kerberos認証への攻撃に関する理解と対策は必須です。
本記事がどなたかの一助になれば幸いです。