[00:00.000 --> 00:10.840] Okay, we can't start. [00:10.840 --> 00:23.880] Hello, I'm Fraser, I come from Australia, work at Red Hat on identity management and [00:23.880 --> 00:31.120] PKI solutions, and yeah, talking about Kerberus PK Unit protocol. [00:31.120 --> 00:36.960] So I'll give an overview of the Kerberus authentication protocol, then I will discuss [00:36.960 --> 00:43.560] PK Unit, what its advantages are, how it works, and a short demo. [00:43.560 --> 00:51.680] Then I will discuss the security considerations and give a demonstration of a recently discovered [00:51.680 --> 01:01.240] attack against the implementation of Kerberus PK Unit that we have in free IPA. [01:01.240 --> 01:08.000] So Kerberus is an authentication protocol based on symmetric cryptography, it's a single [01:08.000 --> 01:16.240] sign on protocol so you can authenticate once per day, for example, and using a token from [01:16.240 --> 01:23.480] that initial authentication, you can then authenticate to additional services, hosts [01:23.480 --> 01:29.760] or users in the organisation's infrastructure. [01:29.760 --> 01:37.240] It was started at MIT in the late 80s, the current major version of the protocol is version [01:37.240 --> 01:42.000] five and it came about in the early 90s. [01:42.000 --> 01:50.800] The most recent IETF document describing the base protocol is RFC 4.1.2.0, and that was [01:50.800 --> 02:00.880] from 2005, so even that version is nearly 18 years old, but there have been many extensions [02:00.880 --> 02:03.680] and enhancements since then. [02:03.680 --> 02:10.160] The major implementations are MIT Kerberus, Microsoft Active Directory, Heimdall, and [02:10.160 --> 02:18.080] free IPA or identity management in RHEL, which uses MIT Kerberus under the hood with some [02:18.080 --> 02:22.920] additional extensions. [02:22.920 --> 02:29.120] The parties in the Kerberus authentication protocol are the client, the key distribution [02:29.120 --> 02:33.760] centre and services. [02:33.760 --> 02:41.120] So the key distribution centre or KDC consists of two services that are logically distinct [02:41.120 --> 02:47.880] within the protocol, but typically combined together into this one party, which is called [02:47.880 --> 02:49.600] the KDC. [02:49.600 --> 02:57.080] Users, services and the KDC itself are all represented as principles in a realm. [02:57.080 --> 03:02.240] So a principle is just a name for a user, host or service in the realm, and the realm [03:02.240 --> 03:05.800] is the namespace for those user hosts or services. [03:05.800 --> 03:11.480] So often you'll see one company, one organisation might have one realm, but as companies grow [03:11.480 --> 03:18.160] or have mergers and acquisitions, then typically you'll end up with multiple realms in your [03:18.160 --> 03:20.760] organisation. [03:20.760 --> 03:28.440] Each principle has a long term secret key, which is shared with the KDC. [03:28.440 --> 03:35.600] For users, it's typically derived from a password or passphrase, so using PBKDF2 or [03:35.600 --> 03:39.240] some other key derivation and algorithm. [03:39.240 --> 03:45.160] And for hosts and services, the file is often stored in just in a flat file, which we call [03:45.160 --> 03:47.560] a key tab. [03:47.560 --> 03:52.840] And the authentication tokens themselves, which are exchanged in this protocol, are [03:52.840 --> 03:55.600] called tickets. [03:55.600 --> 03:58.040] So let's do some diagrams. [03:58.040 --> 04:03.320] The parties, clients, server or services, and the KDC. [04:03.320 --> 04:08.800] We can see the client has a key, the server has a key, and the KDC has all of the keys, [04:08.800 --> 04:15.880] including the ticket granting service TGS key, which is one of the KDC services. [04:15.880 --> 04:21.760] So the initial authentication exchange involves what we call an ASREC or authentication service [04:21.760 --> 04:22.760] request. [04:22.760 --> 04:27.240] The client says, hey, it's me, I want to authenticate. [04:27.240 --> 04:31.320] It doesn't necessarily carry any authentication information. [04:31.320 --> 04:39.640] The authentication happens when the KDC responds to the client and the response includes a [04:39.640 --> 04:46.280] session key randomly generated by the KDC encrypted to the client's secret key. [04:46.280 --> 04:50.800] So the client does not authenticate to the KDC. [04:50.800 --> 04:55.800] There are ways that you can do that, but in the base protocol, the authentication happens [04:55.800 --> 05:00.840] because only the client can decrypt the response containing the session key. [05:00.840 --> 05:07.320] The response also contains a ticket called the ticket granting ticket, which is not encrypted [05:07.320 --> 05:12.120] to the client's key, but rather to the ticket granting services key. [05:12.120 --> 05:18.160] It also contains a copy of the session key and some information about the client. [05:18.160 --> 05:24.480] So the client can decrypt the session key and store the ticket granting ticket. [05:24.480 --> 05:31.960] After when the client wants to authenticate to the server, it sends a TGS request to the [05:31.960 --> 05:39.240] KDC saying, I would like to talk to such and such a principle, in this case, a server. [05:39.240 --> 05:47.640] It includes the ticket granting service ticket or TGT, and it also includes a timestamp [05:47.640 --> 05:54.840] for replay attack prevention and some client information encrypted to the session key. [05:54.840 --> 06:03.520] The KDC can use the TGS secret key to decrypt the ticket, pull out the session key, decrypt [06:03.520 --> 06:09.000] the client authenticator, make sure the client info matches up, make sure the timestamp [06:09.000 --> 06:17.000] is within an allowable skew, and if everything checks out, then in the TGS request, it will [06:17.000 --> 06:18.840] send a TGS reply. [06:18.840 --> 06:25.960] The KDC can return a ticket for the server, which contains a new session key, and it also [06:25.960 --> 06:34.520] returns the new session key encrypted under the existing session key for the TGS session. [06:34.520 --> 06:40.840] So the client can decrypt the second session key and store the ticket for the service, [06:40.840 --> 06:44.520] the service ticket, and finally, it can talk to the service. [06:44.520 --> 06:50.120] So it sends the application protocol request, it includes the service ticket, it includes [06:50.120 --> 06:54.120] an authenticator encrypted using the second session key. [06:54.120 --> 07:00.280] The server can then use its long-term secret key to decrypt the ticket, pull out the session [07:00.280 --> 07:06.640] key, and then it can use that session key to decrypt the authenticator, make sure the [07:06.640 --> 07:12.600] client info all lines up, make sure the timestamp is within the allowable skew, and then there's [07:12.600 --> 07:15.440] a shared session key between the client and the server. [07:15.440 --> 07:21.280] They can talk whatever protocol they want to talk using that session key. [07:21.280 --> 07:28.120] Okay, so that's the base Kerberos protocol. [07:28.120 --> 07:33.440] Kerberos has a bunch of extensions and integrations, there's a pre-authentication framework that [07:33.440 --> 07:42.000] allows you to integrate additional authentication mechanisms, such as a TOTP or an HOTP. [07:42.000 --> 07:49.280] There are mechanisms for embedding Kerberos authentication in the GSS API and in SASL, [07:49.280 --> 07:54.760] so that will allow you to use Kerberos authentication with other protocols that support those authentication [07:54.760 --> 08:01.120] frameworks, such as LDAP or SMTP, IMAP, et cetera. [08:01.120 --> 08:09.600] For HTTP, there's a protocol called Spenego or Spengo, and we can also include authorization [08:09.600 --> 08:18.080] information in the tickets which contain additional information about the client, how they authenticated [08:18.080 --> 08:24.400] to the KDC, so this is what we call the authentication indicator extension, and there are other kinds [08:24.400 --> 08:25.840] of authentication data. [08:25.840 --> 08:31.320] For example, Microsoft Active Directory includes what's called a PAC, I can't remember what [08:31.320 --> 08:39.320] that stands for, but Alexander will know. [08:39.320 --> 08:43.360] Forged attribute certificate, there you go, so that's the MS PAC extension, which you'll [08:43.360 --> 08:49.080] frequently see when you're working with Active Directory or Cross Realm trusts. [08:49.080 --> 08:55.280] With Active Directory, that's that final point, I explained that there were situations where [08:55.280 --> 09:01.160] you're dealing with multiple realms, what if principles from one realm need to communicate [09:01.160 --> 09:06.800] or authenticate to principles in a different realm, that is accomplished by trusts and [09:06.800 --> 09:11.920] the Cross Realm authentication mechanisms. [09:11.920 --> 09:16.880] The advantages of Kerberos, well, it's single sign-on which improves efficiency and reduces [09:16.880 --> 09:21.080] password fatigue for users. [09:21.080 --> 09:28.800] The client has to expose their long-term secret only once until the TGT expires, so maybe [09:28.800 --> 09:35.440] once per day at the start of the day logging into your workstation, a single authentication [09:35.440 --> 09:43.000] happens and from then on, you no longer need to explicitly authenticate. [09:43.000 --> 09:49.640] It is resistant to the replay attacks, that's why all of the authenticators include timestamps, [09:49.640 --> 09:56.720] and it works well for HTTP as well as bare network protocols, which is a shortcoming of [09:56.720 --> 10:07.240] the predominantly HTTP centric SSO protocols like SAML and OpenID Connect. [10:07.240 --> 10:13.320] But the problems are, of course, that passwords are not great and dealing with passwords or [10:13.320 --> 10:18.720] the secret keys in key tabs, making sure that they are rotated, making sure that they are [10:18.720 --> 10:26.000] secure in the first place, can be challenging and burdensome with substantial administrative [10:26.000 --> 10:29.280] overhead. [10:29.280 --> 10:35.560] So this brings us to PKINIT, or Public Key Cryptography for Initial Authentication in [10:35.560 --> 10:39.760] Kerberos as the RFC is called. [10:39.760 --> 10:45.040] In this protocol extension, the client can use asymmetric cryptography to authenticate [10:45.040 --> 10:53.320] to the KDC, and the client presents an X509 certificate in its initial authentication [10:53.320 --> 11:01.840] request, as well as a signature made with the public key or the private key corresponding [11:01.840 --> 11:06.000] to the public key contained in the certificate. [11:06.000 --> 11:14.280] The KDC verifies the certificate, the signature and the binding of the key in the certificate [11:14.280 --> 11:21.120] to the client principal, and if everything checks out, it can respond with a response [11:21.120 --> 11:28.880] encrypted either using Diffie-Hellman or some other analogous key agreement algorithm or [11:28.880 --> 11:34.240] another public key encryption algorithm such as direct RSA encryption. [11:34.240 --> 11:41.080] So visualizing this, the client in the Authentication Service request says, hey, it's me client, [11:41.080 --> 11:45.160] but this time it includes some additional pre-authentication data. [11:45.160 --> 11:51.880] It includes a timestamp, and if it wants to use Diffie-Hellman, a client DH value assigned [11:51.880 --> 11:59.720] by its public key, and it includes the X509 certificate containing that public key. [11:59.720 --> 12:07.920] In the KDC, once it has verified everything is happy to proceed, then its response includes [12:07.920 --> 12:16.000] the TGT, and it includes the session key encrypted using the public key algorithm, in this case [12:16.000 --> 12:22.160] Diffie-Hellman, as well as the KDC Diffie-Hellman value that the client will need to compute [12:22.160 --> 12:28.120] the secret with which the session key is encrypted, and then it can decrypt it, store the session [12:28.120 --> 12:37.320] key, store the TGT, and from this point forward, the rest of the protocol is exactly as before. [12:37.320 --> 12:45.120] In free IPA, by default, we can perform the binding of the certificate and key to the [12:45.120 --> 12:48.960] principal object using an exact certificate match only. [12:48.960 --> 12:54.960] So in the principal's LDAP entry, we'll store a complete copy of the certificate. [12:54.960 --> 12:59.840] We optionally support certificate mapping rules that allow you to be a bit more versatile [12:59.840 --> 13:05.520] in how you establish the binding between the certificate and the principal. [13:05.520 --> 13:12.760] For example, if you're using certificates for hosts, you can pull out the DNS name from [13:12.760 --> 13:18.720] the subject alternative name field in the certificate and construct an LDAP query saying, [13:18.720 --> 13:27.000] well, we're looking for hosts whose FQDN matches that DNS name from the certificate. [13:27.000 --> 13:31.560] And the client certificates can be signed by free IPA's internal CA or by a third-party [13:31.560 --> 13:36.000] CA that the KDC trusts. [13:36.000 --> 13:42.640] The user experience for PKInit, you can do it from a CLI, it's not very pleasant, but [13:42.640 --> 13:49.960] you can use SSSD integrated with your login manager to improve that experience, particularly [13:49.960 --> 13:58.280] if you're using smart cards or TPM for storing the private keys, or doing additional pre-authentication [13:58.280 --> 14:04.440] mechanisms like a two-factor authentication, and Windows offers a similar experience. [14:04.440 --> 14:09.920] It should be, in fact, it must be easy for users and friendly for users, otherwise people [14:09.920 --> 14:14.120] will not use it and you will not get the security benefits. [14:14.120 --> 14:22.680] So quick demo, K-list shows me what tickets I currently have, the answer is none. [14:22.680 --> 14:35.320] If I K-init as Alice, I can type Alice's passphrase, and I now have a TGT for Alice, [14:35.320 --> 14:41.520] so that was a password-based authentication, and if I ping the IPA server, that's just [14:41.520 --> 14:49.520] talking to the free IPA HTTP API, now if I K-list, I can see that behind the scenes, [14:49.520 --> 14:59.400] it's a quieter service ticket for one of the IPA HTTP servers, I'll just destroy those [14:59.400 --> 15:06.920] tickets now, and I'll do a PK-init, so if I change directory here, here I have a certificate [15:06.920 --> 15:24.000] and a key, and just pre-print the cert for you, so what can we say about this cert, and [15:24.000 --> 15:27.360] actually I'll tell you what, I'm doing things in the wrong order here, I'm going to do a [15:27.360 --> 15:49.920] host authentication first, so if I do K-init-x, X509, user identity equals file, and the certificate, [15:49.920 --> 16:04.200] and the key, and a host name, not a host name rather, but the principal name, host slash [16:04.200 --> 16:16.760] rel78.IPA.TEST, and K-list, here we have our TGT for the host principal, okay, so PK-init [16:16.760 --> 16:22.040] advantages, no more passwords or client-shared secrets, the keys can reside on the smart [16:22.040 --> 16:29.280] cards, or so for example in a UV key, in a TPM, or in hardware security module, and [16:29.280 --> 16:34.360] as I mentioned earlier, the rest of the protocol after the initial authentication service exchange [16:34.360 --> 16:39.320] is unchanged, which makes it easy for services. [16:39.320 --> 16:44.920] The complexities, well you need an X509PKI, this brings in the renewal considerations [16:44.920 --> 16:51.320] and revocation considerations, the hardware, if you want the benefit of the hardware security [16:51.320 --> 16:58.400] that will cause an additional financial cost to buy the hardware, and binding the public [16:58.400 --> 17:06.280] key to the principal is an important consideration, so in the RFC, it's RFC 4556 it says, the [17:06.280 --> 17:12.480] KDC must also check that the client's public key used to verify the client's signature [17:12.480 --> 17:18.640] is bound to the client principal name specified in the authentication service request, and [17:18.640 --> 17:24.400] it goes on to suggest how you can do that, a couple of ways you can do it, you can encode [17:24.400 --> 17:30.160] the principal name directly in the certificate in a specialised subject alternative name, [17:30.160 --> 17:36.000] or you can associate the certificate or the key directly with the principal in your database, [17:36.000 --> 17:41.680] that is what we have as the default behaviour in free IPA, but that introduces administrative [17:41.680 --> 17:46.920] overhead because when the certificate is renewed or the client re-keys, then you need to make [17:46.920 --> 17:52.320] sure that those entries are up to date, or you can use other heuristics, for example [17:52.320 --> 17:57.680] if the cert has a DNS name, pull that out and use that to look up a host, if the certificate [17:57.680 --> 18:06.520] has an RFC 822 name, which is an email address, pull that out, use it to look up a user principal, [18:06.520 --> 18:16.680] and you better not mess this up, which brings us to the CVE, so if we have a look at the [18:16.680 --> 18:27.440] certificate that I used to get this host principal, we'll see something interesting, it doesn't [18:27.440 --> 18:35.040] actually mention that principal name anywhere, the RAL7 8-0, but it does have a subject alternative [18:35.040 --> 18:43.400] name, it has two in fact, one of them is a wildcard DNS name. [18:43.400 --> 18:49.200] So what's happening here, it's an LDAP filter injection vulnerability, free IPA is not vulnerable [18:49.200 --> 18:55.440] in the default config because as I mentioned only exact certificate matches used by default. [18:55.440 --> 19:00.920] This bug is in the SSSD component, it was already resolved when I found it, so it was [19:00.920 --> 19:07.120] only older but still supported versions that were affected, and the fix has now been released [19:07.120 --> 19:11.200] and the details are public. [19:11.200 --> 19:17.720] So what's happening is that the cert map rule, sorry about that, the cert map rule is just [19:17.720 --> 19:23.720] pulling the DNS name out of the certificate and concatenating it directly into the LDAP [19:23.720 --> 19:33.280] filter without sanitization and in LDAP, asterisk is a substring match character, so using that [19:33.280 --> 19:40.320] certificate would let you get a TGT for any host principal in your realm. [19:40.320 --> 19:45.880] And another interesting question is what happens if this is your email address? [19:45.880 --> 19:52.400] Now this might seem like a stretch but that is a valid email address and I'm sure many [19:52.400 --> 19:58.320] of you work at companies or have worked at companies where you can request your own email [19:58.320 --> 20:01.240] alias at Red Hat, we certainly do. [20:01.240 --> 20:08.200] So if you managed to request an email alias such as this and the system approved it and [20:08.200 --> 20:13.720] you've got a certificate with that email address on it and you have a cert map rule that looks [20:13.720 --> 20:21.760] something like this where you're stuffing the subject RFC A22 name into the query and [20:21.760 --> 20:29.480] using it to look up a mail attribute and that was somehow nested inside an or list expression, [20:29.480 --> 20:35.480] then you've just got yourself a domain takeover. [20:35.480 --> 20:39.960] So let's see a demo of that. [20:39.960 --> 20:45.960] If there's time, there might not be time, I think, how much? [20:45.960 --> 20:47.960] Five minutes left. [20:47.960 --> 20:52.040] So I'm going to skip it. [20:52.040 --> 20:53.040] Sorry. [20:53.040 --> 20:58.160] I'll tell you what, after I finish the talk, if I can, I'll just do it. [20:58.160 --> 21:00.680] But let me discuss now the mitigation. [21:00.680 --> 21:07.080] So yes, if you're running a vulnerable version of SSSD, you should update it. [21:07.080 --> 21:11.000] The and list rules are harder to exploit than all lists. [21:11.000 --> 21:19.320] Just point out how the LDAP filter expressions work, the all list, if you have a single sub [21:19.320 --> 21:26.240] expression, then the whole list expression will match, but an and list you have to match [21:26.240 --> 21:32.000] every sub clause, so it's just easier to exploit an all list. [21:32.000 --> 21:36.560] You should definitely audit what data can get included in certificates, where that data [21:36.560 --> 21:41.440] comes from, and how it's included or encoded in the cert. [21:41.440 --> 21:46.480] And you could use exact certificate matching to avoid this issue, but that does come with [21:46.480 --> 21:52.880] the administrative overheads to handle renewals or re-keys. [21:52.880 --> 21:58.720] General security considerations for PK unit, well, and this first point is for just all [21:58.720 --> 22:04.760] software always, probably escape and sanitize your inputs according to how you're using [22:04.760 --> 22:06.600] them. [22:06.600 --> 22:11.960] You should review your CA trust, so which CAs are you trusting? [22:11.960 --> 22:17.280] What profiles for issuing the certificates are used or templates? [22:17.280 --> 22:21.840] And how are the attributes that go into the certificates validated? [22:21.840 --> 22:27.920] Who can issue the certificates that you trust, both in terms of their software systems and [22:27.920 --> 22:34.760] the agents, human or otherwise, who act to issue certificates? [22:34.760 --> 22:42.200] And can any of the attributes be influenced by users or other parties, such as if you [22:42.200 --> 22:46.720] have your email address alias request system? [22:46.720 --> 22:51.800] Just because a value is valid in a particular context does not mean that it's benign in [22:51.800 --> 22:54.600] another context. [22:54.600 --> 23:00.720] And the key in principle binding is a critical aspect of PK unit security and PKI application [23:00.720 --> 23:02.080] security in general. [23:02.080 --> 23:13.040] It is as critically important as validating your certificate chain and validating signatures. [23:13.040 --> 23:17.840] The full write up about this issue is at that link on my blog. [23:17.840 --> 23:22.920] And there's a link also to the entry about this issue in the Red Hat CVE database which [23:22.920 --> 23:29.000] includes the list of which products were affected and where the fixes have happened [23:29.000 --> 23:31.440] and where they are not happening. [23:31.440 --> 23:32.440] Okay. [23:32.440 --> 23:48.600] And that's also, I'll ask questions and then maybe I do the domain takeover demo in a minute. [23:48.600 --> 23:50.120] Maybe we have time up for one question. [23:50.120 --> 23:58.560] So is there anyone who has the best question that will be answered in one minute? [23:58.560 --> 23:59.560] They want the demo. [23:59.560 --> 24:00.560] Okay. [24:00.560 --> 24:10.360] So let's, I need to just change the cert map rules, which ones are active? [24:10.360 --> 24:12.880] Oops. [24:12.880 --> 24:13.880] If I can authenticate. [24:13.880 --> 24:14.880] Okay. [24:14.880 --> 24:21.880] My PA is cert map rule, find, this is just the set up. [24:21.880 --> 24:33.160] So I need to disable cert map two and enable cert map one. [24:33.160 --> 24:34.800] Okay. [24:34.800 --> 24:41.360] So this is the rule that I'm enabling. [24:41.360 --> 24:45.160] I didn't enable it. [24:45.160 --> 24:51.360] Oh, thank you for that. [24:51.360 --> 24:54.880] Okay. [24:54.880 --> 24:56.720] Now it's enabled. [24:56.720 --> 25:05.280] And I can do K in it. [25:05.280 --> 25:09.440] Let's see it'll be there in the scroll back somewhere. [25:09.440 --> 25:17.600] That's server, that's okay. [25:17.600 --> 25:23.720] So the naughty certificate and the naughty key. [25:23.720 --> 25:28.840] And I want to be admin. [25:28.840 --> 25:29.840] And now I'm admin. [25:29.840 --> 25:39.880] I'm going to show you the certificate. [25:39.880 --> 25:40.880] Okay. [25:40.880 --> 25:51.360] So the certificate was issued to Alice and the subject name includes Alice's malicious [25:51.360 --> 25:52.360] email alias. [25:52.360 --> 25:53.360] Okay. [25:53.360 --> 25:54.360] There you have it. [25:54.360 --> 26:01.640] That's, there you have it. [26:01.640 --> 26:06.720] Bye. [26:06.720 --> 26:10.560] Thank you. [26:10.560 --> 26:17.960] All right.