Menu

#75 [Patch available] Synapse/OpenSSL accepts wrong-host certificates (security risk)

SVN
closed-fixed
nobody
ssl (3)
9
2023-11-07
2023-10-23
dokkie8844
No

Summary

When using OpenSSL, server certificates are verified automatically. By using Sock.SSL.VerifyCert := True;, a verification error will lead to an exception. However, OpenSSL does not automatically verify the hostname in the certificate that is presented by the server. This is a security risk. If a server presents any non-expired certificate of a different host, this will be accepted in the current setup.

To have OpenSSL verify the hostname in the certificate, which IMHO is essential, the function SSL_set1_host must be used (https://www.openssl.org/docs/man3.0/man3/SSL_set1_host.html). After adding this function to the Synapse code, certificate verification work correctly.

Please see the patches below to correct the code for the ssl_openssl, ssl_openssl11 and ssl_openssl3 variants. Many thanks in advance for correcting this asap, since the current code has an important security risk.

Steps to reproduce:

program project1;

uses httpsend, ssl_openssl3;

const URLs: array[0..5] of string = (
  'https://badssl.com',                // should work
  'https://wrong.host.badssl.com',     // should be rejected
  'https://expired.badssl.com',        // should be rejected
  'https://self-signed.badssl.com',    // should be rejected
  'https://untrusted-root.badssl.com', // should be rejected
  'https://revoked.badssl.com'         // should be rejected
);

var
  URL: string;
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.Sock.SSL.VerifyCert := True;
    HTTP.Sock.SSL.CertCAFile := 'ca-bundle.crt';
    for URL in URLs do
    begin
      if HTTP.HTTPMethod('GET', URL) then
        WriteLn('Success: ', URL)
      else
        WriteLn('Failure: ', URL, '; verify result: ', HTTP.Sock.SSL.GetVerifyCert);
    end;
  finally
    HTTP.Free;
  end;
end.

Current output (without patches)

$ ./project1 
Success: https://badssl.com
Success: https://wrong.host.badssl.com
Failure: https://expired.badssl.com; verify result: 10
Failure: https://self-signed.badssl.com; verify result: 18
Failure: https://untrusted-root.badssl.com; verify result: 19
Failure: https://revoked.badssl.com; verify result: 10

This output shows that the last four URLs are correctly rejected, but that wrong.host.badssl.com is incorrectly not rejected.

Desired output (after applying patches)

$ ./project1 
Success: https://badssl.com
Failure: https://wrong.host.badssl.com; verify result: 62
Failure: https://expired.badssl.com; verify result: 10
Failure: https://self-signed.badssl.com; verify result: 18
Failure: https://untrusted-root.badssl.com; verify result: 19
Failure: https://revoked.badssl.com; verify result: 10

This is the correct output and the verify result is correctly 62.
(See OpenSSL source, which says: # define X509_V_ERR_HOSTNAME_MISMATCH 62)

Patches to repair bug

See the attached patch files to repair the bug.

6 Attachments

Related

Bugs: #77

Discussion

  • Geby

    Geby - 2023-11-07
    • status: open --> closed-fixed
     
  • Geby

    Geby - 2023-11-07

    Thank you, fixed now!

     

Log in to post a comment.