Skip to content

Commit bb65442

Browse files
authored
Merge pull request #382 from RUB-NDS/DeepCopyBuffers
Deep copy buffers & 0RTT MITM replay trace
2 parents 74885a5 + 1a0b66d commit bb65442

File tree

9 files changed

+356
-3
lines changed

9 files changed

+356
-3
lines changed

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/extension/PSK/PSKBinder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
1313
import de.rub.nds.modifiablevariable.integer.ModifiableInteger;
1414
import de.rub.nds.tlsattacker.core.constants.CipherSuite;
15+
import java.io.Serializable;
1516

16-
public class PSKBinder {
17+
public class PSKBinder implements Serializable {
1718

1819
private CipherSuite binderCipherConfig;
1920

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/message/extension/PSK/PSKIdentity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
1313
import de.rub.nds.modifiablevariable.integer.ModifiableInteger;
1414
import de.rub.nds.modifiablevariable.util.ByteArrayAdapter;
15+
import java.io.Serializable;
1516
import javax.xml.bind.annotation.XmlAccessType;
1617
import javax.xml.bind.annotation.XmlAccessorType;
1718
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
1819

1920
@XmlAccessorType(XmlAccessType.FIELD)
20-
public class PSKIdentity {
21+
public class PSKIdentity implements Serializable {
2122

2223
@XmlJavaTypeAdapter(ByteArrayAdapter.class)
2324
private byte[] identityConfig;

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/workflow/WorkflowTrace.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public class WorkflowTrace implements Serializable {
6969
@XmlElement(type = CopyContextFieldAction.class, name = "CopyContextField"),
7070
@XmlElement(type = CopyServerRandomAction.class, name = "CopyServerRandom"),
7171
@XmlElement(type = DeactivateEncryptionAction.class, name = "DeactivateEncryption"),
72+
@XmlElement(type = DeepCopyBufferedMessagesAction.class, name = "DeepCopyBufferedMessages"),
73+
@XmlElement(type = DeepCopyBufferedRecordsAction.class, name = "DeepCopyBufferedRecords"),
74+
@XmlElement(type = DeepCopyBuffersAction.class, name = "DeepCopyBuffers"),
7275
@XmlElement(type = FindReceivedProtocolMessageAction.class, name = "FindReceivedProtocolMessage"),
7376
@XmlElement(type = ForwardAction.class, name = "Forward"),
7477
@XmlElement(type = ForwardRecordsAction.class, name = "ForwardRecords"),
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2017 Ruhr University Bochum / Hackmanit GmbH
5+
*
6+
* Licensed under Apache License 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*/
9+
package de.rub.nds.tlsattacker.core.workflow.action;
10+
11+
import de.rub.nds.tlsattacker.core.exceptions.WorkflowExecutionException;
12+
import de.rub.nds.tlsattacker.core.protocol.message.ProtocolMessage;
13+
import de.rub.nds.tlsattacker.core.state.TlsContext;
14+
import static de.rub.nds.tlsattacker.core.workflow.action.TlsAction.LOGGER;
15+
import java.io.ByteArrayInputStream;
16+
import java.io.ByteArrayOutputStream;
17+
import java.io.IOException;
18+
import java.io.ObjectInputStream;
19+
import java.io.ObjectOutputStream;
20+
import java.util.LinkedList;
21+
22+
public class DeepCopyBufferedMessagesAction extends CopyContextFieldAction {
23+
24+
public DeepCopyBufferedMessagesAction() {
25+
}
26+
27+
public DeepCopyBufferedMessagesAction(String srcConnectionAlias, String dstConnectionAlias) {
28+
super(srcConnectionAlias, dstConnectionAlias);
29+
}
30+
31+
@Override
32+
protected void copyField(TlsContext src, TlsContext dst) {
33+
deepCopyMessages(src, dst);
34+
}
35+
36+
@Override
37+
public boolean executedAsPlanned() {
38+
return isExecuted();
39+
}
40+
41+
@Override
42+
public void reset() {
43+
setExecuted(false);
44+
}
45+
46+
private void deepCopyMessages(TlsContext src, TlsContext dst) {
47+
LinkedList<ProtocolMessage> messageBuffer = new LinkedList<>();
48+
ObjectOutputStream outStream;
49+
ObjectInputStream inStream;
50+
try {
51+
for (ProtocolMessage message : src.getMessageBuffer()) {
52+
53+
ByteArrayOutputStream stream = new ByteArrayOutputStream();
54+
outStream = new ObjectOutputStream(stream);
55+
outStream.writeObject(message);
56+
outStream.close();
57+
inStream = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
58+
ProtocolMessage messageCopy = (ProtocolMessage) inStream.readObject();
59+
60+
messageBuffer.add(messageCopy);
61+
}
62+
} catch (IOException | ClassNotFoundException ex) {
63+
LOGGER.error("Error while creating deep copy of messageBuffer");
64+
throw new WorkflowExecutionException(ex.toString());
65+
}
66+
67+
dst.setMessageBuffer(messageBuffer);
68+
}
69+
70+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2017 Ruhr University Bochum / Hackmanit GmbH
5+
*
6+
* Licensed under Apache License 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*/
9+
package de.rub.nds.tlsattacker.core.workflow.action;
10+
11+
import de.rub.nds.tlsattacker.core.exceptions.WorkflowExecutionException;
12+
import de.rub.nds.tlsattacker.core.record.AbstractRecord;
13+
import de.rub.nds.tlsattacker.core.state.TlsContext;
14+
import static de.rub.nds.tlsattacker.core.workflow.action.TlsAction.LOGGER;
15+
import java.io.ByteArrayInputStream;
16+
import java.io.ByteArrayOutputStream;
17+
import java.io.IOException;
18+
import java.io.ObjectInputStream;
19+
import java.io.ObjectOutputStream;
20+
import java.util.LinkedList;
21+
22+
public class DeepCopyBufferedRecordsAction extends CopyContextFieldAction {
23+
24+
public DeepCopyBufferedRecordsAction() {
25+
26+
}
27+
28+
public DeepCopyBufferedRecordsAction(String srcConnectionAlias, String dstConnectionAlias) {
29+
super(srcConnectionAlias, dstConnectionAlias);
30+
}
31+
32+
@Override
33+
protected void copyField(TlsContext src, TlsContext dst) {
34+
deepCopyRecords(src, dst);
35+
}
36+
37+
@Override
38+
public boolean executedAsPlanned() {
39+
return isExecuted();
40+
}
41+
42+
@Override
43+
public void reset() {
44+
setExecuted(false);
45+
}
46+
47+
private void deepCopyRecords(TlsContext src, TlsContext dst) {
48+
LinkedList<AbstractRecord> recordBuffer = new LinkedList<>();
49+
ObjectOutputStream outStream;
50+
ObjectInputStream inStream;
51+
try {
52+
for (AbstractRecord record : src.getRecordBuffer()) {
53+
54+
ByteArrayOutputStream stream = new ByteArrayOutputStream();
55+
outStream = new ObjectOutputStream(stream);
56+
outStream.writeObject(record);
57+
outStream.close();
58+
inStream = new ObjectInputStream(new ByteArrayInputStream(stream.toByteArray()));
59+
AbstractRecord recordCopy = (AbstractRecord) inStream.readObject();
60+
61+
recordBuffer.add(recordCopy);
62+
}
63+
} catch (IOException | ClassNotFoundException ex) {
64+
LOGGER.error("Error while creating deep copy of recordBuffer");
65+
throw new WorkflowExecutionException(ex.toString());
66+
}
67+
68+
dst.setRecordBuffer(recordBuffer);
69+
}
70+
71+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2017 Ruhr University Bochum / Hackmanit GmbH
5+
*
6+
* Licensed under Apache License 2.0
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*/
9+
package de.rub.nds.tlsattacker.core.workflow.action;
10+
11+
import de.rub.nds.tlsattacker.core.state.State;
12+
import de.rub.nds.tlsattacker.core.state.TlsContext;
13+
14+
public class DeepCopyBuffersAction extends CopyContextFieldAction {
15+
16+
private State state;
17+
18+
public DeepCopyBuffersAction() {
19+
20+
}
21+
22+
public DeepCopyBuffersAction(String srcConnectionAlias, String dstConnectionAlias) {
23+
super(srcConnectionAlias, dstConnectionAlias);
24+
}
25+
26+
@Override
27+
public void execute(State state) {
28+
this.state = state;
29+
super.execute(state);
30+
}
31+
32+
@Override
33+
public boolean executedAsPlanned() {
34+
return isExecuted();
35+
}
36+
37+
@Override
38+
public void reset() {
39+
setExecuted(false);
40+
}
41+
42+
@Override
43+
protected void copyField(TlsContext srcContext, TlsContext dstContext) {
44+
DeepCopyBufferedRecordsAction copyRecords = new DeepCopyBufferedRecordsAction(super.getSrcContextAlias(),
45+
super.getDstContextAlias());
46+
DeepCopyBufferedMessagesAction copyMessages = new DeepCopyBufferedMessagesAction(super.getSrcContextAlias(),
47+
super.getDstContextAlias());
48+
49+
copyRecords.execute(state);
50+
copyMessages.execute(state);
51+
}
52+
53+
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/workflow/action/ResetConnectionAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public void execute(State state) throws WorkflowExecutionException, IOException
3232
tlsContext.getRecordLayer().updateEncryptionCipher();
3333
LOGGER.info("Resetting MessageDigest");
3434
tlsContext.getDigest().reset();
35-
LOGGER.info("Resettin ActiveKeySets");
35+
LOGGER.info("Resetting ActiveKeySets");
3636
tlsContext.setActiveClientKeySetType(Tls13KeySetType.NONE);
3737
tlsContext.setActiveServerKeySetType(Tls13KeySetType.NONE);
3838
tlsContext.setReadSequenceNumber(0);

resources/examples/0rtt_replay.xml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<!-- A MITM trace to replay 0-RTT data
3+
4+
Run server using:
5+
openssl s_server -key rsa1024key.pem -cert rsa1024cert.pem -tls1_3 -early_data
6+
7+
Run client using:
8+
openssl s_client -connect 127.0.0.1:4433 -tls1_3 -early_data earlyDataFile -sess_out 0rtt.pem
9+
10+
Stop the client, start TlsAttacker using this trace and run client again using:
11+
openssl s_client -connect 127.0.0.1:4432 -tls1_3 -early_data earlyDataFile -sess_in 0rtt.pem
12+
13+
OpenSSL should accept and print the early data
14+
-->
15+
<workflowTrace>
16+
<OutboundConnection>
17+
<alias>mitm2server</alias>
18+
<port>4433</port>
19+
<hostname>localhost</hostname>
20+
<timeout>100</timeout>
21+
</OutboundConnection>
22+
<InboundConnection>
23+
<alias>client2mitm</alias>
24+
<port>4432</port>
25+
<timeout>100</timeout>
26+
</InboundConnection>
27+
<!-- Buffer incoming ClientHello and early data -->
28+
<BufferedGenericReceive>
29+
<connectionAlias>client2mitm</connectionAlias>
30+
<messages/>
31+
<records/>
32+
</BufferedGenericReceive>
33+
<!-- Copy buffers to send the messages to the server -->
34+
<DeepCopyBuffers>
35+
<from>client2mitm</from>
36+
<to>mitm2server</to>
37+
</DeepCopyBuffers>
38+
<!-- Send ClientHello to server -->
39+
<PopAndSendRecord>
40+
<connectionAlias>mitm2server</connectionAlias>
41+
</PopAndSendRecord>
42+
<!-- Send early data to server -->
43+
<PopAndSendRecord>
44+
<connectionAlias>mitm2server</connectionAlias>
45+
</PopAndSendRecord>
46+
<!-- Forward server's responses to client -->
47+
<ForwardRecords>
48+
<receiveFromAlias>mitm2server</receiveFromAlias>
49+
<forwardToAlias>client2mitm</forwardToAlias>
50+
</ForwardRecords>
51+
<!-- Forward client's EndOfEarlyData + Finished to Server -->
52+
<ForwardRecords>
53+
<receiveFromAlias>client2mitm</receiveFromAlias>
54+
<forwardToAlias>mitm2server</forwardToAlias>
55+
</ForwardRecords>
56+
<!-- Reset connection to server -->
57+
<ResetConnection>
58+
<connectionAlias>mitm2server</connectionAlias>
59+
</ResetConnection>
60+
<!-- Copy buffers from client's context again -->
61+
<CopyBuffers>
62+
<from>client2mitm</from>
63+
<to>mitm2server</to>
64+
</CopyBuffers>
65+
<!-- Execute the actual replay attack -->
66+
<PopAndSendRecord>
67+
<connectionAlias>mitm2server</connectionAlias>
68+
</PopAndSendRecord>
69+
<PopAndSendRecord>
70+
<connectionAlias>mitm2server</connectionAlias>
71+
</PopAndSendRecord>
72+
</workflowTrace>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<!-- A MITM trace to replay 0-RTT data by sending it to another server with the same certificate
3+
4+
Run server 1 using:
5+
openssl s_server -key rsa1024key.pem -cert rsa1024cert.pem -tls1_3 -early_data
6+
Run server 2 using:
7+
openssl s_server -key rsa1024key.pem -cert rsa1024cert.pem -tls1_3 -early_data -port 4434
8+
9+
Run client using:
10+
openssl s_client -connect 127.0.0.1:4433 -tls1_3 -early_data earlyDataFile -sess_out 0rtt.pem
11+
12+
Stop the client, start TlsAttacker using this trace and run client again using:
13+
openssl s_client -connect 127.0.0.1:4432 -tls1_3 -early_data earlyDataFile -sess_in 0rtt.pem
14+
15+
Server 1 should accept and print the early data (although EndOfEarlyData is missing)
16+
Server 2 should accept the re-transmitted application data
17+
-->
18+
<workflowTrace>
19+
<OutboundConnection>
20+
<alias>mitm2server</alias>
21+
<port>4433</port>
22+
<hostname>localhost</hostname>
23+
<timeout>100</timeout>
24+
</OutboundConnection>
25+
<OutboundConnection>
26+
<alias>mitm2server2</alias>
27+
<port>4434</port>
28+
<hostname>localhost</hostname>
29+
<timeout>100</timeout>
30+
</OutboundConnection>
31+
<InboundConnection>
32+
<alias>client2mitm</alias>
33+
<port>4432</port>
34+
<timeout>100</timeout>
35+
</InboundConnection>
36+
<!-- Buffer incoming ClientHello and early data -->
37+
<BufferedGenericReceive>
38+
<connectionAlias>client2mitm</connectionAlias>
39+
<messages/>
40+
<records/>
41+
</BufferedGenericReceive>
42+
<!-- Copy buffers to send the messages to the 1st server -->
43+
<DeepCopyBuffers>
44+
<from>client2mitm</from>
45+
<to>mitm2server</to>
46+
</DeepCopyBuffers>
47+
<!-- Copy buffers to send the messages to the 2nd server -->
48+
<DeepCopyBuffers>
49+
<from>client2mitm</from>
50+
<to>mitm2server2</to>
51+
</DeepCopyBuffers>
52+
<!-- Send ClientHello to 1st server -->
53+
<PopAndSendRecord>
54+
<connectionAlias>mitm2server</connectionAlias>
55+
</PopAndSendRecord>
56+
<!-- Send early data to 1st server -->
57+
<PopAndSendRecord>
58+
<connectionAlias>mitm2server</connectionAlias>
59+
</PopAndSendRecord>
60+
<!-- Send ClientHello to 2nd server -->
61+
<PopAndSendRecord>
62+
<connectionAlias>mitm2server2</connectionAlias>
63+
</PopAndSendRecord>
64+
<!-- Send early data to 2nd server -->
65+
<PopAndSendRecord>
66+
<connectionAlias>mitm2server2</connectionAlias>
67+
</PopAndSendRecord>
68+
<!-- Reset connection to 1st server (from now on, the client will only talk to server 2)-->
69+
<ResetConnection>
70+
<connectionAlias>mitm2server</connectionAlias>
71+
</ResetConnection>
72+
<!-- Forward server responses to client -->
73+
<ForwardRecords>
74+
<receiveFromAlias>mitm2server2</receiveFromAlias>
75+
<forwardToAlias>client2mitm</forwardToAlias>
76+
</ForwardRecords>
77+
<!-- Forward client's handshake messages + retransmitted AppData to Server -->
78+
<ForwardRecords>
79+
<receiveFromAlias>client2mitm</receiveFromAlias>
80+
<forwardToAlias>mitm2server2</forwardToAlias>
81+
</ForwardRecords>
82+
</workflowTrace>

0 commit comments

Comments
 (0)