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