/// <summary> /// Import a krb-cred structure containing one or more tickets into the current user ticket cache. /// </summary> /// <param name="krbCred">The krb-cred to import into the cache.</param> /// <param name="luid">The Logon Id of the user owning the ticket cache. The default of 0 represents the currently logged on user.</param> public unsafe void ImportCredential(KrbCred krbCred, long luid = 0) { if (krbCred is null) { throw new ArgumentNullException(nameof(krbCred)); } var krbCredBytes = krbCred.EncodeApplication(); var ticketRequest = new KERB_SUBMIT_TKT_REQUEST { MessageType = KERB_PROTOCOL_MESSAGE_TYPE.KerbSubmitTicketMessage, KerbCredSize = krbCredBytes.Length, KerbCredOffset = Marshal.SizeOf(typeof(KERB_SUBMIT_TKT_REQUEST)), LogonId = luid }; var bufferSize = ticketRequest.KerbCredOffset + krbCredBytes.Length; using (var pool = CryptoPool.Rent <byte>(bufferSize)) { var buffer = pool.Memory.Slice(0, bufferSize); fixed(void *pBuffer = &MemoryMarshal.GetReference(buffer.Span)) { Marshal.StructureToPtr(ticketRequest, (IntPtr)pBuffer, false); krbCredBytes.Span.CopyTo(buffer.Span.Slice(ticketRequest.KerbCredOffset)); this.LsaCallAuthenticationPackage(pBuffer, bufferSize); } } }
public override bool Add(TicketCacheEntry entry) { if (entry.Value is KerberosClientCacheEntry cacheEntry) { var cred = KrbCred.WrapTicket( cacheEntry.KdcResponse.Ticket, new KrbCredInfo { Key = cacheEntry.SessionKey, AuthTime = cacheEntry.AuthTime, EndTime = cacheEntry.EndTime, Flags = cacheEntry.Flags, PName = cacheEntry.KdcResponse.CName, Realm = cacheEntry.KdcResponse.CRealm, RenewTill = cacheEntry.RenewTill, SName = cacheEntry.KdcResponse.Ticket.SName, SRealm = cacheEntry.KdcResponse.Ticket.Realm, StartTime = cacheEntry.StartTime } ); lsa.ImportCredential(cred); } return(true); }
public void CreateKrbCredSucceeds() { KrbCred krbCred = CreateKrbCredential(); Assert.IsNotNull(krbCred); Assert.AreEqual(EncryptionType.NULL, krbCred.EncryptedPart.EType); Assert.AreEqual("host/test.com", krbCred.Tickets[0].SName.FullyQualifiedName); }
/// <summary> /// Shows the Kerberos Ticket included in an authentication token with KrbCred format /// which is used to transfer Kerberos credentials between applications. /// Reference: /// The Unencrypted Form of Kerberos 5 KRB-CRED Message /// https://tools.ietf.org/html/rfc6448 /// </summary> /// <param name="message"></param> internal void ShowKrbCredTicket(string message) { var krbAsRepBytes = Convert.FromBase64String(message); var krbCred = KrbCred.DecodeApplication(krbAsRepBytes); Assert.IsNotNull(krbCred); var credPart = krbCred.Validate(); Assert.IsNotNull(credPart); AADKerberosLogger.PrintLines(2); AADKerberosLogger.Save("KRB-CRED Supplemental Ticket -----------------------------"); AADKerberosLogger.Save(" ProtocolVersionNumber: " + krbCred.ProtocolVersionNumber); AADKerberosLogger.Save(" Message Type: " + krbCred.MessageType); AADKerberosLogger.Save(" # of Tickets: " + krbCred.Tickets.Length); for (int i = 0; i < krbCred.Tickets.Length; i++) { var ticket = krbCred.Tickets[i]; var ticketInfo = credPart.TicketInfo[i]; var key = new byte[ticketInfo.Key.KeyValue.Length]; ticketInfo.Key.KeyValue.CopyTo(key); AADKerberosLogger.Save(" Number: " + ticket.TicketNumber); AADKerberosLogger.Save(" Realm: " + ticket.Realm); AADKerberosLogger.Save(" SName: " + ticket.SName.FullyQualifiedName); ShowEncryptedDataPart("EncryptedPart", ticket.EncryptedPart); AADKerberosLogger.Save(" Ticket.Flags: " + ticketInfo.Flags); AADKerberosLogger.Save(" Ticket.Realm: " + ticketInfo.Realm); AADKerberosLogger.Save(" Ticket.PName: " + ticketInfo.PName.FullyQualifiedName); AADKerberosLogger.Save(" Ticket.SRealm: " + ticketInfo.SRealm); AADKerberosLogger.Save(" Ticket.SName: " + ticketInfo.SName.FullyQualifiedName); AADKerberosLogger.Save(" Ticket.AuthTime: " + ticketInfo.AuthTime); AADKerberosLogger.Save(" Ticket.StartTime: " + ticketInfo.StartTime); AADKerberosLogger.Save(" Ticket.EndTime: " + ticketInfo.EndTime); AADKerberosLogger.Save(" Ticket.RenewTill: " + ticketInfo.RenewTill); ShowEncrytionKey("Ticket.Key", ticketInfo.Key); if (ticketInfo.AuthorizationData == null) { AADKerberosLogger.Save(" Ticket.AuthorizationData:"); } else { for (int j = 0; j < ticketInfo.AuthorizationData.Length; j++) { ShowAuthorizationData("Ticket.AuthorizationData", ticketInfo.AuthorizationData[j]); } } AADKerberosLogger.Save(""); } }
/// <summary> /// Create KRB_CRED. This PDU should be sent after AP exchange successfully. /// </summary> /// <returns>The created KRB_CRED.</returns> public KrbCred CreateKrbCredRequest() { KrbCred cred = new KrbCred(context); cred.KerberosCred.msg_type = new Asn1Integer((int)MsgType.KRB_CRED); cred.KerberosCred.pvno = new Asn1Integer(ConstValue.KERBEROSV5); Ticket[] ticket = new Ticket[] { context.ApTicket }; cred.KerberosCred.tickets = new Asn1SequenceOf <Ticket>(ticket); EncryptionKey key = context.ContextKey; cred.CredEncPart = ConstrutCredEncryptedData(key); return(cred); }
private static KrbCred CreateKrbCredential() { KrbCred krbCred = KrbKdcRep.GenerateWrappedServiceTicket(new ServiceTicketRequest { Principal = new FakeKerberosPrincipal("*****@*****.**"), ServicePrincipal = new FakeKerberosPrincipal(RequestedSpn), ServicePrincipalKey = Key, IncludePac = false, RealmName = "test.com", Now = DateTimeOffset.UtcNow, StartTime = DateTimeOffset.UtcNow, EndTime = DateTimeOffset.UtcNow.AddHours(5), RenewTill = DateTimeOffset.UtcNow.AddDays(3), Flags = TicketFlags.Renewable }); return(krbCred); }
public async Task KdcTagPeekFailureUnknownHandler() { var kdc = new KdcServer(new KdcServerOptions { DefaultRealm = "domain.com", IsDebug = true }); var krbCred = new KrbCred { Tickets = Array.Empty <KrbTicket>() }; var response = await kdc.ProcessMessage(krbCred.EncodeApplication()); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("doesn't have a message handler registered")); }
private static KrbCred CreateKrbCredential() { var key = new KerberosKey(key: new byte[16], etype: EncryptionType.AES128_CTS_HMAC_SHA1_96); KrbCred krbCred = KrbKdcRep.GenerateWrappedServiceTicket(new ServiceTicketRequest { Principal = new FakeKerberosPrincipal("*****@*****.**"), ServicePrincipal = new FakeKerberosPrincipal("host/test.com"), ServicePrincipalKey = key, IncludePac = false, RealmName = "test.com", Now = DateTimeOffset.UtcNow, StartTime = DateTimeOffset.UtcNow, EndTime = DateTimeOffset.UtcNow.AddHours(5), RenewTill = DateTimeOffset.UtcNow.AddDays(3), Flags = TicketFlags.Renewable }); return(krbCred); }
public async Task KdcTagPeekFailureNullBuilder() { var kdc = new KdcServer(new KdcServerOptions { DefaultRealm = "domain.com", IsDebug = true }); kdc.RegisterMessageHandler(MessageType.KRB_CRED, (b, o) => null); var krbCred = new KrbCred { Tickets = Array.Empty <KrbTicket>() }; var response = await kdc.ProcessMessage(krbCred.EncodeApplication()); var err = KrbError.DecodeApplication(response); Assert.IsNotNull(err); Assert.AreEqual(KerberosErrorCode.KRB_ERR_GENERIC, err.ErrorCode); Assert.IsTrue(err.EText.Contains("Message handler builder KRB_CRED must not return null")); }
//FROM TGS_REP public static byte[] toKirbi(KrbTgsRep tgsRep, KrbEncTgsRepPart tgsDecryptedRepPart, bool ptt = false) { //KrbCredInfo::= SEQUENCE { // key[0] EncryptionKey, //prealm[1] Realm OPTIONAL, //pname[2] PrincipalName OPTIONAL, //flags[3] TicketFlags OPTIONAL, //authtime[4] KerberosTime OPTIONAL, //starttime[5] KerberosTime OPTIONAL, //endtime[6] KerberosTime OPTIONAL //renew - till[7] KerberosTime OPTIONAL, //srealm[8] Realm OPTIONAL, //sname[9] PrincipalName OPTIONAL, //caddr[10] HostAddresses OPTIONAL //} var info = new KrbCredInfo() { Key = tgsDecryptedRepPart.Key, Realm = tgsDecryptedRepPart.Realm, PName = tgsRep.CName, Flags = tgsDecryptedRepPart.Flags, StartTime = tgsDecryptedRepPart.StartTime, EndTime = tgsDecryptedRepPart.EndTime, RenewTill = tgsDecryptedRepPart.RenewTill, SRealm = tgsDecryptedRepPart.Realm, SName = tgsDecryptedRepPart.SName }; //EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { //ticket-info[0] SEQUENCE OF KrbCredInfo, //nonce[1] INTEGER OPTIONAL, //timestamp[2] KerberosTime OPTIONAL, //usec[3] INTEGER OPTIONAL, //s-address[4] HostAddress OPTIONAL, //r-address[5] HostAddress OPTIONAL //} KrbCredInfo[] infos = { info }; var encCredPart = new KrbEncKrbCredPart() { TicketInfo = infos }; //KRB-CRED ::= [APPLICATION 22] SEQUENCE { //pvno[0] INTEGER, //msg - type[1] INTEGER, --KRB_CRED //tickets[2] SEQUENCE OF Ticket, //enc - part[3] EncryptedData //} var myCred = new KrbCred(); myCred.ProtocolVersionNumber = 5; myCred.MessageType = MessageType.KRB_CRED; KrbTicket[] tickets = { tgsRep.Ticket }; myCred.Tickets = tickets; var encryptedData = new KrbEncryptedData() { Cipher = encCredPart.EncodeApplication(), }; myCred.EncryptedPart = encryptedData; byte[] kirbiBytes = myCred.EncodeApplication().ToArray(); string kirbiString = Convert.ToBase64String(kirbiBytes); if (ptt) { LSA.ImportTicket(kirbiBytes, new LUID()); } return(kirbiBytes); }
//FROM TGS public static byte[] toKirbi(KrbTicket tgs, string srvName, string srvHash, EncryptionType etype, string service, bool ptt = false, bool verbose = false) { var kerbCred = new Utils.KerberosHashCreds(srvName, srvHash, etype); var ticketDecrypted = tgs.EncryptedPart.Decrypt (kerbCred.CreateKey(), KeyUsage.Ticket, b => KrbEncTicketPart.DecodeApplication(b)); //KrbCredInfo::= SEQUENCE { // key[0] EncryptionKey, //prealm[1] Realm OPTIONAL, //pname[2] PrincipalName OPTIONAL, //flags[3] TicketFlags OPTIONAL, //authtime[4] KerberosTime OPTIONAL, //starttime[5] KerberosTime OPTIONAL, //endtime[6] KerberosTime OPTIONAL //renew - till[7] KerberosTime OPTIONAL, //srealm[8] Realm OPTIONAL, //sname[9] PrincipalName OPTIONAL, //caddr[10] HostAddresses OPTIONAL //} string srvHost = null; if (srvName.Contains("$")) { srvHost = srvName.Replace("$", string.Empty) + "." + ticketDecrypted.CRealm; } else { srvHost = srvName; } var info = new KrbCredInfo() { Key = ticketDecrypted.Key, Realm = ticketDecrypted.CRealm, PName = ticketDecrypted.CName, Flags = ticketDecrypted.Flags, StartTime = ticketDecrypted.StartTime, EndTime = ticketDecrypted.EndTime, RenewTill = ticketDecrypted.RenewTill, SRealm = ticketDecrypted.CRealm, SName = new KrbPrincipalName() { Type = PrincipalNameType.NT_SRV_INST, Name = new[] { service, srvHost } } }; //EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { //ticket-info[0] SEQUENCE OF KrbCredInfo, //nonce[1] INTEGER OPTIONAL, //timestamp[2] KerberosTime OPTIONAL, //usec[3] INTEGER OPTIONAL, //s-address[4] HostAddress OPTIONAL, //r-address[5] HostAddress OPTIONAL //} KrbCredInfo[] infos = { info }; var encCredPart = new KrbEncKrbCredPart() { TicketInfo = infos }; //KRB-CRED ::= [APPLICATION 22] SEQUENCE { //pvno[0] INTEGER, //msg - type[1] INTEGER, --KRB_CRED //tickets[2] SEQUENCE OF Ticket, //enc - part[3] EncryptedData //} var myCred = new KrbCred(); myCred.ProtocolVersionNumber = 5; myCred.MessageType = MessageType.KRB_CRED; KrbTicket[] tickets = { tgs }; myCred.Tickets = tickets; //https://github.com/dirkjanm/krbrelayx/blob/master/lib/utils/kerberos.py#L220 //No Encryption for KRB-CRED var encryptedData = new KrbEncryptedData() { Cipher = encCredPart.EncodeApplication() }; myCred.EncryptedPart = encryptedData; byte[] kirbiBytes = myCred.EncodeApplication().ToArray(); string kirbiString = Convert.ToBase64String(kirbiBytes); if (ptt) { LSA.ImportTicket(kirbiBytes, new LUID()); } else { Console.WriteLine("[+] SliverTicket Ticket Kirbi:"); Console.WriteLine(" - {0}", kirbiString); } if (verbose) { Console.WriteLine("[*] Ticket Info:"); PrintFunc.PrintKirbi(kirbiString); } return(kirbiBytes); }