Using One TIme Passwords with FreeRadius
Dear reader of this mailinglist I'm new to the RADIUS business and I did my frist FreeRadius installation just two weeks ago. I still might misunderstand some of the concepts. So keep in mind that whenever I make statments about what FreeRadius does or should do - these are all my personal assumptions only and might be totally wrong. So far I only tried to get things working. I did not look at my "solution" from a security perspective. I'm describing my solution since this might be useful to other people. And I was hoping to get some feedback. My goal was to allow our users to authenticate with our WiFi accesspoints with a 2-factor method. This means for us, that they either have to user their identity card (which has a builtin smart card chip) or their OTP-token (which generates OATH TOTP values). The solution was expected to work with both laptops (Windows and MacOS) and smart phones/tablets (iPhones, Android). It was expected to work with company-devices (manages by our own MDM) and with BYO-devices from eployees or guests. I never heard of solutions that allows an iPhone to use a smart card for authentication. And using smart cards always needs prior installation of smart card middleware. But one time passwords can be used whenever a password has to be entered. Some of our employees have a second token for generation of "guest-passwords". So using passwords generated by our OTP-tokens seemed to be the only way to go. Without two-factor authentication our employees must go to a central helpdesk, prove their identity by showing their identity card or passport, just to get a piece of paper with a password that allows WiFi acces for twelve hours only. If they forward this password to a guest, they have to fill out another piece of paper. With this situation we cannot force the devices to use certain algorithms for WiFi-authentication. OTP-authentication might require that the supplicant sends the password in clear (PAP or PAP within EAP-TTLS). But configuring guest devices to use this authentication method is unrealistic. iPhones for example can do this, but only if they are under MDM-control. So we use EAP-PEAP with MSCHAPv2 because that's supported by all devices if the accesspoint is configured for WPA2-Enterprise. At least we hope that this is true. And we don't care about guests that visit us with their Win-XP laptops. MSCHAPv2 does not send the password in cleartext within the inner tunnel. But as you all know there's no need to compare password A with password B if you just want to check wether they are equal or not. Comparing HashFunction(A) with HashFunction(B) does work as well and the hash function used by MSCHAPv2 is well documented in RFC 2759. So how do you teach FreeRadius to verify an OATH time based one time password? rlm_otp and rlm_secureid where of no help. So I read the the source code of other FreeRadius modules to find the place where FreeRadius does authentication based on the RFC2759 hash function. I found it in rlm_mschap.c in function do_mschap(). There's a switch statement which looks at the value of method. If method==AUTH_INTERNAL FreeRadius calculates the MSCHAPv2 hash on it's own and complains if the password is missing. But to my great pleasure (I love this FreeRadius-software) I spotted another FreeRadius authentication method in that switch-statement, namely AUTH_NTLM_EXEC. With that method FreeRadius delegates the decision about wether the MSCHAPv2 hash value is correct or not to an external program. The location of this external program is configured by the ntlm_auth configuration directive. And the idea behind this was obviously to let the ntlm_auth programm from Samba do the decision. But there's no real reason why the ntlm_auth programm must be the Samba one. So I put ntlm_auth = "/etc/radius/check_otp '%{mschap:User-Name}' '%{mschap:Challenge}' '%{mschap:NT-Response}' '%{Packet-SRC-IP-Address}'" into mods-enabled/mschap and wrote my own "ntlm_auth"-style routine. It takes the username, challenge and a correct token values, calculates the response from these values and compares that with the given response. The 4th-parameter has informational purpoes only and will be included in syslog-messages when something goes wrong. Actually /etc/radius/check_otp does not do anything on its own, but just forwards all arguments to our authentication server. One could avoid that indirection across check_otp and let FreeRadius talk directly with our authentication server. I don't think that's worth the minimal performance improvement. And the interface between FreeRadius and the "ntlm_auth"-program is very easy to implement. This solutions is used within our IT-department since monday and will go into production next week. So far we had no problems. Everybody is glad that he must not visit the helpdesk anymore (which is mostely closed anyway due to corona). There are some pitfalls: Most important: If a one time password turned out to be correct, it will be reused by the supplicant many times. And for obvious reasons you don't want to enter a new token value over and over again. Hence the check_otp routine must accept token values that were successfully used within the past for some amount of time. We use 12 hours for guests and I have to fight with the security staff about wether this can be increased for employees. Their main argument is, that a valid password might be given to other people. So I'm looking for a way to detect wether two supplicants are using the same user/password-combination. iOS MAC-randomization is my enemy here. Maybe someone has an idea how to do this. Kind regards Peter
On Apr 29, 2021, at 4:22 AM, radius.pkoch@dfgh.net wrote:
I'm new to the RADIUS business and I did my frist FreeRadius installation just two weeks ago. I still might misunderstand some of the concepts. So keep in mind that whenever I make statments about what FreeRadius does or should do - these are all my personal assumptions only and might be totally wrong. So far I only tried to get things working. I did not look at my "solution" from a security perspective.
You've taken the best approach, which is a methodical approach. It's much more efficient (and less frustrating) than making random changes in the hope that something works.
I never heard of solutions that allows an iPhone to use a smart card for authentication. And using smart cards always needs prior installation of smart card middleware. But one time passwords can be used whenever a password has to be entered. Some of our employees have a second token for generation of "guest-passwords". So using passwords generated by our OTP-tokens seemed to be the only way to go.
Most people solve the "guest account" problem by just putting guests into a different SSID / VLAN. It's a lot simpler, and has a better user experience.
Without two-factor authentication our employees must go to a central helpdesk, prove their identity by showing their identity card or passport, just to get a piece of paper with a password that allows WiFi acces for twelve hours only. If they forward this password to a guest, they have to fill out another piece of paper.
That is a terrible process. Likely invented by "security" people. i.e. people who understand enough about security to be dangerous, but not enough to be productive. If it's that important to control access to the network, then the network should be partitioned via VLANs, IPSec, etc. For example, Microsoft has a somewhat open corporate network, in that basic network access is controlled via EAP, etc. But that access doesn't really get you anything other than the ability to access the printers. All critical systems are secured via IPSec. So if someone needs access to a particular server, they create a machine-to-machine IPSec connection. The server can do authorization for that particular user / connection / machine. And that's a trillion-dollar corporation protecting billions of dollars in assets. I doubt that smaller companies need a higher level of security. The kind of "security" you describe here is BS security invented by people who have little to no understanding of real network security. It's about proving that they're doing "something" about security, without actually doing anything useful.
But there's no real reason why the ntlm_auth programm must be the Samba one. So I put
ntlm_auth = "/etc/radius/check_otp '%{mschap:User-Name}' '%{mschap:Challenge}' '%{mschap:NT-Response}' '%{Packet-SRC-IP-Address}'"
into mods-enabled/mschap and wrote my own "ntlm_auth"-style routine. It takes the username, challenge and a correct token values, calculates the response from these values and compares that with the given response.
That works... but it's a lot of effort. You could just set Cleartext-Password to be the value of the password + OTP, if it's cached. Then the mschap module would Just Work.
There are some pitfalls:
Most important: If a one time password turned out to be correct, it will be reused by the supplicant many times. And for obvious reasons you don't want to enter a new token value over and over again. Hence the check_otp routine must accept token values that were successfully used within the past for some amount of time. We use 12 hours for guests and I have to fight with the security staff about wether this can be increased for employees. Their main argument is, that a valid password might be given to other people. So I'm looking for a way to detect wether two supplicants are using the same user/password-combination. iOS MAC-randomization is my enemy here. Maybe someone has an idea how to do this.
Cache it somewhere in your script. But all of this is a huge amount of effort to work around a broken "security" process. No one else uses this kind of process for a reason: it's complex, awkward, has a bad user experience, and does little or nothing for security. Alan DeKok.
radius.pkoch@dfgh.net <radius.pkoch@dfgh.net> Wrote:
If a one time password turned out to be correct, it will be reused by the supplicant many times.
...this is why MFA is generally not used as a WiFi authentication method. There is a vendor-specific solution to this with Aruba WiFi... they have a specially hacked up WPA-Personal mode called MPSK where each device has it's own secret rather than a shared network-wide secret. How long that password is good for is controlled by the device's network registration, which is done by MAC address and is tunable. There's a self-service registration server and it has flexible enough AAA tie-ins that you can integrate MFA to logging into that server... so users that haven't done this get dumped where they can only get to that server. It's still WPA-PSK which has no DH exchange so an active attacker could potentially compromise a secret.. they'd only get a device-specific secret but MAC addresses can be spoofed. So it's not perfect. Note that EAP-PEAP-MSCHAPv2 on many types of devices is also subject to active attack because the certificate is not pinned so the device will accept any valid certificate... unless you properly set it up to (and on Android you cannot restrict your CA.) Properly securing it involves going deep into configuration menus. And yes, the MPSK solution also falls to crap with MAC randomization, so you have to get the user to turn that off or set it to per-network. Which may be easier than getting them to configure an EAP method, but still has them going into their settings rather than just typing in a password. (A humorous aside, just after adding MAC randomization some Android installs broke inner-tunnel-IDs so you cannot anonymize federated authentications anymore... way to go "privacy protection"!) Hopefully implementing WPA3-SAE will force vendors to fix this whole situation, but they'll probably just find a brand new way to screw things up. As Alan noted, network layer security is only one layer of a properly secured network. It's basically just there to keep out the rabble so real security threats are not drowned out in your log files. It really isn't the place for MFA, and you aren't really doing MFA if your "one time" passwords are just cached for X hours. Use MFA to control access to self-service registration servers and call it a day.
participants (3)
-
Alan DeKok -
Brian Julin -
radius.pkoch@dfgh.net