Hello Thomas,

Thank you very much for these detailed explanations.

I did use
    ssl_client_certificate /etc/ssl/certs/myuser.crt;
    ssl_verify_client on;

But I had in mind to remove "ssl_client_certificate /etc/ssl/certs/myuser.crt", 
and replace it with
if ($ssl_client_s_dn !~ "O=MyCorp") { return 403; }

When I read your explanation, I understand that in this file
  ssl_client_certificate /path/to/client/cert/ca.pem;
=> I would need to concatenate all my individual client certificates ?

I wanted to remove "ssl_client_certificate /etc/ssl/certs/myuser.crt" because I 
wanted that client verification would work for myuser1, myuser2....not juste 
for one user.
Basicly for all my users in my company, and the website would be exposed on the 
internet.


Thank you for clarifying the attack scenario, I didn't think about it at all.


My ssl configuration is
    ssl_dhparam /etc/nginx/dhparam4096.key;
    ssl_ecdh_curve prime256v1;
    ssl_certificate /etc/ssl/certs/myapp.mydomain.org_chain.crt;
    ssl_certificate_key /etc/ssl/private/myapp.mydomain.org.key;
    ssl_stapling_verify on;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 
"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 180m;
    ssl_client_certificate /etc/ssl/certs/myuser1.crt;
    ssl_verify_client on;


Regards


Le mercredi 12 mars 2025 à 00:35:36 UTC+1, Thomas Ward <tew...@ubuntu.com> a 
écrit : 





Ideally, I would suggest you avoid using `if` for this because there's 
ways your string matching could be bypassed (by providing a client cert 
with your Org defined in the DN but not legitimate), and instead rely on 
issuing of certs by a specific Certificate Authority and validate 
against that, ala:

server {
  listen 443 ssl;
  ...
  ssl_client_certificate /path/to/client/cert/ca.pem;
  ssl_verify_client on;
  ...
}

This will reject anyone who doesn't have a valid client certificate 
created by the CA defined in ssl_client_certificate. Explanation of my 
issues with YOUR approach (as you don't specify if you're doing 
ssl_client_certificate or ssl_verify_client on;) is assuming you aren't 
doing this, and there's a detailed explanation of why your solution is bad.

---

The way YOU'VE suggested is unsafe and opens to MITM or certificate 
faking. Let's use the following example.

My site accepts client certificates. The CA chain is:

CN=Spigot-CA,OU=Technical,O=Spigot,C=US (Serial 69D2DC9DAAABD023)
--> CN=teward,OU=Admin,O=Spigot (Serial 575EDDCAAA0D654F)

I am using your if statement, matching any case where O(rg) is not equal 
to Spigot. However, I am not actually validating the certificate 
signature against the CA cert. As part of Red Team exercises, the red 
team makes a new certificate that has no CA chain and is self-signed 
with the following DN:

(SELFSIGNED) CN=joesmith,OU=badguy,O=Spigot

When the `if` gets triggered and the ssl_client_certificiate isn't set 
and ssl_verify_client not set to "on", then when your if statement reads 
the DN of the Red Team's certificate, it will not ever hit the 443, 
instead it'll be seen as a "legitimate" cert and processing continues. 
That opens you up to "spoofing" of certificates to bypass protections.

Red Team notifies the security team (me) about this vulnerability. So I 
enforce CA cert checks and client verification.  By forcing the 
verification instead of the CA's certificate against the Client 
Certificate presented (which does cryptographic signature tests, etc. 
far beyond just checking the DN of a certificate), it will prevent that 
'spoofed' cert from working.

Accordingly, when I ask Red Team to retest with the permissions set 
accordingly to actually validate the cert against a specific CA cert or 
chain of certs, the Red Team can no longer succeed with their 'spoofed 
certificates' approach, and would need a valid client certificate signed 
by the valid CA certificate (which requires them to have the private 
key, which if you handle data right will never happen) to access the 
site or its resources (and simply would get Bad Request or similar 
because they didn't send a proper SSL cert).

---

Unless I'm misunderstanding your intention, which may be possible 
because you don't include your whole example configuration, etc. for 
this use case.


Thomas

On 2025-03-11 18:58, Mik J via nginx wrote:
> Hello,
>
> I remember from Nginx that "if" can be evil.
>
> I would like to validate that if can be used in the a context where I would 
> like to authenticate my clients with a certificate.
>
> if ($ssl_client_s_dn !~ "O=MyCorp") { return 403; }
>
> Do you have any recommendation ?
>
> Thank you
> _______________________________________________
> nginx mailing list
> nginx@nginx.org
> https://mailman.nginx.org/mailman/listinfo/nginx
_______________________________________________
nginx mailing list
nginx@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx

Reply via email to