Skip to content

Commit c5defff

Browse files
authored
Merge pull request #224 from tls-attacker/newDtlsProbes
Added new tests for dtls
2 parents bdcab03 + ed9d4e6 commit c5defff

26 files changed

+752
-117
lines changed

TLS-Scanner-Core/src/main/java/de/rub/nds/tlsscanner/core/constants/TlsAnalyzedProperty.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public enum TlsAnalyzedProperty implements AnalyzedProperty {
4242
SUPPORTS_TLS_1_3_DRAFT_26(TlsAnalyzedPropertyCategory.VERSIONS),
4343
SUPPORTS_TLS_1_3_DRAFT_27(TlsAnalyzedPropertyCategory.VERSIONS),
4444
SUPPORTS_TLS_1_3_DRAFT_28(TlsAnalyzedPropertyCategory.VERSIONS),
45+
SUPPORTS_DTLS_1_0_DRAFT(TlsAnalyzedPropertyCategory.VERSIONS),
4546
SUPPORTS_DTLS_1_0(TlsAnalyzedPropertyCategory.VERSIONS),
4647
SUPPORTS_DTLS_1_2(TlsAnalyzedPropertyCategory.VERSIONS),
4748
SUPPORTS_DTLS_1_3(TlsAnalyzedPropertyCategory.VERSIONS),
@@ -279,9 +280,14 @@ public enum TlsAnalyzedProperty implements AnalyzedProperty {
279280
* DTLS
280281
*/
281282
SUPPORTS_DTLS_FRAGMENTATION(TlsAnalyzedPropertyCategory.QUIRKS),
283+
DTLS_FRAGMENTATION_REQUIRES_EXTENSION(TlsAnalyzedPropertyCategory.QUIRKS),
284+
SUPPORTS_DTLS_FRAGMENTATION_WITH_INDIVIDUAL_PACKETS(TlsAnalyzedPropertyCategory.QUIRKS),
285+
DTLS_FRAGMENTATION_WITH_INDIVIDUAL_PACKETS_REQUIRES_EXTENSION(TlsAnalyzedPropertyCategory.QUIRKS),
282286
SUPPORTS_REORDERING(TlsAnalyzedPropertyCategory.QUIRKS),
283287
HAS_HVR_RETRANSMISSIONS(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
284288
HAS_COOKIE_CHECKS(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
289+
USES_IP_ADDRESS_FOR_COOKIE(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
290+
USES_PORT_FOR_COOKIE(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
285291
USES_VERSION_FOR_COOKIE(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
286292
USES_RANDOM_FOR_COOKIE(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),
287293
USES_SESSION_ID_FOR_COOKIE(TlsAnalyzedPropertyCategory.HELLO_VERIFY_REQUEST),

TLS-Scanner-Core/src/main/java/de/rub/nds/tlsscanner/core/constants/TlsProbeType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,14 @@ public enum TlsProbeType implements ProbeType {
5252
DIRECT_RACCOON("Direct RACCOON"),
5353
EC_POINT_FORMAT("EC point formats"),
5454
RACCOON_ATTACK("RACCOON attack"),
55+
DTLS_IP_ADDRESS_IN_COOKIE("DTLS ip address in cookie"),
5556
DTLS_HELLO_VERIFY_REQUEST("DTLS hello verify request"),
5657
DTLS_COMMON_BUGS("DTLS common bugs"),
57-
DTLS_FEATURES("DTLS features"),
58+
DTLS_REORDERING("DTLS reordering"),
59+
DTLS_FRAGMENTATION("DTLS fragmentation"),
5860
DTLS_MESSAGE_SEQUENCE_NUMBER("DTLS message sequence number"),
5961
DTLS_RETRANSMISSIONS("DTLS retransmissions"),
62+
DTLS_APPLICATION_FINGERPRINT("DTLS application fingerprint"),
6063
HTTP_FALSE_START("HTTP false start"),
6164
HELLO_RETRY("Hello retry"),
6265
CROSS_PROTOCOL_ALPACA("Alpaca attack"),

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/constants/ApplicationProtocol.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
package de.rub.nds.tlsscanner.serverscanner.constants;
1111

1212
public enum ApplicationProtocol {
13+
ECHO,
14+
STUN,
15+
TURN,
16+
VPN_CITRIX,
17+
VPN_FORTINET,
18+
COAP,
1319
HTTP,
1420
FTP,
1521
SMTP,

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/execution/TlsServerScanner.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,13 @@
6363
import de.rub.nds.tlsscanner.serverscanner.probe.ConnectionClosingProbe;
6464
import de.rub.nds.tlsscanner.serverscanner.probe.DirectRaccoonProbe;
6565
import de.rub.nds.tlsscanner.serverscanner.probe.DrownProbe;
66+
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsApplicationFingerprintProbe;
6667
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsBugsProbe;
67-
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsFeaturesProbe;
68+
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsFragmentationProbe;
6869
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsHelloVerifyRequestProbe;
70+
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsIpAddressInCookieProbe;
6971
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsMessageSequenceProbe;
72+
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsReorderingProbe;
7073
import de.rub.nds.tlsscanner.serverscanner.probe.DtlsRetransmissionsProbe;
7174
import de.rub.nds.tlsscanner.serverscanner.probe.ECPointFormatProbe;
7275
import de.rub.nds.tlsscanner.serverscanner.probe.EarlyCcsProbe;
@@ -215,11 +218,14 @@ protected void fillProbeLists() {
215218
afterList.add(new RaccoonAttackAfterProbe());
216219
afterList.add(new CertificateSignatureAndHashAlgorithmAfterProbe());
217220
if (config.getDtlsDelegate().isDTLS()) {
218-
addProbeToProbeList(new DtlsFeaturesProbe(configSelector, parallelExecutor));
221+
addProbeToProbeList(new DtlsReorderingProbe(configSelector, parallelExecutor));
222+
addProbeToProbeList(new DtlsFragmentationProbe(configSelector, parallelExecutor));
219223
addProbeToProbeList(new DtlsHelloVerifyRequestProbe(configSelector, parallelExecutor));
220224
addProbeToProbeList(new DtlsBugsProbe(configSelector, parallelExecutor));
221225
addProbeToProbeList(new DtlsMessageSequenceProbe(configSelector, parallelExecutor));
222226
addProbeToProbeList(new DtlsRetransmissionsProbe(configSelector, parallelExecutor));
227+
addProbeToProbeList(new DtlsApplicationFingerprintProbe(configSelector, parallelExecutor));
228+
addProbeToProbeList(new DtlsIpAddressInCookieProbe(configSelector, parallelExecutor), false);
223229
afterList.add(new DtlsRetransmissionAfterProbe());
224230
afterList.add(new DestinationPortAfterProbe());
225231
} else {

TLS-Server-Scanner/src/main/java/de/rub/nds/tlsscanner/serverscanner/passive/DestinationPortExtractor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
import de.rub.nds.scanner.core.passive.StatExtractor;
1313
import de.rub.nds.tlsattacker.core.state.State;
14+
import de.rub.nds.tlsattacker.transport.TransportHandler;
15+
import de.rub.nds.tlsattacker.transport.udp.ClientUdpTransportHandler;
16+
import de.rub.nds.tlsattacker.transport.udp.ServerUdpTransportHandler;
1417
import de.rub.nds.tlsattacker.transport.udp.UdpTransportHandler;
1518
import de.rub.nds.tlsscanner.core.passive.TrackableValueType;
1619

@@ -22,8 +25,9 @@ public DestinationPortExtractor() {
2225

2326
@Override
2427
public void extract(State state) {
25-
if (state.getTlsContext().getTransportHandler() instanceof UdpTransportHandler) {
26-
int port = ((UdpTransportHandler) state.getTlsContext().getTransportHandler()).getDstPort();
28+
TransportHandler handler = state.getTlsContext().getTransportHandler();
29+
if (handler instanceof ClientUdpTransportHandler || handler instanceof ServerUdpTransportHandler) {
30+
int port = ((UdpTransportHandler) handler).getDstPort();
2731
if (port != -1) {
2832
put(port);
2933
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/**
2+
* TLS-Server-Scanner - A TLS configuration and analysis tool based on TLS-Attacker
3+
*
4+
* Copyright 2017-2022 Ruhr University Bochum, Paderborn University, Hackmanit GmbH
5+
*
6+
* Licensed under Apache License, Version 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0.txt
8+
*/
9+
10+
package de.rub.nds.tlsscanner.serverscanner.probe;
11+
12+
import com.google.common.primitives.Bytes;
13+
import de.rub.nds.modifiablevariable.util.ArrayConverter;
14+
import de.rub.nds.modifiablevariable.util.Modifiable;
15+
import de.rub.nds.scanner.core.constants.TestResult;
16+
import de.rub.nds.scanner.core.constants.TestResults;
17+
import de.rub.nds.tlsattacker.core.config.Config;
18+
import de.rub.nds.tlsattacker.core.constants.RunningModeType;
19+
import de.rub.nds.tlsattacker.core.protocol.ProtocolMessage;
20+
import de.rub.nds.tlsattacker.core.protocol.message.ApplicationMessage;
21+
import de.rub.nds.tlsattacker.core.record.AbstractRecord;
22+
import de.rub.nds.tlsattacker.core.record.Record;
23+
import de.rub.nds.tlsattacker.core.state.State;
24+
import de.rub.nds.tlsattacker.core.workflow.ParallelExecutor;
25+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTrace;
26+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceUtil;
27+
import de.rub.nds.tlsattacker.core.workflow.action.ReceiveAction;
28+
import de.rub.nds.tlsattacker.core.workflow.action.SendAction;
29+
import de.rub.nds.tlsattacker.core.workflow.factory.WorkflowConfigurationFactory;
30+
import de.rub.nds.tlsattacker.core.workflow.factory.WorkflowTraceType;
31+
import de.rub.nds.tlsscanner.core.constants.TlsProbeType;
32+
import de.rub.nds.tlsscanner.serverscanner.constants.ApplicationProtocol;
33+
import de.rub.nds.tlsscanner.serverscanner.probe.result.DtlsApplicationFingerprintResult;
34+
import de.rub.nds.tlsscanner.serverscanner.report.ServerReport;
35+
import de.rub.nds.tlsscanner.serverscanner.selector.ConfigSelector;
36+
import java.io.ByteArrayOutputStream;
37+
import java.io.IOException;
38+
import java.util.ArrayList;
39+
import java.util.Arrays;
40+
import java.util.List;
41+
42+
public class DtlsApplicationFingerprintProbe
43+
extends TlsServerProbe<ConfigSelector, ServerReport, DtlsApplicationFingerprintResult> {
44+
45+
private List<ApplicationProtocol> supportedApplications;
46+
private TestResult isAcceptingUnencryptedAppData;
47+
48+
public DtlsApplicationFingerprintProbe(ConfigSelector configSelector, ParallelExecutor parallelExecutor) {
49+
super(parallelExecutor, TlsProbeType.DTLS_APPLICATION_FINGERPRINT, configSelector);
50+
}
51+
52+
@Override
53+
public DtlsApplicationFingerprintResult executeTest() {
54+
supportedApplications = new ArrayList<>();
55+
isAcceptingUnencryptedAppData = TestResults.NOT_TESTED_YET;
56+
if (!isEchoServer()) {
57+
isVpnSupported();
58+
isStunSupported();
59+
isTurnSupported();
60+
isCoapSupported();
61+
}
62+
return new DtlsApplicationFingerprintResult(supportedApplications, isAcceptingUnencryptedAppData);
63+
}
64+
65+
private boolean isEchoServer() {
66+
byte[] appData = ArrayConverter.hexStringToByteArray("9988776655443322110000112233445566778899");
67+
byte[] data = isProtocolSupported(appData);
68+
if (Arrays.equals(data, appData)) {
69+
supportedApplications.add(ApplicationProtocol.ECHO);
70+
return true;
71+
}
72+
return false;
73+
}
74+
75+
private void isVpnSupported() {
76+
byte[] length = ArrayConverter.hexStringToByteArray("0118");
77+
byte[] string = ArrayConverter.hexStringToByteArray("0047467479706500636c7468656c6c6f005356504e434f4f4b494500");
78+
byte[] cookie = ArrayConverter.hexStringToByteArray("34626a384f64735a486a6f644e736859512b59");
79+
byte[] appData = ArrayConverter.concatenate(length, string, cookie);
80+
byte[] data = isProtocolSupported(appData);
81+
byte[] fortinetHandshakeFail =
82+
ArrayConverter.hexStringToByteArray("00214746747970650073767268656C6C6F0068616E647368616B65006661696C00");
83+
byte[] fortinetHandshakeOk =
84+
ArrayConverter.hexStringToByteArray("001f4746747970650073767268656C6C6F0068616E647368616B65006f6b00");
85+
byte[] citrixResponse = ArrayConverter.hexStringToByteArray("FF0000010000000000000000000000000000000001");
86+
if (Bytes.indexOf(data, fortinetHandshakeFail) != -1) {
87+
supportedApplications.add(ApplicationProtocol.VPN_FORTINET);
88+
isAcceptingUnencryptedAppData(appData);
89+
} else if (Bytes.indexOf(data, fortinetHandshakeOk) != -1) {
90+
supportedApplications.add(ApplicationProtocol.VPN_FORTINET);
91+
isAcceptingUnencryptedAppData(appData);
92+
} else if (Bytes.indexOf(data, citrixResponse) != -1) {
93+
supportedApplications.add(ApplicationProtocol.VPN_CITRIX);
94+
isAcceptingUnencryptedAppData(appData);
95+
}
96+
}
97+
98+
private void isStunSupported() {
99+
byte[] type = ArrayConverter.hexStringToByteArray("0001");
100+
byte[] length = ArrayConverter.hexStringToByteArray("0000");
101+
byte[] cookie = ArrayConverter.hexStringToByteArray("2112a442");
102+
byte[] transactionId = ArrayConverter.hexStringToByteArray("112233445566778899001122");
103+
byte[] appData = ArrayConverter.concatenate(type, length, cookie, transactionId);
104+
byte[] data = isProtocolSupported(appData);
105+
if (Bytes.indexOf(data, transactionId) != -1) {
106+
supportedApplications.add(ApplicationProtocol.STUN);
107+
isAcceptingUnencryptedAppData(appData);
108+
}
109+
}
110+
111+
private void isTurnSupported() {
112+
byte[] type = ArrayConverter.hexStringToByteArray("0003");
113+
byte[] length = ArrayConverter.hexStringToByteArray("0008");
114+
byte[] cookie = ArrayConverter.hexStringToByteArray("2112a442");
115+
byte[] transactionId = ArrayConverter.hexStringToByteArray("112233445566778899001122");
116+
byte[] requestedTransport = ArrayConverter.hexStringToByteArray("0019000411000000");
117+
byte[] appData = ArrayConverter.concatenate(type, length, cookie, transactionId, requestedTransport);
118+
byte[] data = isProtocolSupported(appData);
119+
if (Bytes.indexOf(data, transactionId) != -1) {
120+
supportedApplications.add(ApplicationProtocol.TURN);
121+
isAcceptingUnencryptedAppData(appData);
122+
}
123+
}
124+
125+
private void isCoapSupported() {
126+
byte[] header = ArrayConverter.hexStringToByteArray("4000");
127+
byte[] messageId = ArrayConverter.hexStringToByteArray("9812");
128+
byte[] appData = ArrayConverter.concatenate(header, messageId);
129+
byte[] data = isProtocolSupported(appData);
130+
if (Bytes.indexOf(data, messageId) != -1) {
131+
supportedApplications.add(ApplicationProtocol.COAP);
132+
isAcceptingUnencryptedAppData(appData);
133+
}
134+
}
135+
136+
private byte[] isProtocolSupported(byte[] data) {
137+
Config config = configSelector.getBaseConfig();
138+
WorkflowTrace trace = new WorkflowConfigurationFactory(config)
139+
.createWorkflowTrace(WorkflowTraceType.DYNAMIC_HANDSHAKE, RunningModeType.CLIENT);
140+
trace.addTlsAction(new SendAction(new ApplicationMessage(config, data)));
141+
ReceiveAction receiveAction = new ReceiveAction(new ApplicationMessage());
142+
trace.addTlsAction(receiveAction);
143+
State state = new State(config, trace);
144+
executeState(state);
145+
if (receiveAction.getReceivedRecords() != null && !receiveAction.getReceivedRecords().isEmpty()) {
146+
ByteArrayOutputStream receivedAppData = new ByteArrayOutputStream();
147+
try {
148+
for (AbstractRecord record : receiveAction.getReceivedRecords()) {
149+
receivedAppData.write(record.getCleanProtocolMessageBytes().getValue());
150+
}
151+
} catch (IOException ex) {
152+
LOGGER.error("Could not write cleanProtocolMessageBytes to receivedAppData");
153+
}
154+
return receivedAppData.toByteArray();
155+
} else {
156+
return new byte[0];
157+
}
158+
}
159+
160+
private void isAcceptingUnencryptedAppData(byte[] data) {
161+
Config config = configSelector.getBaseConfig();
162+
WorkflowTrace trace = new WorkflowConfigurationFactory(config)
163+
.createWorkflowTrace(WorkflowTraceType.DYNAMIC_HANDSHAKE, RunningModeType.CLIENT);
164+
trace.addTlsAction(new SendAction(new ApplicationMessage(config, data)));
165+
trace.addTlsAction(new ReceiveAction(new ApplicationMessage()));
166+
State state = new State(config, trace);
167+
executeState(state);
168+
ProtocolMessage receivedMessage = WorkflowTraceUtil.getLastReceivedMessage(state.getWorkflowTrace());
169+
170+
trace = new WorkflowConfigurationFactory(config).createWorkflowTrace(WorkflowTraceType.DYNAMIC_HANDSHAKE,
171+
RunningModeType.CLIENT);
172+
SendAction sendAction = new SendAction(new ApplicationMessage(config, data));
173+
Record record = new Record(config);
174+
record.setEpoch(Modifiable.explicit(0));
175+
sendAction.setRecords(record);
176+
trace.addTlsAction(sendAction);
177+
trace.addTlsAction(new ReceiveAction(new ApplicationMessage()));
178+
state = new State(config, trace);
179+
executeState(state);
180+
ProtocolMessage receivedMessageModified = WorkflowTraceUtil.getLastReceivedMessage(state.getWorkflowTrace());
181+
if (receivedMessage != null && receivedMessageModified != null && receivedMessage.getCompleteResultingMessage()
182+
.equals(receivedMessageModified.getCompleteResultingMessage())) {
183+
isAcceptingUnencryptedAppData = TestResults.TRUE;
184+
}
185+
}
186+
187+
@Override
188+
public boolean canBeExecuted(ServerReport report) {
189+
return true;
190+
}
191+
192+
@Override
193+
public DtlsApplicationFingerprintResult getCouldNotExecuteResult() {
194+
return new DtlsApplicationFingerprintResult(null, TestResults.COULD_NOT_TEST);
195+
}
196+
197+
@Override
198+
public void adjustConfig(ServerReport report) {
199+
}
200+
201+
}

0 commit comments

Comments
 (0)