18

How can I connect to a HTTPS website using a specific SSL cipher, and view the output?

This would be useful when doing a vulnerability analysis and weeding out false positives, such as when a device advertises it supports a weak cipher but displays a page informing that a strong cipher must be used.

AviD
  • 72,138
  • 22
  • 136
  • 218
Sonny Ordell
  • 3,476
  • 9
  • 33
  • 56
  • I just used the method in the answer and it worked great. Often times the ciphers reported by the scanning tool don't align with the cipher name that must be specified in OpenSSL. There is a handy list located at: https://www.openssl.org/docs/apps/ciphers.html – k1DBLITZ Jul 27 '15 at 13:00
  • The [Toggle Cipher Suites](https://addons.mozilla.org/en-US/firefox/addon/toggle-cipher-suites/?src=cb-dl-updated) add-on for Firefox might be worth a look – iolsmit Dec 28 '16 at 17:36

1 Answers1

24

The easiest way to do what you're asking is simply to use openssl s_client to connect to the site with a restricted cipher list. And, in fact, the same approach will work for a number of tools - certainly with most programming or scripting languages (Python (as @terry-chia suggests), Perl, tcl, C...) and with browsers (some useful commentary here).

Let's walk through how you can do this with openssl.

Determine ciphers you want to try

You can use the tool sslscan to determine ciphers that a given site accepts or rejects:

$ sslscan www.google.com | grep Rejected | head -1
    Rejected  SSLv3  256 bits  ECDHE-ECDSA-AES256-SHA
$ sslscan www.google.com | grep Accepted | head -1
    Accepted  SSLv3  256 bits  ECDHE-RSA-AES256-SHA
$ 

And this has told us one cipher that www.google.com rejects and one that it accepts. Now we can test both with openssl s_client.

Testing a Rejected cipher

Simply use the '-cipher' argument to openssl to limit the cipher suite which your client will support to the one cipher you want to test. Here I pick the one that is marked Rejected by sslscan:

$ openssl s_client -cipher 'ECDHE-ECDSA-AES256-SHA' -connect www.google.com:443
CONNECTED(00000003)
140465833367232:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:741:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 127 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
$

We see a handshake failure near the top, and then we see "Cipher is (NONE)" which is a clear sign that the server was unwilling to agree with a client that was negotiating only the one cipher we specified. I presume this is what you mean when you say you want to connect with a specific SSL cipher and "view the output."

Testing an Accepted cipher

Now if we do the same with the cipher that we know the server supports, we see a full connection go through and we can type in HTTP commands. Below the output I'll list some things to have noticed:

$ openssl s_client -cipher 'ECDHE-RSA-AES256-SHA' -connect www.google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEdjCCA16gAwIBAgIIRYUpUVjSfHQwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
...
OEK3nH1sBk2Hy5ZBcyludHyUzqTHsXSjnIjwZNPpihVmFrs5I1Ma7iEj
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3750 bytes and written 277 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.1
    Cipher    : ECDHE-RSA-AES256-SHA
    Start Time: 1385691323
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
TRACE / HTTP/1.0

HTTP/1.0 405 Method Not Allowed
Content-Type: text/html; charset=UTF-8
Content-Length: 960
Date: Fri, 29 Nov 2013 02:15:31 GMT
Server: GFE/2.0
...

Note the following signs:

  1. We do not see the "handshake failed" error message
  2. Instead of "New, (NONE), Cipher is (NONE)", we see "New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA"
  3. We also see the same Cipher listed under the SSL-Session section.
  4. You can see where I typed in an HTTP command "TRACE / HTTP/1.0", and where Google responded "HTTP/1.0 405 Method Not Allowed". You would not be able to do this or see this if the cipher had been rejected, obviously; you can only talk to the HTTP server if the SSL connection was nailed up successfully.

Caveats

This is relatively easy in openssl command line. Doing it in code may be harder, depending on the language and the library used. Doing it in browsers may be painful, because such fine-grained control is not readily accessible - for example, if Chrome is using the OS for SSL on Windows, you need to figure out the registry keys used to manipulate SSL.

Another problem can be figuring out which cipher string you want to test. If you're investigating the report of another tool, as your question suggests, it's probably not describing the cipher problem it sees in terms of an OpenSSL cipher string. More than once I've ended up on the phone with support asking "What exactly are you referring to when you say 'weak cipher'?"

gowenfawr
  • 71,975
  • 17
  • 161
  • 198