Asked  7 Months ago    Answers:  5   Viewed   51 times

I am connecting to my database Google Cloud SQL via SSL. I use codeigniter 3.0 to do so, although the mysqli driver is a bit modified to allow this functionality.

It's been working well for months. However it just started to return this warning:

Message: mysqli::real_connect(): SSL operation failed with code 1. OpenSSL Error messages: error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

I'm assuming DH Key is too small is the main problem, but I have no idea what that means. I've googled Diffie–Hellman key exchange, along with the message "key too small" but I haven't had much luck.

Is this a sign that the keys on the server have been tampered with? I've checked the last-modified dates on them -- no abnormal recent access.

It could be that my server did some upgrading to PHP or their server configuration, which may result in this breaking, but I wanted to check and make sure that it wasn't something else.

Thanks for any insight / readable material on the subject.

 Answers

45
... error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small

The error number you are interested in is the OpenSSL error 0x14082174.

The SSL3_CHECK_CERT_AND_ALGORITHM is usually seen when enabling export grade ciphers. It may be showing up again in non-export grade negotiations due to Logjam (see below).


I'm assuming DH Key is too small is the main problem, but I have no idea what that means. I've googled Diffie–Hellman key exchange, along with the message "key too small" but I haven't had much luck.

That's due to the recent Logjam attack from the paper Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice.

You should use 2048-bit Diffie-Hellman groups or larger. You should not be using 512-bit or 1024-bit Diffie-Hellman groups.

The first thing to check for is your cipher list string. It should be similar to:

"HIGH:!aNULL:!MD5:!RC4"

It will avoid the export grade ciphers, and use modern ciphers. But you will also need to ensure your DH callback is not using a weak/small field size. For that, you need to check the server configuration.


Some folks are "solving" the issue with kRSA. kRSA is a key transport scheme, not a key agreement scheme. The RSA key transport scheme does not provide forward secrecy, and its use is usually discouraged. In fact, its going to be removed from TLS 1.3.

I can only say "usually discouraged" because it depends on the data being protected. If you have SSL/TLS to guard downloads of a publicly available file, then its probably OK to use. If your website has a login, then its probably a little risky to use it because the password is secret data (unlike the publicly downloadable file).

To avoid key transport and pass those Qualsys SSL Labs tests for web server configurations and forward secrecy, use:

"HIGH:!aNULL:!kRSA:!MD5:!RC4"

In your Apache configuration file, it would look like so:

# cat /etc/httpd/conf.d/ssl.conf | grep SSLCipherSuite
# SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLCipherSuite HIGH:!aNULL:!kRSA:!MD5:!RC4

I seem to recall wget rejected small groups quite some time before the paper was released. It might make a good test case for your site.

There's also an improved sslscan, which tests for lots of things. That might make a good QA tool, too.

Wednesday, March 31, 2021
 
rypskar
answered 7 Months ago
11

This was an enormously helpful link to find:

http://php.net/manual/en/migration56.openssl.php

An official document describing the changes made to open ssl in PHP 5.6 From here I learned of one more parameter I should have set to false: "verify_peer_name"=>false

Note: This has very significant security implications. Disabling verification potentially permits a MITM attacker to use an invalid certificate to eavesdrop on the requests. While it may be useful to do this in local development, other approaches should be used in production.

So my working code looks like this:

<?php
$arrContextOptions=array(
    "ssl"=>array(
        "verify_peer"=>false,
        "verify_peer_name"=>false,
    ),
);  

$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));

echo $response; ?>
Wednesday, March 31, 2021
 
cyber_truite
answered 7 Months ago
44

It looks like the 2 relevant bugs in PHP are still not entirely resolved: #68344 and #71003.

Saturday, May 29, 2021
 
dimitarvp
answered 5 Months ago
55

Twilio developer evangelist here.

I found this happened when you don't have the curl bindings for PHP. Try recompiling PHP with curl or installing the php5-curl package.

Let me know if that helps at all.

Saturday, May 29, 2021
 
themihai
answered 5 Months ago
64

Here PHP (and mysqli_real_connect) is the client not the server. You're configuring it with mysqli_ssl_set for client-certificate authentication (and using the server key and certificate).

I'm not sure how you've configured your MySQL server, but there should be something like this in the (MySQL) server section of the configuration:

ssl-key=/mysql-ssl-certs/server-key.pem
ssl-cert=/mysql-ssl-certs/server-cert.pem
ssl-ca=/mysql-ssl-certs/ca-cert.pem

These don't belong to the client side anyway (only the CA certificate does, but definitely not the server's private key).

Once you've done this, you can try to see if the server is configured properly using the command line client:

mysql --ssl-verify-server-cert --ssl-ca=/mysql-ssl-certs/ca-cert.pem --ssl -h hostname ...

or perhaps this (although verify server cert should really be enabled for SSL/TLS to be useful)

mysql --ssl-ca=/mysql-ssl-certs/ca-cert.pem --ssl -h hostname ...

This should work at least on the command line.

Then, from PHP, you get two options:

  • use mysqli_ssl_set like you've done, but leaving $key and $cert null, unless you want to use a client-certificate which really ought to be different from your server certificate. (I can't remember whether that works.)
  • possibly easier, omit mysqli_ssl_set altogether and configure this in your global MySQL client configuration file (where PHP should be able to pick it up, possibly /etc/mysql/my.cnf, but this may vary depending on your distribution):

    [client]
    ssl-ca=/mysql-ssl-certs/ca-cert.pem
    

(This is similar to the server config, but on the client side/in the client section.)

For the authorization part (GRANT):

  • REQUIRE SSL only requires the use of SSL/TLS
  • REQUIRE ISSUER, REQUIRE SUBJECT and REQUIRE X509 require the client to present a client-certificate to compare to the required values (that's the case where you'd need to use ssl-key and ssl-cert on the client side (config or within mysqli_ssl_set).
Saturday, July 3, 2021
 
janlindso
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share