Logging EAP-TLS certificate details

Alan DeKok aland at deployingradius.com
Fri Mar 19 13:04:04 CET 2021


On Mar 18, 2021, at 10:43 PM, Roberto.Franceschetti at ocfl.net wrote:
> We see this "feature" of EAP-TLS that allows to specify a completely random username as a serious security risk, as there is no information being logged in the radacct table to indicate what certificate was used to authenticate a particular session.

  As Matthew says, that's how the protocols work.  It's not a security issue with FreeRADIUS.  It's an issue with your local configuration.

  TBH, it's RADIUS.  If it "just works", then great.  Otherwise, it's your responsibility to understand what's going on, and to work around issues with broken clients, broken NASes, etc.  This is simply the reality of RADIUS.

  FreeRADIUS gives you not only the information on exactly what's going on, it gives you the power to fix it.  So the only question here is "how do you work around the issues you're seeing".

  You can send the Class attribute back in the Access-Accept.  And the NAS *should* echo it back in Accounting-Request packets for the same session.

  You can create Class fairly easily in v3, and there are examples to do this.  In 2.2.9, it's a little harder, but not impossible.  Maybe:

update reply {
	Class := "0x%{md5:%{NAS-Identifier}%{TLS-Client-Cert-Common-Name}%{TLS-Client-Cert-Serial}%{TLS-Client-Cert-Issuer}"
}

  You'll have to try some things to see what works.  The idea is to have Class be a 16-byte value, which is taken from an MD5 hash of a bunch of things specific to that particular session.  This hash MUST be unique.

  i.e. if two users log in at the same time, with the same certificate, then they MUST get different values for the Class attribute.  You'll have to (surprise) read the debug output to see wha's in the packets, and what makes those sessions unique.  Things like NAS-Port, etc.

  Once you find out which attributes make the request unique, then put them into the input for the MD5 hash.

  And also log the Class attribute, along with any information about the session (TLS cert information, Framed-IP-Address, NAS-IP-Address, NAS-Port, NAS-Identifier, etc.) before sending the Access-Accept.  Logging this information lets you cross-check the Class when the server receives an Accounting-Request packet which contains the Class.

> Here is our scenario. Hundreds of IoT devices, each authenticating with certs, connecting/disconnecting multiple times per minute. All of them are logging in with the username "user". If one of those certificates is compromised and is used in a malicious way in a different device, while the radius accounting table will show us the IP address of the attacker, there will be absolutely no way to find out which of the hundreds of certificates we issued was abused, and we would thus not know which certificate was compromised and needs to be revoked.

  If you have the Class attribute in the Accounting-Request packets, you just look up that in a DB, find the TLS cert information, and revoke the cert.

  If you don't have Class, you can likely just look up NAS-IP, port, etc.  And that *should* generally be enough.  But not always.  Which is why Class exists.

  And whatever you do, you have to log things when sending the Access-Accept.

> We were able to log the certificate information and link it to the client's IP during the Access-Request via syslog by modifying this in the linelog:
> Access-Request = "Packet-Type=\"%{Packet-Type}\" ...... ,Timestamp = %l,%{User-Name},%{Framed-IP-Address},TLS-Client-Cert-Common-Name = \"%{TLS-Client-Cert-Common-Name}\",TLS-Client-Serial=\"%{TLS-Client-Cert-Serial}\",TLS-Client-Cert-Issuer = \"%{TLS-Client-Cert-Issuer}\","

  That's good, if the NAS sends Framed-IP-Address.  Except the whole point of RADIUS is that it happens *before* the system has network access.  So in general, the Access-Request will not contain a Framed-IP-Address.

  But if Framed-IP-Address exists in the Access-Request *and* Accounting-Request packets, then you can use it to associate the two packets, and then revoke the correct certificate.

> The above will ultimately probably allow us identify the compromised certificate if we're able to capture/archive the syslog data (which we do...), but this is a workaround - the certificate information should really be available in the radacct table as that's what's used to examine user's activity (time remaining connected, bytes transferred, time of connection and so forth).

  No.  Absolutely not.  This is NOT how RADIUS works.

  Read the debug output.  See what's in the Accounting-Request packets.  Note that there's no certificate information.

> Customizing the accounting queries in the dialup.conf however does not seem to work for adding the same TLS-Cert fields to the radacct table (we did of course modify the schema to add the extra TLS-Cert fields). The TLS-Cert fields are being filled with blank values in the radacct table. We're thinking it's probably because the various %{TLS-Client-Cert-nnnnn} are not available during the "Accounting-Request" process. Our modified query is below.

  Read the debug output to see what's in the Accounting-Request packets.  It really is that easy.

  There is no magic here.  If you want to know WHY something is in the radacct table, then read the debug output.  Just... PLEASE read the debug output.  Note that there's no certificate information in the Accounting-Request packet.  So... any idea why the certificate information isn't being logged into radacct?

> Has anyone found a solution to log certificate information in the radius accounting table for users who authenticate via EAP-TLS?

  You don't.  It's impossible.

  What you DO is log the certificate information during authentication, AND log some information which identifies the session.  THEN when receiving an Accounting-Request packet, look up the session information in a database, in order to find the certificate information.

  You're running into the limitations of the RADIUS protocol.  These are NOT limitations in FreeRADIUS.  These are not security issues in FreeRADIUS.

  Every system using RADIUS has it's own set of bizarreness and breakages.  NASes which ignore the standards, supplicants which do weird things, etc.  Your responsibility is to figure out what's going on, and then to use FreeRADIUS and databases in order to glue together a solution.

  You simply cannot rely on the NAS to do anything intelligent.  The NAS gives you packets containing "something".  You have to work with that.  You can't make the NAS do anything else (except usually echo back Class).  So the ONLY solution here is to write FreeRADIUS policies which read/write a database, in order to get the results you want.

  Welcome to RADIUS.  It's a horrific nightmare of insanity.  But FreeRADIUS gives you back control, and lets you work around almost every issue you'll see.

  Alan DeKok.




More information about the Freeradius-Users mailing list