2.16 Testing Renegotiation
In TLS, renegotiation is a failed feature that was responsible for several protocol weaknesses, some of which are quite easy to exploit. TLS 1.3 no longer supports renegotiation, but there are still older servers out there that support it with earlier protocol revisions.
The s_client
tool has a couple of features that can assist you with manual testing of renegotiation. First of all, when you connect, the tool will report if the remote server supports secure renegotiation. This is because a server that supports secure renegotiation indicates its support for it via a special TLS extension that is exchanged during the handshake phase. When support is available, the output may look like this:
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
[...]
If secure renegotiation is not supported, the output will be slightly different:
Secure Renegotiation IS NOT supported
Because TLS 1.3 doesn’t support renegotiation, the s_client
tool will always give a negative answer if this protocol version is negotiated. To ensure reliable results, use the -no_tls1_3
switch to force negotiation of an earlier protocol version.
Even if the server indicates support for secure renegotiation, you may wish to test whether it also allows clients to initiate renegotiation. Client-initiated renegotiation is a protocol feature that doesn’t serve any purpose in practice (because the server can always initiate renegotiation when it is needed) and makes the server more susceptible to denial of service attacks.
To initiate renegotiation, after the TLS handshake is complete, type an R
character on a line by itself. For example, assuming we’re talking to an HTTP server, you can type the first line of a request, initiate renegotiation, and then finish the request. Here’s what that looks like when talking to a web server that supports client-initiated renegotiation:
GET / HTTP/1.0
R
RENEGOTIATING
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Extended Validation Server CA
verify return:1
depth=0 businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = California, serialNumber = C2543436, C = US, ST = California, L = Mountain View, O = Mozilla Foundation, OU = Cloud Services, CN = addons.mozilla.org
verify return:1
Host: addons.mozilla.org
HTTP/1.1 301 Moved Permanently
Content-Type: text/plain; charset=utf-8
Date: Mon, 31 Aug 2020 12:40:49 GMT
Location: /en-US/firefox/
Strict-Transport-Security: max-age=31536000
Content-Length: 49
Connection: Close
Moved Permanently. Redirecting to /en-US/firefox/closed
When renegotiation is taking place, the server will send its certificates to the client again. You can see the verification of the certificate chain in the output. The next line after that continues with the Host
request header. Seeing the web server’s response is the proof that renegotiation is supported. Because of the various ways the renegotiation issue was addressed in various versions of SSL/TLS libraries, servers that do not support renegotiation may break the connection or may keep it open but refuse to continue to talk over it (which usually results in a timeout).
A server that does not support renegotiation will flatly refuse the second handshake on the connection:
HEAD / HTTP/1.0
R
RENEGOTIATING
140003560109728:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:592:
At the time of writing, the default behavior for OpenSSL is to connect to servers that don’t support secure renegotiation; it will also accept both secure and insecure renegotiation, opting for whatever the server is able to do. If renegotiation is successful with a server that doesn’t support secure renegotiation, you will know that the server supports insecure client-initiated renegotiation.
The most reliable way to test for insecure renegotiation is to use the method described in this section, but with a version of OpenSSL that was released before the discovery of insecure renegotiation (e.g., 0.9.8k). I mention this because there is a small number of servers that support both secure and insecure renegotiation. This vulnerability is difficult to detect with modern versions of OpenSSL, which always prefer the secure option.