(多くの) OS 依存関係のないマネージド コードのみで構築された完全な Kerberos ライブラリ。
このプロジェクトは .NET Foundation によってサポートされています。
このライブラリは Microsoft によって正式にサポートされていません。 Oracle の ODP.NET 経由で使用している場合、Kerberos.NET は Oracle サポート経由でのみサポートされます。問題が Kerberos.NET にあることがわかっている場合でも、Oracle サポートに連絡する必要があります。 Kerberos.NET に問題がある場合、Oracle サポートは Microsoft と直接連携します。 Microsoft は、Kerberos.NET に関して Microsoft と直接作成したサポート ケースを終了します。
要約すると、一部の Microsoft 従業員がこのリポジトリを管理し、貢献している可能性があるにもかかわらず、このリポジトリは Microsoft によって正式にサポートされていません。彼らは、Microsoft (または Microsoft 従業員) からの SLA なしで、自由時間に、または社内で使用するために部分的に業務時間としてこれを行っています。 ODP.NET での Kerberos.NET の使用は、Oracle サポートを通じてのみサポートされます。
Kerberos メッセージを操作できるようにする .NET に組み込まれたライブラリ。クライアントを実行したり、独自の KDC をホストしたり、受信したチケットを検証したりすることができます。可能な限り軽量になるように設計されています。
Kerberos.NET の設計について詳しく説明されており、一読の価値があります。
このプロジェクトは主にライブラリですが、アプリケーションの構築や Kerberos の問題のトラブルシューティングに役立つ、ライブラリをラップする便利なツールも多数含まれています。
Fiddler 拡張機能インストーラーは、このページの右側のリリースの下にあります。詳細については、インストール方法と使用方法に関する記事を読んでください。
Bruce コマンド ライン ツールは、Kerberos.NET ライブラリ コンポーネントと対話できるようにするユーティリティのコレクションであり、 dotnet tool install bruce -g
経由で利用できます。チケット キャッシュやキータブ管理などに便利なツールが含まれています。これには、後述する Ticket Decoder ユーティリティも含まれています。このツールは多かれ少なかれ MIT および Heimdal コマンド ライン標準に従っていますが、スイート内のすべてのツールの詳細については、Bruce コマンド ラインのhelp
参照してください。
このツールの使用方法については、このブログ投稿を参照してください。
krb5 構成ファイルを表示および変更します。
Kerberos/Negotiate チケットをデコードし、秘密を知っている場合はオプションで復号化します。
チケット キャッシュ ファイルを削除します。
ユーザーを認証し、リクエストに使用可能な多数のオプションを指定して TGT をリクエストします。
キャッシュ内のすべてのチケットを表示し、必要に応じてさらにチケットをリクエストします。
現在のユーザーまたは指定されたユーザーの AS-REQ「ping」を KDC に送信して、ユーザーのメタデータを取得します。
トラブルシューティングをサポートしてキータブ ファイルを表示および操作します。
現在のユーザーのチケットをリクエストし、使いやすい方法で詳細をフォーマットします。
/verbose
コマンド ライン パラメーターを渡すと、このツールは有用なログ メッセージを公開します。
このライブラリは、サポートされているすべての .NET Standard 2.0 プラットフォームで動作しますが、いくつかの注意点があります。
このライブラリを使用するには 2 つの方法があります。 1 つ目は、コードをダウンロードしてローカルでビルドすることです。 2 番目のより良いオプションは、nuget を使用することです。
PM> インストールパッケージ Kerberos.NET
このライブラリを使用するには 3 つの方法があります。
クライアントは、他のプラットフォームにあるクライアントと比較して、意図的に単純になっています。これは完全な機能を備えており、SPNego メッセージの生成をサポートしています。
var client = new KerberosClient();var kerbCred = new KerberosPasswordCredential("[email protected]", "userP@ssw0rd!");await client.Authenticate(kerbCred);var ticket = await client.GetServiceTicket("host/appservice .corp.identityintervention.com");var header = "交渉" + Convert.ToBase64String(ticket.EncodeGssApi().ToArray());
KDC のホストは、特定のポートでリッスンする必要があるため、少し複雑です。通常はポート 88 でリッスンします。
var port = 88;var options = new ListenerOptions{ListeningOn = new IPEndPoint(IPAddress.Loopback, port),DefaultRealm = "corp.identityintervention.com".ToUpper(),RealmLocator = realmName => new MyRealmService(realmName)};varリスナー = 新しい KdcServiceListener(オプション);リスナーを待機します。Start();
リスナーは、 listener.Stop()
が呼び出される (または破棄される) まで待機します。
チケットの認証は 2 段階で行われます。最初の段階では、 KerberosValidator
のデフォルト実装を使用してIKerberosValidator
を介してチケットが正しいかどうかを検証します。第 2 段階では、チケットを使用可能なClaimsIdentity
(特にKerberosIdentity : ClaimsIdentity
) に変換します。これはKerberosAuthenticator
で行われます。
開始する最も簡単な方法は、新しいKerberosAuthenticator
を作成し、 Authenticate
呼び出すことです。変換の動作を微調整する必要がある場合は、 ConvertTicket(DecryptedData data)
メソッドをオーバーライドすることで実行できます。
varauthenticator = new KerberosAuthenticator(new KeyTable(File.ReadAllBytes("sample.keytab")));varidentity =authenticator.Authenticate("YIIHCAYGKwYBBQUCoIIG...");Assert.IsNotNull(identity);var name =identity.Name ;Assert.IsFalse(string.IsNullOrWhitespace(名前));
オーセンティケーターのコンストラクター パラメーターはKeyTable
であることに注意してください。 KeyTable
、他のプラットフォームでキーを保存するために使用される一般的な形式です。 ktpass
などのツールで作成されたファイルを使用することも、インスタンス化中にKerberosKey
渡すだけでも同じ効果が得られます。
nuget パッケージは通常、コア ライブラリへの変更に応じて最新の状態に保たれます。
やあ、うまくいくよ! nuget パッケージを参照として追加するだけです。
詳細情報
Active Directory では、トークンが送信されるドメインと一致する ID が存在する必要があります。この ID には、Active Directory 内の任意のユーザーまたはコンピュータ オブジェクトを指定できますが、正しく構成されている必要があります。これは、サービス プリンシパル名 (SPN) が必要であることを意味します。テスト ユーザーの設定手順については、こちらをご覧ください。
Active Directory は、Server 2012 からクレームをサポートしています。当時は、Windows プリンシパルまたは ADFS ダーク マジックを介してのみクレームにアクセスできました。 Kerberos.NET は、Kerberos チケットのクレームの解析をネイティブにサポートするようになりました。この設定の詳細については、クレーム ガイドをご覧ください。
Kerberos.NET は、Kerberos チケットの復号化と検証に使用されるキーを渡すための KeyTable (keytab) ファイル形式をサポートしています。 keytab ファイル形式は、キーを保存するために多くのプラットフォームで使用される一般的な形式です。これらのファイルは、リモート サーバー管理ツール (RSAT) パックの一部であるktpass
コマンド ライン ユーティリティを使用して Windows 上で生成できます。 PowerShell 経由 (または Windows コンポーネントの追加ダイアログ経由) でサーバーにインストールできます。
Windows 機能 RSAT の追加
そこから、次のコマンドを実行してキータブ ファイルを生成できます。
ktpass /princ HTTP/[email protected] /mapuser IDENTITYINTERserver01$ /pass P@ssw0rd! /out サンプル.keytab /crypto all /PTYPE KRB5_NT_SRV_INST /mapop set
パラメータprinc
は、生成された PrincipalName と、それを Active Directory 内のユーザーにマップするために使用されるmapuser
指定するために使用されます。 crypto
パラメータは、どのアルゴリズムがエントリを生成するかを指定します。
AES チケットはネイティブにサポートされています。余計なことをする必要はありません!
これには、RFC8009 を介した SHA256 および SHA384 のサポートも含まれるようになりました。
詳細については、「FAST Armoring」を参照してください。
これは現在サポートされていませんが、ロードマップに記載されています。
DES のような他のアルゴリズムに対する独自のサポートを追加することもできます (なぜそうするのかはわかりませんが...)。暗号化タイプを、新しい復号化プログラムをインスタンス化する Func<> に関連付けます。また、必要に応じて、このプロセスを DI することを妨げるものは何もありません。
KerberosRequest.RegisterDecryptor( 暗号化タイプ.DES_CBC_MD5、 (トークン) => 新しい DESMD5DecryptedData(トークン));
組み込みのリプレイ検出は、 MemoryCache
使用して、チケット nonce のハッシュへの参照を一時的に保存します。これらの参照は、チケットの有効期限が切れると削除されます。検出プロセスは、認証シーケンス番号が利用可能になるとすぐに、復号化の直後に行われます。
キャッシュがマシン間で共有されないため、アプリケーションがクラスター化されている場合、組み込みの検出ロジックは効果的に機能しないことに注意してください。組み込み実装はメモリ内サービスを使用するため、誰とも共有されません。
これがクラスター環境で正しく機能するには、マシン間で共有されるキャッシュを作成する必要があります。これは、新しい .NET Core 依存関係注入サービスによって大幅に簡素化されました。必要なのは、 IDistributedCache
実装を登録することだけです。詳細については、Microsoft Docs を参照してください。
独自のリプレイ検出を使用したい場合は、 ITicketReplayValidator
インターフェイスを実装し、それをKerberosValidator
コンストラクターに渡すだけです。
サンプルあります!
KerbCrypto サポートされている 6 つのトークン形式で実行されます。
rc4-kerberos-data
rc4-spnego-データ
aes128-kerberos-data
aes128-spnego-データ
aes256-kerberos-data
aes256-spnego-データ
KerbTester 実際のチケットをテストし、解析結果をダンプするために使用されるコマンド ライン ツール。
KerberosMiddlewareEndToEndSample サーバーがどのようにネゴシエーションを要求し、エミュレートされたブラウザーの応答を示すエンドツーエンドのサンプル。
KerberosMiddlewareSample チケットが存在する場合はデコードしますが、存在しない場合はネゴシエーションを要求しない、単純な合否ミドルウェア サンプルです。
KerberosWebSample IIS でホストされることを目的としたサンプル Web プロジェクト。ブラウザーから受信したチケットをネゴシエートして検証するように求められます。
このプロジェクトには MIT ライセンスがあります。詳細については、ライセンス ファイルを参照してください。これが依存するプロジェクトのライセンスの詳細については、通知ファイルも参照してください。
このライブラリには、サービス チケットをデコードするためのオプションのユーティリティが付属しています。使い方は簡単です。 Base64 でエンコードされたチケットのコピーを左側のテキストボックスにコピーするだけです。キーを指定しない場合は、暗号化されていないメッセージがデコードされます。キーを指定すると、メッセージの復号化が試行されます。チケットが RC4 を使用して暗号化されている場合はホスト値を指定する必要はありませんが、(ソルトを導出するために) AES で暗号化されている場合はホスト値が必要になります。あるいは、keytab ファイルがある場合は、それを含めることもできます。
bruce kdecode
を含む Bruce ツールを使用して起動できます。
デコーダは、Kerberos チケットを構造化されたツリー ビューに変換します。プロセスは、Kerberos ASN.1 => JSON () => ツリー ビュー レンダリングです。これは、チケットで利用可能なすべての情報を示す中間 JSON です。
{ "Request": {"KrbApReq": { "ProtocolVersionNumber": 5, "MessageType": "KRB_AP_REQ", "ApOptions": "Reserved", "Ticket": {"TicketNumber": 5,"Realm": "CORP. IDENTITYINTERVENTION.COM","SName": { "FullyQualifiedName": "desktop-h71o9uu", "IsServiceName": false, "Type": "NT_PRINCIPAL", "Name": ["desktop-h71o9uu" ]},"EncryptedPart": { "EType": "AES256_CTS_HMAC_SHA1_96", "KeyVersionNumber": 3、「暗号」: "Vo4uodU2...スニペット...XBwjmsshgyjs+Vr+A=="} }, "Authenticator": {"EType": "AES256_CTS_HMAC_SHA1_96","KeyVersionNumber": null,"Cipher": "NnLmEFkmO3HXCS...スニペット。 ..up0YmNW5AicQVvvk" }},"KrbApRep": null }、 "復号化": {"オプション": "予約","EType": "AES256_CTS_HMAC_SHA1_96","SName": { "FullyQualifiedName": "desktop-h71o9uu", "IsServiceName": false, "Type": "NT_PRINCIPAL", 「名前」: ["デスクトップ-h71o9uu" ]},"Authenticator": { "AuthenticatorVersionNumber": 5, "Realm": "CORP.IDENTITYINTERVENTION.COM", "CName": {"FullyQualifiedName": "jack","IsServiceName": false,"Type": " NT_PRINCIPAL","名前": [ "jack"] }, "チェックサム": {"タイプ": "32771","チェックサム": "EAAAAAAAAAAAAAAAAAAAAAAAAAAAA8QAAA" }, "CuSec": 305, "CTime": "2021-04-21T17:38:11+00:00", "Subkey": {"Usage": "Unknown","EType": "AES256_CTS_HMAC_SHA1_96" ","キー値": "nPIQrMQu/tpUV3dmeIJYjdUCnpg0sVDjFGHt8EK94EM=" }, "SequenceNumber": 404160760, "AuthorizationData": [{ "Type": "AdIfRelevant", "Data": "MIHTMD+gBAICAI2hNwQ1M...snip...BJAE8ATgAuAEMATwBNAA=="} ]},"チケット": { "フラグ": ["EncryptedPreAuthentication","PreAuthenticated","Renewable","Forwardable" ], "Key": {"使用法": "不明","Eタイプ": "AES256_CTS_HMAC_SHA1_96","KeyValue": "gXZ5AIsNAdQSo/qdEzkfw3RrLhhypyuG+YcZwqdX9mk=" }, "CRealm": "CORP.IDENTITYINTERVENTION.COM", "CName": {"FullyQualifiedName": "jack","IsServiceName": false,"Type": "NT_PRINCIPAL","Name": [ "jack"] }, "Transited": {"Type": "DomainX500Compress","Contents": "" }, "AuthTime": "2021-04 -21T17:24:53+00:00"、"開始時間": "2021-04-21T17:38:11+00:00"、"EndTime": "2021-04-22T03:24:53+00:00"、"RenewTill": "2021-04-28T17:24:53 +00:00"、"CAddr": null、"AuthorizationData": [{ "Type": "AdIfRelevant", "データ": "MIIDIjCCAx6gBAICAIChg...snip...muoGI9Mcg0="},{ "Type": "AdIfRelevant", "データ": "MF0wP6AEAgIAj...snip...AXg9hCAgAACTDBBAAAAAA="} ]} ,"DelegationTicket": null,"SessionKey": { "使用方法": null, "EncryptionType": "AES256_CTS_HMAC_SHA1_96"、"Host": null、"PrincipalName": null、"Version": null、"Salt": ""、"Password": null、"IterationParameter": ""、"PasswordBytes": ""、"SaltFormat": "ActiveDirectoryService"、"RequiresDerivation": false},"スキュー": "00:05:00" }、 "Computed": {"Name": "[email protected]","Restrictions": { "KerbAuthDataTokenRestrictions": [{ "RestrictionType": 0, "Restriction": {"Flags": "Full"," TokenIntegrityLevel": "高"、"MachineId": "Txr82+sI2kbFmPnkrjldLUfESt/oJzLaWWNqCkOgC7I=" }, "タイプ": "KerbAuthDataTokenRestrictions"},{ "RestrictionType": 0, "制限": {"Flags": "Full","TokenIntegrityLevel": "High","MachineId" : "Txr82+sI2kbFmPnkrjldLUfESt/oJzLaWWNqCkOgC7I=" }, "タイプ": "KerbAuthDataTokenRestrictions"} ], "KerbLocal": [{ "値": "EBeD2EICAAAJMMEEAAAAAA==", "タイプ": "KerbLocal"},{ "値": "EBeD2EICAAAJMMEEAAAAAA==", "タイプ": "KerbLocal"} ], "KerbApOptions": [{ "オプション": "ChannelBindingSupported", "タイプ": "KerbApOptions"} ], "KerbServiceTarget": [{ "ServiceName": "[email protected]", "タイプ": "KerbServiceTarget"} ]、"AdWin2kPac": [{ "モード": "サーバー"、"DecodingErrors": []、"バージョン": 0、"LogonInfo": {"PacType": "LOGON_INFO"、 「ログオン時間」: "2021-04-21T17:24:53.4021307+00:00","ログオフ時間": "0001-01-01T00:00:00+00:00","キックオフ時間": "0001-01-01T00:00:00 +00:00","PwdLastChangeTime": "2021-01-14T23:55:39.0024458+00:00","PwdCanChangeTime": "2021-01-15T23:55:39.0024458+00:00","PwdMustChangeTime": "0001-01-01T00:00:00+00:00","UserName": "jack","UserDisplayName": "Jack Handey","LogonScript": "","ProfilePath": "","HomeDirectory" : "","HomeDrive": "","LogonCount": 99,"BadPasswordCount": 0,"UserId": 1126,"GroupId": 513,"GroupCount": 6,"GroupIds": [ {"RelativeId": 1132,"Attributes": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1131,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1128,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1130,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 513,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }, {"RelativeId": 1129,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }],"UserFlags": "LOGON_EXTRA_SIDS","UserSessionKey": "AAAAAAAAAAAAAAAAAAAAA==","ServerName": "DC01u0000","DomainName": "CORPu0000","DomainId": "S-1-5-21-311626132-1109945507-1757856464","Reserved1": "AAAAAAAAAAA=","UserAccountControl": [ "ADS_UF_LOCKOUT", "ADS_UF_NORMAL_ACCOUNT"],"SubAuthStatus": 0,"LastSuccessfulILogon": "1601-01-01T00:00:00+00:00"、"LastFailedILogon": "1601-01-01T00:00:00+00:00"、"FailedILogonCount": 0、"Reserved3": 0、"ExtraSidCount" ": 1,"ExtraIds": [ {"Sid": "S-1-18-1","属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"] }],"ResourceDomainId": null,"ResourceGroupCount": 0,"ResourceGroupIds": null,"UserSid ": { "ID": 1126、「属性」: "0"、「値」: "S-1-5-21-311626132-1109945507-1757856464-1126"}、"GroupSid": { "ID": 513、"属性": "0 "、 "価値": "S-1-5-21-311626132-1109945507-1757856464-513"},"GroupSids": [ {"Id": 1132,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-1132" }, {"ID": 1131,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-1131" }, {"ID": 1128,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-1128" }, {"ID": 1130,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-1130" }, {"ID": 513,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-513" }, {"ID": 1129,"属性": [ "SE_GROUP_MANDATORY", "SE_GROUP_ENABLED_BY_DEFAULT", "SE_GROUP_ENABLED"],"値": "S-1-5-21-311626132-1109945507-1757856464-1129" }],"ExtraSids": [ {"Id": 1,"属性": "0","値": "S-1-18-1" }],"ResourceDomainSid": null,"ResourceGroups": [],"DomainSid": { "Id": 1757856464, 「属性」: 「0」、「値」: "S-1-5-21-311626132-1109945507-1757856464"} }, "ServerSignature": {"タイプ": "HMAC_SHA1_96_AES256","署名": "Q0gnRmxBoh5w0DzS","RODCIdentifier": 0,"PacType": "0" }, "CredentialType": null, "KdcSignature": {"Type": "HMAC_SHA1_96_AES256","Signature": "HVsreq5rqBiPTHIN","RODCIdentifier": 0,"PacType": "0 " }, "ClientClaims": null, "DeviceClaims": null, "ClientInformation": {"ClientId": "2021-04-21T17:24:53+00:00","Name": "jack","PacType": "CLIENT_NAME_TICKET_INFO" }, "UpnDomainInformation" ": {"Upn": "[email protected]","ドメイン": "CORP.IDENTITYINTERVENTION.COM","Flags": "0","PacType": "UPN_DOMAIN_INFO" }, "DelegationInformation": null, "HasRequiredFields": true, "Type": "AdWin2kPac"} ]},"ValidationMode ": "パック","クレーム": [ {"タイプ": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid","値": "S-1-5-21-311626132-1109945507-1757856464-1126" }, {"タイプ": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","Value": "Jack Handey" }, {"Type": "http://schemas.xmlsoap.org/ ws/2005/05/identity/claims/nameidentifier","Value": "[email protected]" }, {"Type": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-1132" }, {"タイプ": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-1131" }, {"タイプ": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-1128" }, {"タイプ": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-1130" }, {"タイプ": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-513" }, {"タイプ": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role","値": "ドメイン ユーザー" }, {"タイプ": "http://schemas.microsoft.com/ ws/2008/06/identity/claims/groupsid","値": "S-1-5-21-311626132-1109945507-1757856464-1129" }, {"種類": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid","値": "S-1-18-1" }] }、 "KeyTable": {"FileVersion": 2,"KerberosVersion": 5,"Entries": [ {"EncryptionType": "NULL","Length": 0,"Timestamp": "2021-04-21T23:52: 22.5460123+00:00","バージョン": 5,"ホスト": null,"PasswordBytes": "jBBI1KL19X3olbCK/f9p/+cxZi3RnqqQRH4WawB4EzY=","KeyPrincipalName": { "Realm": "CORP.IDENTITYINTERVENTION.COM", "Names": ["STEVE-HOME" ], "NameType": " NT_SRV_HST", "FullyQualifiedName": "STEVE-HOME"},"Salt": null }] }}