Kerberos
Kerberos では、クライアントが KDC から TGT とサービスチケットを順に受け取り、 そのチケットでサービスに認証します。このページは、Impacket がその交換を どう組み立て、どの鍵で各メッセージを処理するかをコードから追います。 AD での認証全体と SPN の扱いはKerberos 認証の解説を参照してください。
impacket/krb5/ は RFC 4120 に [MS-KILE] / [MS-PAC] / [MS-SFU] を足した
クライアント実装です。ASN.1 は pyasn1、暗号は RFC 3961/3962/4757 です。
| モジュール | 責務 |
|---|---|
constants.py | メッセージ番号、PA-DATA、KDC option、enctype |
asn1.py | AS/TGS/AP、PA-DATA、KRB-CRED、S4U、dMSA |
types.py | Principal、Ticket、KerberosTime |
crypto.py | string-to-key、encrypt/decrypt、checksum、Key |
kerberosv5.py | getKerberosTGT / getKerberosTGS / GSS Type1/Type3 |
pac.py | PAC buffer と sign_pac |
ccache.py | MIT ccache と kirbi (KRB-CRED) |
gssapi.py | AP-REQ checksum、WRAP/MIC |
keytab.py | MIT keytab |
kpasswd.py | RFC 3244、TCP 464 |
関連コマンド: getTGT、getST、 GetUserSPNs、GetNPUsers、 ticketer、describeTicket
交換の全体像
Section titled “交換の全体像”sequenceDiagram
participant C as Client
participant K as KDC :88/tcp
participant S as Service
C->>K: AS-REQ (PA_PAC_REQUEST)
K-->>C: KDC_ERR_PREAUTH_REQUIRED + ETYPE_INFO2
C->>K: AS-REQ (PA_ENC_TIMESTAMP usage 1)
K-->>C: AS-REP (enc-part usage 3) = TGT + TGS session key
C->>K: TGS-REQ (PA_TGS_REQ AP-REQ usage 7)
K-->>C: TGS-REP (enc-part usage 8) = ST + app session key
C->>S: AP-REQ in SPNEGO (authenticator usage 11)
S-->>C: optional AP-REP (usage 12)
KDC 通信は sendReceive() です。TCP、先頭 4 byte が big-endian 長です。
KRB_ERROR のうち KDC_ERR_PREAUTH_REQUIRED (25) だけを通常応答として返し、
それ以外は KerberosError になります。
AS-REQ / AS-REP — getKerberosTGT
Section titled “AS-REQ / AS-REP — getKerberosTGT”getKerberosTGT(clientName, password, domain, lmhash, nthash, aesKey='', kdcHost=None, requestPAC=True, serverName=None, kerberoast_no_preauth=False, timeout=None)→ (tgt_bytes, cipher, client_key, sessionKey)最初の AS-REQ は未認証で、PA_PAC_REQUEST だけを付けます。
sname は既定 krbtgt/DOMAIN。serverName を渡すと AS-REQ で別 SPN を
要求できます (kpasswd の kadmin/changepw、no-preauth roast)。
etype 選択:
| 入力 | 最初に出す etype |
|---|---|
| NT hash あり | RC4 (23) のみ |
| AES key 32 byte | AES256 (18) |
| AES key 16 byte | AES128 (17) |
| password のみ | AES256。KDC_ERR_ETYPE_NOSUPP なら RC4 |
KDC が METHOD_DATA を返すと PA_ETYPE_INFO2 (なければ PA_ETYPE_INFO)
から etype → salt を取り、cipher.string_to_key(password, salt) で
長期鍵を作ります。2 回目の AS-REQ に PA_ENC_TIMESTAMP (key usage 1) を
付けます。
UF_DONT_REQUIRE_PREAUTH のとき、最初の応答がそのまま AS-REP になります。
enc-part は依然としてクライアント長期鍵 (usage 3) です。復号に失敗し
kerberoast_no_preauth=True なら、session key 無しで生 AS-REP を返します
(AS-REP roasting)。
password だけの経路で 2 回目が KDC_ERR_ETYPE_NOSUPP なら、LM/NT hash を
計算して再帰します (RC4 fallback)。
TGS-REQ / TGS-REP — getKerberosTGS
Section titled “TGS-REQ / TGS-REP — getKerberosTGS”getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey, renew=False, etypes=None, timeout=None)tgt は AS-REP でも TGS-REP でも構いません (referral 追従)。
- TGT を入れた AP-REQ。Authenticator は TGS session key、usage 7
- それを
PA_TGS_REQとして TGS-REQ に載せる - option:
forwardable | renewable | renewable_ok | canonicalize(renew=Trueならrenewも) - etype: 既定では RC4、AES256、AES128、DES3、DES-MD5。
etypesを渡すと提示順と種類を指定できる - TGS-REP
enc-partを usage 8 で復号 → 新しい session key - 返った
snameが要求と違えば referral として再帰
S4U と U2U はこの関数にはありません。 examples/getST.py と
getPac.py / ticketer.py が ASN.1 を直接組みます。
暗号と salt
Section titled “暗号と salt”crypto.py の公開 API: Key、string_to_key、encrypt、decrypt、
make_checksum、verify_checksum、cf2、generate_kerberos_keys。
| クラス | etype | 鍵長 | string-to-key |
|---|---|---|---|
_DESCBC | 3 | 8 | MIT DES + salt |
_DES3CBC | 16 | 24 | n-fold(password+salt) |
_AES128CTS | 17 | 16 | PBKDF2-HMAC-SHA1、既定 4096 回、derive(..., b'kerberos') |
_AES256CTS | 18 | 32 | 同上、32 byte seed |
_RC4 | 23 | 16 | salt 無視。MD4(UTF-16LE(password)) = NT hash |
AES/DES3 は RFC 3961 簡略プロファイルです。Ke は usage || 0xAA、
Ki は usage || 0x55。暗号文は confounder + HMAC-SHA1 切り詰め 12 byte。
RC4 (RFC 4757) は usage 3→8、23→13 に読み替えます。
よく使う key usage:
| Usage | 場所 |
|---|---|
| 1 | AS-REQ PA_ENC_TIMESTAMP |
| 2 | Ticket enc-part (サービス長期鍵)。getST の force-forwardable |
| 3 | AS-REP enc-part |
| 7 | TGS-REQ Authenticator |
| 8 | TGS-REP enc-part |
| 11 | AP-REQ Authenticator |
| 12 | AP-REP enc-part |
| 13 | KRB-PRIV (kpasswd) |
| 17 | S4U PA_FOR_USER HMAC-MD5 |
AD の典型 salt: ユーザは DOMAIN.COMuser、コンピュータは
DOMAIN.COMhost + 小文字 sam。getST -force-forwardable が password から
AES を出すときは DOMAIN.upper()+user をハードコードします。コンピュータ
アカウントでは一致しないことがあります。
cf2() (FAST) は実装されていますが getKerberosTGT には繋がっていません。
PAC は ticket authorization-data の AD_IF_RELEVANT / AD_WIN2K_PAC です。
構造は NDR と Structure の混在です。
| 定数 | 値 | 内容 |
|---|---|---|
PAC_LOGON_INFO | 1 | KERB_VALIDATION_INFO (RID、group、UAC、ExtraSids) |
PAC_CREDENTIALS_INFO | 2 | 資格情報 |
PAC_SERVER_CHECKSUM | 6 | サービス鍵による署名 |
PAC_PRIVSVR_CHECKSUM | 7 | KDC 鍵による署名 (server checksum の上) |
PAC_CLIENT_INFO_TYPE | 10 | クライアント名と時刻 |
PAC_DELEGATION_INFO | 11 | S4U2proxy 経由サービス |
PAC_UPN_DNS_INFO | 12 | UPN / DNS。S flag で SAM+SID |
PAC_CLIENT_CLAIMS_INFO_TYPE | 13 | クライアントの claims |
PAC_DEVICE_INFO_TYPE | 14 | デバイス情報 |
PAC_DEVICE_CLAIMS_INFO_TYPE | 15 | デバイスの claims |
PAC_ATTRIBUTES_INFO | 17 | PAC 属性 |
PAC_REQUESTOR_INFO | 18 | 要求者 SID |
sign_pac() は両方の checksum をゼロ埋めしてからシリアライズし、
server checksum を PAC 全体、KDC checksum を server 署名だけに取ります。
checksum type は KERB_NON_KERB_CKSUM_SALT (17)。AES か HMAC-MD5 かは
SignatureType または AES 鍵長から決めます。
S4U2self / S4U2proxy / U2U
Section titled “S4U2self / S4U2proxy / U2U”実装の中心は GETST.doS4U です。
S4U2self
- 呼び出し元 TGT の
PA_TGS_REQ - 追加 PA-DATA:
- 既定:
PA_FOR_USER。S4UByteArray = LE32(NT_PRINCIPAL) || user || realm || 'Kerberos'を session key、usage 17、HMAC-MD5 で署名 -dmsa:PA_S4U_X509_USER。TGS-REP のencrypted_pa_dataにKERB_DMSA_KEY_PACKAGEが付くことがある
- 既定:
- sname は呼び出し元自身 (自分宛ての ticket)
-selfならここで止まる
U2U (-u2u): enc_tkt_in_skey を立て、呼び出し元 TGT を
additional-tickets に入れる。ticket enc-part が TGT session key で
暗号化されるため、サービス鍵無しで PAC を読める
(getPac)。
S4U2proxy
- option:
cname_in_addl_tkt | canonicalize | forwardable | renewable PA_PAC_OPTIONSにresource_based_constrained_delegationadditional-tickets= S4U2self (または-additional-ticket) の ST- sname = 最終 SPN
-force-forwardable は S4U2self ticket をサービス長期鍵 (usage 2) で復号し、
forwardable を立てて再暗号化します。サービス鍵が本当に手元にあることが
前提です。
ccache と kirbi
Section titled “ccache と kirbi”| 形式 | 実体 |
|---|---|
| ccache | MIT FILE:。version 3/4 (0x0503 / 0x0504)。v1/v2 は未実装 |
| kirbi | Mimikatz の KRB-CRED (msg-type 22)。enc-part.etype=0 で |
EncKrbCredPart を平文格納 |
CCache.fromTGT / fromTGS が enc-part を復号して credential を埋めます。
Credential.toTGT / toTGS はダミー enc-part 付きの偽 AS-REP/TGS-REP を
作り、getKerberosTGS が ticket + session key を再利用できるようにします。
CCache.parseFile(domain, user, target) は KRB5CCNAME を読み、
対象 SPN の TGS を優先、無ければ krbtgt/DOMAIN@DOMAIN を返します。
相互変換は ticketConverter。 Impacket が保持するフィールド範囲では second ticket / address は使いません。
GSS-API
Section titled “GSS-API”getKerberosType1 は host/<target> の TGS を取り、SPNEGO NegTokenInit に
AP-REQ を載せます。Authenticator checksum type は 0x8003
(CheckSumField: Lgth=16、Bnd[16]、Flags)。
DCERPC では GSS_C_CONF|INTEG|SEQUENCE|REPLAY|MUTUAL|DCE_STYLE。
LDAP の LDAPS では Bnd に TLS CBT の MD5 を入れます。
WRAP: RC4 は RFC 4757 (TOK_ID 0x0102)、AES は RFC 4121 (0x0504、
RRC=28、usage 24/22)。LDAP signing は GSS_Wrap_LDAP で MechIndepToken
(OID 1.2.840.113554.1.2.2) に包みます。
発行済み ticket の改変と偽造
Section titled “発行済み ticket の改変と偽造”KDC から得た ticket と、手元の長期鍵で作る ticket は別経路です。
| 経路 | 必要な鍵 | 実装 |
|---|---|---|
| Golden | krbtgt の AES または NT hash | ticketer が PAC を組み立て sign_pac |
| Silver | 対象サービスの長期鍵 | 同上。sname をサービスに合わせる |
| Sapphire / U2U PAC | 呼び出し元 TGT session key | S4U2self + U2U で本物 PAC を取得し改変 |
| MS14-068 | 署名検証の欠落 | goldenPac。改変 PAC を含む TGS |
| Key List | RODC krbtgt_XXXXX の AES | keylistattack、KERB_KEY_LIST_REQ (PA 161) |
ticketer は KERB_VALIDATION_INFO の RID、group、ExtraSids (SIDHistory)、
UAC を埋め、server/KDC checksum を対応する鍵で署名します。
raiseChild は child の krbtgt から forest 側の信頼経路を辿り、
SIDHistory を含む ticket を作ります。
これらは getKerberosTGT の出力を「編集する」処理ではありません。
PAC の buffer 順、checksum の入れ子、ticket flag、crealm/sname が
サービス側の検証と一致する必要があります。
kpasswd / keytab
Section titled “kpasswd / keytab”- kpasswd: TCP 464、protocol
0xFF80、TGT SPNkadmin/changepw。 AP-REQ (usage 11、乱数 subkey) +KRB_PRIV(usage 13) にChangePasswdData。changePasswordは本人変更、setPasswordは管理者 reset。 - keytab: MIT v0x0502。
getKeyは AES256 → AES128 → RC4 の順。loadKeysFromKeytabは CLI の-aesKeyまたは-hashesへ展開します。
変更時の確認
Section titled “変更時の確認”- etype リストと fallback 順を変えると、後続 TGS が落ちることがある
- PAC 署名は server → KDC の順。片方だけ直さない
- S4U の PA-DATA と
additional-ticketsをgetKerberosTGSに無理に混ぜない - clock skew、salt 不一致、
KDC_ERR_ETYPE_NOSUPPを一般例外へ畳み込まない - 関連テスト:
tests/misc/test_ccache.py、test_krb5_crypto.py、test_krb5_gssapi.py

