Skip to content

Commit 96a8890

Browse files
authored
Improved evaluation of servers that only support TLS 1.3 (#250)
1 parent b9655d3 commit 96a8890

34 files changed

+372
-250
lines changed

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/AlpacaProbe.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public AlpacaResult executeTest() {
4444
}
4545

4646
private TestResult isSupportingStrictSni() {
47-
Config tlsConfig = configSelector.getBaseConfig();
47+
Config tlsConfig = configSelector.getAnyWorkingBaseConfig();
4848
tlsConfig.setWorkflowTraceType(WorkflowTraceType.DYNAMIC_HELLO);
4949
tlsConfig.setAddServerNameIndicationExtension(true);
5050
tlsConfig.getDefaultClientConnection().setHostname("notarealtls-attackerhost.com");
@@ -59,7 +59,7 @@ private TestResult isSupportingStrictSni() {
5959
}
6060

6161
private TestResult isSupportingStrictAlpn() {
62-
Config tlsConfig = configSelector.getBaseConfig();
62+
Config tlsConfig = configSelector.getAnyWorkingBaseConfig();
6363
tlsConfig.setWorkflowTraceType(WorkflowTraceType.DYNAMIC_HELLO);
6464
tlsConfig.setAddServerNameIndicationExtension(true);
6565
tlsConfig.setAddAlpnExtension(true);

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/AlpnProbe.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public AlpnResult executeTest() {
3737
}
3838

3939
private List<String> getSupportedAlpnProtocols() {
40-
Config tlsConfig = configSelector.getBaseConfig();
40+
Config tlsConfig = configSelector.getAnyWorkingBaseConfig();
4141
tlsConfig.setWorkflowTraceType(WorkflowTraceType.DYNAMIC_HELLO);
4242
tlsConfig.setAddAlpnExtension(true);
4343

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CcaProbe.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public CcaResult executeTest() {
136136
@Override
137137
public boolean canBeExecuted(ServerReport report) {
138138
return (report.getResult(TlsAnalyzedProperty.REQUIRES_CCA) == TestResults.TRUE)
139-
&& (report.getVersionSuitePairs() != null);
139+
&& (report.getVersionSuitePairs() != null) && configSelector.foundWorkingConfig();
140140
}
141141

142142
@Override

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CcaRequiredProbe.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public CcaRequiredResult executeTest() {
5151

5252
@Override
5353
public boolean canBeExecuted(ServerReport report) {
54-
return (report.getResult(TlsAnalyzedProperty.SUPPORTS_CCA) == TestResults.TRUE);
54+
return (report.getResult(TlsAnalyzedProperty.SUPPORTS_CCA) == TestResults.TRUE
55+
&& configSelector.foundWorkingConfig());
5556
}
5657

5758
@Override

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CcaSupportProbe.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public CcaSupportResult executeTest() {
4343

4444
@Override
4545
public boolean canBeExecuted(ServerReport report) {
46-
return true;
46+
return configSelector.foundWorkingConfig();
4747
}
4848

4949
@Override

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CertificateProbe.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,19 @@ public CertificateResult executeTest() {
6464
ecdsaCertSigGroupsTls13 = new LinkedList<>();
6565

6666
Set<CertificateChain> certificates = new HashSet<>();
67-
if (scanForRsaCert) {
68-
certificates.addAll(getRsaCerts());
69-
}
70-
if (scanForDssCert) {
71-
certificates.addAll(getDssCerts());
72-
}
73-
if (scanForEcdsaCert) {
74-
certificates.addAll(getEcdsaCerts());
75-
}
76-
if (scanForGostCert) {
77-
certificates.addAll(getGostCert());
67+
if (configSelector.foundWorkingConfig()) {
68+
if (scanForRsaCert) {
69+
certificates.addAll(getRsaCerts());
70+
}
71+
if (scanForDssCert) {
72+
certificates.addAll(getDssCerts());
73+
}
74+
if (scanForEcdsaCert) {
75+
certificates.addAll(getEcdsaCerts());
76+
}
77+
if (scanForGostCert) {
78+
certificates.addAll(getGostCert());
79+
}
7880
}
7981
if (scanForTls13) {
8082
certificates.addAll(getTls13Certs());

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CertificateTransparencyProbe.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -108,32 +108,24 @@ private void getPrecertificateSCTs() {
108108
private void getTlsHandshakeSCTs() {
109109
supportsHandshakeSCTs = false;
110110

111-
Config tlsConfig = configSelector.getBaseConfig();
111+
Config tlsConfig = configSelector.getAnyWorkingBaseConfig();
112112
tlsConfig.setWorkflowTraceType(WorkflowTraceType.DYNAMIC_HELLO);
113113
tlsConfig.setAddSignedCertificateTimestampExtension(true);
114114
State state = new State(tlsConfig);
115115
executeState(state);
116116

117-
List<ExtensionType> supportedExtensions = new ArrayList<>(state.getTlsContext().getNegotiatedExtensionSet());
118-
if (supportedExtensions.contains(ExtensionType.SIGNED_CERTIFICATE_TIMESTAMP)) {
119-
if (WorkflowTraceUtil.didReceiveMessage(HandshakeMessageType.SERVER_HELLO, state.getWorkflowTrace())) {
120-
ServerHelloMessage serverHelloMessage = (ServerHelloMessage) WorkflowTraceUtil
121-
.getFirstReceivedMessage(HandshakeMessageType.SERVER_HELLO, state.getWorkflowTrace());
122-
if (serverHelloMessage != null
123-
&& serverHelloMessage.containsExtension(ExtensionType.SIGNED_CERTIFICATE_TIMESTAMP)) {
117+
SignedCertificateTimestampExtensionMessage sctExtensionMessage =
118+
getNegotiatedExtension(state.getWorkflowTrace(), SignedCertificateTimestampExtensionMessage.class);
119+
if (sctExtensionMessage != null) {
120+
byte[] encodedSctList = sctExtensionMessage.getSignedTimestamp().getOriginalValue();
124121

125-
SignedCertificateTimestampExtensionMessage sctExtensionMessage =
126-
serverHelloMessage.getExtension(SignedCertificateTimestampExtensionMessage.class);
127-
byte[] encodedSctList = sctExtensionMessage.getSignedTimestamp().getOriginalValue();
128-
129-
SignedCertificateTimestampListParser sctListParser =
130-
new SignedCertificateTimestampListParser(0, encodedSctList, serverCertChain, false);
131-
handshakeSctList = sctListParser.parse();
122+
SignedCertificateTimestampListParser sctListParser =
123+
new SignedCertificateTimestampListParser(0, encodedSctList, serverCertChain, false);
124+
handshakeSctList = sctListParser.parse();
132125

133-
supportsHandshakeSCTs = true;
134-
}
135-
}
126+
supportsHandshakeSCTs = true;
136127
}
128+
137129
}
138130

139131
/**

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CipherSuiteOrderProbe.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public CipherSuiteOrderResult executeTest() {
4444
}
4545

4646
public CipherSuite getSelectedCipherSuite(List<CipherSuite> toTestList) {
47-
Config tlsConfig = configSelector.getBaseConfig();
47+
Config tlsConfig = configSelector.getAnyWorkingBaseConfig();
4848
tlsConfig.setWorkflowTraceType(WorkflowTraceType.DYNAMIC_HELLO);
4949
tlsConfig.setDefaultClientSupportedCipherSuites(toTestList);
5050
configSelector.repairConfig(tlsConfig);

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/probe/CommonBugProbe.java

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import de.rub.nds.tlsattacker.core.constants.CipherSuite;
1818
import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType;
1919
import de.rub.nds.tlsattacker.core.constants.NamedGroup;
20+
import de.rub.nds.tlsattacker.core.constants.ProtocolVersion;
2021
import de.rub.nds.tlsattacker.core.constants.SignatureAndHashAlgorithm;
2122
import de.rub.nds.tlsattacker.core.protocol.message.ClientHelloMessage;
2223
import de.rub.nds.tlsattacker.core.protocol.message.HelloVerifyRequestMessage;
@@ -155,8 +156,10 @@ private TestResult getResult(Config config, WorkflowTrace trace, boolean checkFo
155156
try {
156157
State state = new State(config, trace);
157158
executeState(state);
158-
return checkForTrue == WorkflowTraceUtil.didReceiveMessage(HandshakeMessageType.SERVER_HELLO_DONE, trace)
159-
? TestResults.TRUE : TestResults.FALSE;
159+
return checkForTrue == (WorkflowTraceUtil.didReceiveMessage(HandshakeMessageType.SERVER_HELLO_DONE, trace)
160+
|| (state.getTlsContext().getSelectedProtocolVersion() == ProtocolVersion.TLS13
161+
&& (WorkflowTraceUtil.didReceiveMessage(HandshakeMessageType.FINISHED, trace)))) ? TestResults.TRUE
162+
: TestResults.FALSE;
160163
} catch (Exception e) {
161164
if (e.getCause() instanceof InterruptedException) {
162165
LOGGER.error("Timeout on " + getProbeName());
@@ -169,7 +172,7 @@ private TestResult getResult(Config config, WorkflowTrace trace, boolean checkFo
169172
}
170173

171174
private TestResult hasExtensionIntolerance() {
172-
Config config = configSelector.getBaseConfig();
175+
Config config = configSelector.getAnyWorkingBaseConfig();
173176
ClientHelloMessage message = new ClientHelloMessage(config);
174177
UnknownExtensionMessage extension = new UnknownExtensionMessage();
175178
extension.setTypeConfig(new byte[] { (byte) 3F, (byte) 3F });
@@ -180,7 +183,7 @@ private TestResult hasExtensionIntolerance() {
180183
}
181184

182185
private TestResult hasBigClientHelloIntolerance() {
183-
Config config = configSelector.getBaseConfig();
186+
Config config = configSelector.getAnyWorkingBaseConfig();
184187
config.setAddPaddingExtension(true);
185188
config.setDefaultPaddingExtensionBytes(new byte[14000]);
186189
ClientHelloMessage message = new ClientHelloMessage(config);
@@ -189,7 +192,7 @@ private TestResult hasBigClientHelloIntolerance() {
189192
}
190193

191194
private TestResult hasIgnoresSigHashAlgoOfferingBug() {
192-
Config config = configSelector.getBaseConfig();
195+
Config config = configSelector.getAnyWorkingBaseConfig();
193196
config.setAddSignatureAndHashAlgorithmsExtension(false);
194197
List<CipherSuite> suiteList = new LinkedList<>();
195198
for (CipherSuite suite : CipherSuite.getImplemented()) {
@@ -208,26 +211,33 @@ private TestResult hasIgnoresSigHashAlgoOfferingBug() {
208211
}
209212

210213
private TestResult hasIgnoresNamedGroupsOfferingBug() {
211-
Config config = configSelector.getBaseConfig();
212-
List<CipherSuite> suiteList = new LinkedList<>();
213-
for (CipherSuite suite : CipherSuite.getImplemented()) {
214-
if (suite.isEphemeral() && suite.name().contains("EC")) {
215-
suiteList.add(suite);
214+
if (configSelector.foundWorkingConfig()) {
215+
Config config = configSelector.getBaseConfig();
216+
List<CipherSuite> suiteList = new LinkedList<>();
217+
for (CipherSuite suite : CipherSuite.getImplemented()) {
218+
if (suite.isEphemeral() && suite.name().contains("EC")) {
219+
suiteList.add(suite);
220+
}
216221
}
222+
config.setDefaultClientSupportedCipherSuites(suiteList);
223+
config.setAddECPointFormatExtension(true);
224+
config.setAddEllipticCurveExtension(false);
225+
ClientHelloMessage message = new ClientHelloMessage(config);
226+
EllipticCurvesExtensionMessage extension = new EllipticCurvesExtensionMessage();
227+
extension.setSupportedGroups(Modifiable.explicit(new byte[] { (byte) 0xED, (byte) 0xED }));
228+
message.addExtension(extension);
229+
WorkflowTrace trace = getWorkflowTrace(config, message);
230+
return getResult(config, trace, true);
231+
} else {
232+
// servers choosing a different group in TLS 1.3 would send an
233+
// invalid HelloRetryRequest message which has a significantly
234+
// different meaning than the TLS 1.2 test case
235+
return TestResults.FALSE;
217236
}
218-
config.setDefaultClientSupportedCipherSuites(suiteList);
219-
config.setAddECPointFormatExtension(true);
220-
config.setAddEllipticCurveExtension(false);
221-
ClientHelloMessage message = new ClientHelloMessage(config);
222-
EllipticCurvesExtensionMessage extension = new EllipticCurvesExtensionMessage();
223-
extension.setSupportedGroups(Modifiable.explicit(new byte[] { (byte) 0xED, (byte) 0xED }));
224-
message.addExtension(extension);
225-
WorkflowTrace trace = getWorkflowTrace(config, message);
226-
return getResult(config, trace, true);
227237
}
228238

229239
private void adjustCipherSuiteSelectionBugs() {
230-
Config config = configSelector.getBaseConfig();
240+
Config config = configSelector.getAnyWorkingBaseConfig();
231241
ClientHelloMessage message = new ClientHelloMessage(config);
232242
message.setCipherSuites(Modifiable.explicit(new byte[] { (byte) 0xEE, (byte) 0xCC }));
233243
WorkflowTrace trace = getWorkflowTrace(config, message);
@@ -255,7 +265,7 @@ private void adjustCipherSuiteSelectionBugs() {
255265
}
256266

257267
private TestResult hasSignatureAndHashAlgorithmIntolerance() {
258-
Config config = configSelector.getBaseConfig();
268+
Config config = configSelector.getAnyWorkingBaseConfig();
259269
config.setAddSignatureAndHashAlgorithmsExtension(false);
260270
List<CipherSuite> suiteList = new LinkedList<>();
261271
for (CipherSuite suite : CipherSuite.getImplemented()) {
@@ -274,7 +284,7 @@ private TestResult hasSignatureAndHashAlgorithmIntolerance() {
274284
}
275285

276286
private TestResult hasNamedGroupIntolerance() {
277-
Config config = configSelector.getBaseConfig();
287+
Config config = configSelector.getAnyWorkingBaseConfig();
278288
List<CipherSuite> suiteList = new LinkedList<>();
279289
for (CipherSuite suite : CipherSuite.getImplemented()) {
280290
if (suite.isEphemeral() && suite.name().contains("EC")) {
@@ -293,25 +303,30 @@ private TestResult hasNamedGroupIntolerance() {
293303
}
294304

295305
private TestResult hasOnlySecondCipherSuiteByteEvaluatedBug() {
296-
Config config = configSelector.getBaseConfig();
297-
ClientHelloMessage message = new ClientHelloMessage(config);
298-
ByteArrayOutputStream stream = new ByteArrayOutputStream();
299-
for (CipherSuite suite : CipherSuite.values()) {
300-
if (suite.getByteValue()[0] == 0x00) {
301-
try {
302-
stream.write(new byte[] { (byte) 0xDF, suite.getByteValue()[1] });
303-
} catch (IOException ex) {
304-
LOGGER.debug(ex);
306+
if (configSelector.foundWorkingConfig()) {
307+
Config config = configSelector.getBaseConfig();
308+
ClientHelloMessage message = new ClientHelloMessage(config);
309+
ByteArrayOutputStream stream = new ByteArrayOutputStream();
310+
for (CipherSuite suite : CipherSuite.values()) {
311+
if (suite.getByteValue()[0] == 0x00) {
312+
try {
313+
stream.write(new byte[] { (byte) 0xDF, suite.getByteValue()[1] });
314+
} catch (IOException ex) {
315+
LOGGER.debug(ex);
316+
}
305317
}
306318
}
319+
message.setCipherSuites(Modifiable.explicit(stream.toByteArray()));
320+
WorkflowTrace trace = getWorkflowTrace(config, message);
321+
return getResult(config, trace, true);
322+
} else {
323+
// not applicable to TLS 1.3-only servers due to 0x13XX structure
324+
return TestResults.FALSE;
307325
}
308-
message.setCipherSuites(Modifiable.explicit(stream.toByteArray()));
309-
WorkflowTrace trace = getWorkflowTrace(config, message);
310-
return getResult(config, trace, true);
311326
}
312327

313328
private TestResult hasEmptyLastExtensionIntolerance() {
314-
Config config = configSelector.getBaseConfig();
329+
Config config = configSelector.getAnyWorkingBaseConfig();
315330
ClientHelloMessage message = new ClientHelloMessage(config);
316331
ExtendedMasterSecretExtensionMessage extension = new ExtendedMasterSecretExtensionMessage();
317332
message.getExtensions().add(extension);
@@ -320,44 +335,52 @@ private TestResult hasEmptyLastExtensionIntolerance() {
320335
}
321336

322337
private TestResult hasVersionIntolerance() {
323-
Config config = configSelector.getBaseConfig();
338+
Config config = configSelector.getAnyWorkingBaseConfig();
324339
ClientHelloMessage message = new ClientHelloMessage(config);
325340
message.setProtocolVersion(Modifiable.explicit(new byte[] { 0x03, 0x05 }));
326341
WorkflowTrace trace = getWorkflowTrace(config, message);
327342
return getResult(config, trace, false);
328343
}
329344

330345
private TestResult hasCompressionIntolerance() {
331-
Config config = configSelector.getBaseConfig();
332-
ClientHelloMessage message = new ClientHelloMessage(config);
333-
message.setCompressions(new byte[] { (byte) 0xFF, (byte) 0x00 });
334-
WorkflowTrace trace = getWorkflowTrace(config, message);
335-
return getResult(config, trace, false);
346+
if (configSelector.foundWorkingConfig()) {
347+
Config config = configSelector.getBaseConfig();
348+
ClientHelloMessage message = new ClientHelloMessage(config);
349+
message.setCompressions(new byte[] { (byte) 0xFF, (byte) 0x00 });
350+
WorkflowTrace trace = getWorkflowTrace(config, message);
351+
return getResult(config, trace, false);
352+
} else {
353+
// At this point, we must have only found a working TLS 1.3 config
354+
// and RFC 8446 states:
355+
// If a TLS 1.3 ClientHello is received with any other value in this
356+
// field, the server MUST abort the handshake with an
357+
// "illegal_parameter" alert.
358+
return TestResults.FALSE;
359+
}
336360
}
337361

338362
private TestResult hasCipherSuiteLengthIntolerance512() {
339-
Config config = configSelector.getBaseConfig();
363+
Config config = configSelector.getAnyWorkingBaseConfig();
340364
List<CipherSuite> toTestList = new LinkedList<>();
341365
toTestList.addAll(Arrays.asList(CipherSuite.values()));
342366
toTestList.remove(CipherSuite.TLS_FALLBACK_SCSV);
343367
toTestList.remove(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
344368
config.setDefaultClientSupportedCipherSuites(toTestList);
345-
configSelector.repairConfig(config);
346369
ClientHelloMessage message = new ClientHelloMessage(config);
347370
WorkflowTrace trace = getWorkflowTrace(config, message);
348371
return getResult(config, trace, false);
349372
}
350373

351374
private TestResult hasCipherSuiteIntolerance() {
352-
Config config = configSelector.getBaseConfig();
375+
Config config = configSelector.getAnyWorkingBaseConfig();
353376
ClientHelloMessage message = new ClientHelloMessage(config);
354377
message.setCipherSuites(Modifiable.insert(new byte[] { (byte) 0xCF, (byte) 0xAA }, 1));
355378
WorkflowTrace trace = getWorkflowTrace(config, message);
356379
return getResult(config, trace, false);
357380
}
358381

359382
private TestResult hasAlpnIntolerance() {
360-
Config config = configSelector.getBaseConfig();
383+
Config config = configSelector.getAnyWorkingBaseConfig();
361384
config.setAddAlpnExtension(true);
362385
List<String> alpnProtocols = new LinkedList<>();
363386
for (AlpnProtocol protocol : AlpnProtocol.values()) {
@@ -371,7 +394,7 @@ private TestResult hasAlpnIntolerance() {
371394
}
372395

373396
private TestResult hasClientHelloLengthIntolerance() {
374-
Config config = configSelector.getBaseConfig();
397+
Config config = configSelector.getAnyWorkingBaseConfig();
375398
config.setAddPaddingExtension(true);
376399
ClientHelloMessage message = new ClientHelloMessage(config);
377400
int newLength = 512 - 4 - getClientHelloLength(message, config);
@@ -385,7 +408,7 @@ private TestResult hasClientHelloLengthIntolerance() {
385408
}
386409

387410
private TestResult hasGreaseCipherSuiteIntolerance() {
388-
Config config = configSelector.getBaseConfig();
411+
Config config = configSelector.getAnyWorkingBaseConfig();
389412
Arrays.asList(CipherSuite.values()).stream().filter(cipherSuite -> cipherSuite.isGrease())
390413
.forEach(greaseCipher -> config.getDefaultClientSupportedCipherSuites().add(greaseCipher));
391414
ClientHelloMessage message = new ClientHelloMessage(config);
@@ -394,7 +417,7 @@ private TestResult hasGreaseCipherSuiteIntolerance() {
394417
}
395418

396419
private TestResult hasGreaseNamedGroupIntolerance() {
397-
Config config = configSelector.getBaseConfig();
420+
Config config = configSelector.getAnyWorkingBaseConfig();
398421
Arrays.asList(NamedGroup.values()).stream().filter(group -> group.isGrease())
399422
.forEach(greaseGroup -> config.getDefaultClientNamedGroups().add(greaseGroup));
400423
ClientHelloMessage message = new ClientHelloMessage(config);
@@ -403,7 +426,7 @@ private TestResult hasGreaseNamedGroupIntolerance() {
403426
}
404427

405428
private TestResult hasGreaseSignatureAndHashAlgorithmIntolerance() {
406-
Config config = configSelector.getBaseConfig();
429+
Config config = configSelector.getAnyWorkingBaseConfig();
407430
Arrays.asList(SignatureAndHashAlgorithm.values()).stream().filter(algorithm -> algorithm.isGrease()).forEach(
408431
greaseAlgorithm -> config.getDefaultClientSupportedSignatureAndHashAlgorithms().add(greaseAlgorithm));
409432
ClientHelloMessage message = new ClientHelloMessage(config);

0 commit comments

Comments
 (0)