Forum Discussion
Maxim_Taskov_90
Nimbostratus
Nov 15, 2011Client Certificate Validation by Subject
I am trying to use the common name CN from the x509::subject variable to validate a client certificate. I used the rule from teh following post as a sample:
http://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/39/aft/1167776/showtab/groupforums/Default.aspx
, and the following DevCentral Wiki for some additional ideas:
http://devcentral.f5.com/wiki/iRules.ClientCertificateCNChecking.ashx
My original iRule was:
when CLIENTSSL_CLIENTCERT {
set subject_dn [X509::subject [SSL::cert 0]]
log local0. "Client Certificate Received: $subject_dn"
if { [matchclass $subject_dn contains $::ebilling_accepted_certs]} {
log local0. "Client Certificate Accepted: $subject_dn"
} else {
log local0. "Invalid Client Certificate Was Found Using: $subject_dn"
reject
}
}
The above iRule does a very good job except that it had two defects, or at least that is what I observed in my deployment:
1. The iRule was crashing with TCL error when client certificate was not presented and instead of rejecting the connection, it allowed it.
2. The iRule was crashing with TCL error when the subject of client certificate was blank (yes, this happens) and instead of rejecting the connection, it allowed it.
Otherwise it was working very well by allowing the connectiong when the presented certificate was in the list of allowed and rejecting the connection when proper client certifiacte was presented (including a subject field, which is not blank) but it is not in the list of teh allowed certificates.
Then I tried to modify the rule to handle the failing conditions of 1 and 2 above. Here is what I got:
when CLIENTSSL_CLIENTCERT {
set subject_dn [X509::subject [SSL::cert 0]]
Log the subject properties of the presented certificate
log local0. "Client Certificate Received: $subject_dn"
Check to see if the presented certificate is allowed and if yes, accept
if {[matchclass $subject_dn contains $::ebilling_accepted_certs]} {
log local0. "Client Certificate Accepted: $subject_dn"
Check to see if certificate is presented and if not, reject
} elseif {[SSL::cert 0] eq ""} {
log local0. "Client Certificate was not provided"
reject
Check to see if the presented certificate has subject and if not, accept
} elseif {[string length $subject_dn] == 0 } {
log local0. "Client Certificate with blank subject was detected"
reject
} elseif {
Any other condition and valid bu unauthorized certificate, reject
log local0. "Unauthorized Client Certificate was detected: $subject_dn"
reject
}
}
The iRule above compiles and runs but still crashes and cannot handle the "blank subject" or "no certificate" conditions and continues to allow the connections when it should be rejecting them.
Any assistance will be greatly appreciated and is desperately needed. Thanks.
18 Replies
- hoolio
Cirrostratus
Hi Maxim,
You should be able to use [SSL::cert count] > 0 to check for a cert before attempting to parse the cert:when CLIENTSSL_CLIENTCERT { if {[SSL cert count] > 1 and [SSL::cert 0] ne ""}{ set subject_dn [X509::subject [SSL::cert 0]] Log the subject properties of the presented certificate log local0. "Client Certificate Received: $subject_dn" Check to see if the presented certificate is allowed and if yes, accept if {$subject_dn eq ""} { Certificate has blank subject, reject log local0. "Client Certificate with blank subject was detected" reject } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} { log local0. "Client Certificate Accepted: $subject_dn" } else { Any other condition, reject log local0. "Unauthorized Client Certificate was detected: $subject_dn" reject } } }
Note that I've remove the $:: prefix from the datagroup name assuming you're on 9.4.4 or higher. If you're on an LTM version lower than 9.4.4, add the $:: prefix back.
Aaron - Maxim_Taskov_90
Nimbostratus
Thanks for the fast reply hoolio. Yes, I am on 9.4.7, so the $:: prefix isn't really needed.
The iRule continues to function fine if authorized and valid but unauthorized client certificate is received. However, the iRule co9ntinues to crash with the following TCL error and allow the connection:
Nov 15 20:34:59 tmm tmm[1672]: 01220001:3: TCL error: client_cert_check - command returned bad code: 32 while executing "if {[SSL::cert count] > 1 and [SSL::cert 0] ne ""}{ set subject_dn [X509::subject [SSL::cert 0]] log local0. "Client Certificate Received:..."
Now the connection is at least rejected when client certificate is not presented but nothing appears in the log.
Thanks again for your help. - nitass
Employee
why is [SSL::cert count] greater than 1? shouldn't it be 1?
this is mine.[root@ve1023:Active] config b virtual bar list virtual bar { snat automap pool foo destination 172.28.65.152:https ip protocol tcp rules myrule profiles { http {} myclientssl { clientside } tcp {} } } [root@ve1023:Active] config b rule myrule list rule myrule { when CLIENTSSL_CLIENTCERT { if {[SSL::cert count] > 0 and [SSL::cert 0] ne ""}{ set subject_dn [X509::subject [SSL::cert 0]] log local0. "Client Certificate Received: $subject_dn" if {$subject_dn eq ""} { log local0. "Client Certificate with blank subject was detected" reject } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} { log local0. "Client Certificate Accepted: $subject_dn" } else { log local0. "Unauthorized Client Certificate was detected: $subject_dn" reject } } } } [root@ve1023:Active] config b class ebilling_accepted_certs list class ebilling_accepted_certs { type string } [root@ve1023:Active] config curl -Ik https://172.28.65.152/ --cert /var/tmp/temp/ca/client.crt --key /var/tmp/temp/ca/client.key curl: (55) SSL_write() returned SYSCALL, errno = 104 [root@ve1023:Active] config Nov 16 00:44:08 local/tmm info tmm[4766]: Rule myrule : Client Certificate Received: CN=client.f5net.com,OU=ps,O=f5net,L=seattle,ST=wa,C=us Nov 16 00:44:08 local/tmm info tmm[4766]: Rule myrule : Unauthorized Client Certificate was detected: CN=client.f5net.com,OU=ps,O=f5net,L=seattle,ST=wa,C=us [root@ve1023:Active] config b class ebilling_accepted_certs list class ebilling_accepted_certs { "CN=client.f5net.com,OU=ps,O=f5net,L=seattle,ST=wa,C=us" } [root@ve1023:Active] config curl -Ik https://172.28.65.152/ --cert /var/tmp/temp/ca/client.crt --key /var/tmp/temp/ca/client.key HTTP/1.1 200 OK Date: Wed, 16 Nov 2011 08:45:17 GMT Server: Apache/2.2.3 (CentOS) Last-Modified: Fri, 11 Nov 2011 14:48:14 GMT ETag: "4183e4-3e-9c564780" Accept-Ranges: bytes Content-Length: 62 Connection: close Content-Type: text/html; charset=UTF-8 [root@ve1023:Active] config Nov 16 00:45:03 local/tmm info tmm[4766]: Rule myrule : Client Certificate Received: CN=client.f5net.com,OU=ps,O=f5net,L=seattle,ST=wa,C=us Nov 16 00:45:03 local/tmm info tmm[4766]: Rule myrule : Client Certificate Accepted: CN=client.f5net.com,OU=ps,O=f5net,L=seattle,ST=wa,C=us - Maxim_Taskov_90
Nimbostratus
Thanks for th reply nitass. You are probably right, why is it >1?! Anyway, I changed it to >0 and it made no difference, I still get the following TCL error when a certificate with blank subject field is presented and the connection is allowed:
Nov 16 14:34:57 tmm tmm[1672]: 01220001:3: TCL error: ebilling_client_cert_check - command returned bad code: 32 while executing "if {[SSL::cert count] > 1}{ set subject_dn [X509::subject [SSL::cert 0]] log local0. "Client Certificate Received: $subject_dn" if {$s..."
Pretty good hack!
After looking at the iRule I thought that maybe "if {[SSL::cert count] > 0 and [SSL::cert 0] ne ""}" statement is at fault as the subject_dn variable will not be populated if [SSL::cert 0] is blank, so then later on when we check for it in "if {$subject_dn eq ""}", the TCL engine has no idea what to do. Well, I removed the "and [SSL::cert 0] ne ""}" part and still got the same TCL error and the connection was allowed/accepted. I hope I am not running into some king of iRule/TCL anomaly as I need to get this running soon and this looks like a serious security vulnerability.
I hope you guys have some additional ideas. - hoolio
Cirrostratus
Yes, the cert count check should have been for >0. I had that in the text of the post but stuck a 1 in the code for reasons unknown :).
I expected X509::subject to return a null string if there wasn't a subject or it couldn't be parsed. But I'm guessing it's returning the runtime error.
Can you open a case with F5 Support on this?
Thanks, Aaron - nitass
Employee
can you advise how to create certificate with blank subject by openssl command?
or may i have your ca certificate, client certificate and key files? - Maxim_Taskov_90
Nimbostratus
Thanks hoolio, I will open a case with F5 but have little faith as they usually send me right back to DevCentral if it is not a hardware issue. I will let you know the outcome.
Nitass, I am not sure how to create the certificate with blank subject field in openssl. I actually stumbled on this issue by accident as I never thought you could have a certificate with blank subject field but I guess you can. In my initial testing of my iRule I just grabbed the first certificate I had in my machine certificate store with the Client Authentication role and it happened to be one issued via auto-enrollment by Microsoft Certificate Authority for the purpose of machine level authentication for a different process. I wouldn't have pursued the anomaly if the connection was rejected but I guess iRule validation fails on TCL error. This appears to be a dangerous exploit and that is why I wanted to find the reason for it and a solution to the obvious security problem.
I can send you the certificate, key and trusted root chain in a separate email if you provide your contact details. Please disable CRL checking in your test configuratuion as I will revoke this certificate for understandable reasons. - hoolio
Cirrostratus
Hi Maxim,
Post the case number and let me know if you have any issues with support helping on this issue. You can reach me at aaron at f5 dot com. In general, support can't be expected to write iRules, but they should troubleshoot when an existing iRule isn't working as expected. They should also be able to help determine proper use of iRule features if they're not already documented on the wiki.
Aaron - nitass
Employee
I can send you the certificate, key and trusted root chain in a separate email if you provide your contact details. thanks, my email is nitass [at] f5 [dot] com - nitass
Employee
thanks for the certificates and key.[root@ve1023:Active] iRuleTest b virtual bar list virtual bar { snat automap pool foo destination 172.28.19.79:https ip protocol tcp rules myrule profiles { myclientssl { clientside } tcp {} } } [root@ve1023:Active] iRuleTest b profile myclientssl list profile clientssl myclientssl { defaults from clientssl ca file "clientblank_ca.crt" peer cert mode require } [root@ve1023:Active] iRuleTest b rule myrule list rule myrule { when CLIENTSSL_CLIENTCERT { if {[SSL::cert count] > 0 and [SSL::cert 0] ne ""}{ catch {X509::subject [SSL::cert 0]} subject_dn log local0. "Client Certificate Received: $subject_dn" if {$subject_dn eq ""} { log local0. "Client Certificate with blank subject was detected" reject } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} { log local0. "Client Certificate Accepted: $subject_dn" } else { log local0. "Unauthorized Client Certificate was detected: $subject_dn" reject } } } } [root@ve1023:Active] iRuleTest curl -Ik https://172.28.19.79 --cert clientblank.crt --key clientblank.key curl: (55) SSL_write() returned SYSCALL, errno = 104 [root@ve1023:Active] iRuleTest Nov 17 09:36:40 local/tmm info tmm[4766]: Rule myrule : Client Certificate Received: Nov 17 09:36:40 local/tmm info tmm[4766]: Rule myrule : Client Certificate with blank subject was detected
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
