Skip to content

Commit 4eb8374

Browse files
authored
Merge pull request #280 from jtesta/windows2019_fixes
Fix TLS 1.2 and 1.3 detection against Windows Server 2019
2 parents bc46606 + 6c8b15e commit 4eb8374

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

sslscan.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4901,6 +4901,70 @@ void bs_append_x448_pubkey(bs *b) {
49014901
}
49024902

49034903

4904+
/* Returns true if the ServerHello response contains TLSv1.3 in its supported_versions extension. */
4905+
unsigned int checkSupportedVersionsExtensionForTLS13(bs *server_hello) {
4906+
4907+
unsigned int handshake_record_len = bs_get_byte(server_hello, 3) << 8 | bs_get_byte(server_hello, 4);
4908+
4909+
/* The Server Hello *record* passed into this function can have multiple handshake protocols inside. We need to find the Server Hello *handshake protocol*, specifically, since that contains the extensions we need to parse. */
4910+
unsigned int handshake_record_ptr = 5;
4911+
while (handshake_record_ptr < handshake_record_len) {
4912+
unsigned int handshake_protocol_type = bs_get_byte(server_hello, handshake_record_ptr);
4913+
unsigned int handshake_protocol_len = bs_get_byte(server_hello, handshake_record_ptr + 1) << 16 | bs_get_byte(server_hello, handshake_record_ptr + 2) << 8 | bs_get_byte(server_hello, handshake_record_ptr + 3);
4914+
4915+
/* We found the Server Hello handshake protocol entry... */
4916+
if (handshake_protocol_type == 2) {
4917+
4918+
/* The session ID field is variable, so we need to find its length first so we can skip over it and get to the extensions section. */
4919+
unsigned int session_id_len = (unsigned int)bs_get_byte(server_hello, handshake_record_ptr + 5 + 32 + 1);
4920+
4921+
/* Get the length of all the extensions. */
4922+
unsigned int extensions_len_offset = handshake_record_ptr + 5 + 32 + 1 + session_id_len + 4;
4923+
unsigned int extensions_len = bs_get_byte(server_hello, extensions_len_offset) << 8 | bs_get_byte(server_hello, extensions_len_offset + 1);
4924+
4925+
/* Loop through each extension. */
4926+
unsigned int extensions_base_offset = extensions_len_offset + 2;
4927+
unsigned int extensions_offset = 0;
4928+
while (extensions_offset < extensions_len) {
4929+
4930+
/* Get the extension type and length. */
4931+
unsigned int extension_type = bs_get_byte(server_hello, extensions_base_offset + extensions_offset) << 8 | bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 1);
4932+
unsigned int extension_len = bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 2) << 8 | bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 3);
4933+
4934+
/* The supported_version extension is type 43. */
4935+
if (extension_type == 43) {
4936+
4937+
/* The length of this extension should be divisible by 2, since the TLS versions are each 2 bytes. */
4938+
if ((extension_len % 2) != 0) {
4939+
fprintf(stderr, "Error in %s: extension length for supported_versions is not even!: %u\n", __func__, extension_len);
4940+
return 0;
4941+
}
4942+
4943+
/* Loop through all the TLS versions in the supported_versions extension. Each version uses two bytes. */
4944+
for (int i = 0; i < extension_len; i += 2) {
4945+
unsigned int tls_high_byte = (unsigned int)bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 4 + i);
4946+
unsigned int tls_low_byte = (unsigned int)bs_get_byte(server_hello, extensions_base_offset + extensions_offset + 5 + i);
4947+
4948+
/* If we find TLS version 0x0304 in the supported_versions extension, then the server supports TLSv1.3! */
4949+
if ((tls_high_byte == 3) && (tls_low_byte == 4))
4950+
return 1;
4951+
}
4952+
}
4953+
4954+
extensions_offset += (4 + extension_len);
4955+
}
4956+
4957+
/* We already found the Server Hello protocol handshake and looked through all the extensions. If we reached here, then there's no point in continuing. */
4958+
return 0;
4959+
}
4960+
4961+
handshake_record_ptr += (4 + handshake_protocol_len);
4962+
}
4963+
4964+
return 0;
4965+
}
4966+
4967+
49044968
/* Returns true if a specific TLS version is supported by the server. */
49054969
unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version) {
49064970
bs *tls_extensions = NULL, *ciphersuite_list = NULL, *client_hello = NULL, *server_hello = NULL;
@@ -4992,6 +5056,10 @@ unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsig
49925056
if ((server_tls_version_high != 3) || (server_tls_version_low != expected_tls_version_low))
49935057
goto done;
49945058

5059+
/* TLSv1.3's ServerHello will be tagged as TLSv1.2 in the header, but will include v1.3 in the supported_versions extension. Some servers (like Windows Server 2019), when only supporting v1.2, will still respond with a ServerHello to our v1.3 Client Hello. So to eliminate false positives, we need to check the supported_versions extension and ensure v1.3 is listed there. */
5060+
if ((tls_version == TLSv1_3) && (!checkSupportedVersionsExtensionForTLS13(server_hello)))
5061+
goto done;
5062+
49955063
/* A valid Server Hello was returned, so this TLS version is supported. */
49965064
ret = true;
49975065

@@ -5052,6 +5120,9 @@ bs *makeCiphersuiteListAll(unsigned int tls_version) {
50525120
bs_append_ushort(ciphersuite_list, missing_ciphersuites[i].id);
50535121
}
50545122

5123+
/* Append TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff), otherwise some servers will reject the connection outright. */
5124+
bs_append_ushort(ciphersuite_list, 255);
5125+
50555126
return ciphersuite_list;
50565127
}
50575128

0 commit comments

Comments
 (0)