tls-attacker / TLS-Attacker

TLS-Attacker is a Java-based framework for analyzing TLS libraries. It can be used to manually test TLS clients and servers or as as a software library for more advanced tools.
Apache License 2.0
789 stars 136 forks source link

Help: How to get client_hello length before executing workflowExecutor #98

Closed ayushbindlish closed 3 years ago

ayushbindlish commented 3 years ago

When I try to print clientHelloMessage.getLength() before execution, I get null as output. How can I get length before execution?

WorkflowTrace trace = new WorkflowTrace();
        ClientHelloMessage clientHelloMessage = new ClientHelloMessage(tls12Init.getConf().getConfig());

        System.out.println(clientHelloMessage.getLength());

        System.out.println(clientHelloMessage.getProtocolVersion());

        tls12Init.setClientCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);

        clientHelloMessage.setLength(Modifiable.explicit(1));

        SendAction clienthello = new SendAction(clientHelloMessage);
        trace.addTlsAction(clienthello);
        trace.addTlsAction(new ReceiveAction(new AlertMessage()));
        State state = TLS12Execute.execute(tls12Init.getConf(), trace);  // executing workflowExecutor here
ic0ns commented 3 years ago

You cant. All originalValues are computed dynamically. The contents of messages depend on the context when the message will be sent so it is not possible to determine that beforehand.

For example, if your client hello contains the RenegotiationInfo extension, the length of the client hello will depend on whether you are sending the clienthello in the beginning of the connection or as a renegotiation request (in which case it might contain the verifyData which changes its size). If YOU already know in which context the message is sent, you can ask TLS-Attacker to fill the message contents to see how long the message will get. This requires some manual fiddling with the ClientHelloPreparator class.

ic0ns commented 3 years ago

Basically, you can create the TlsContext in which you want to send the message yourself (if you are in the beginning of the connection you can leave it as it is), and then create a Chooser with the ChooserFactory and you Config file. Then you can create a new ClientHelloPreparator with the chooser and the message in the constructor. If you then call preparator.prepare() the value will not be null anymore.

ayushbindlish commented 3 years ago

Oh okay got it. Also, will it be possible to get, in place of trace.addTlsAction(new ReceiveAction(new AlertMessage())); , check if server has closed the connection without sending back anything?

ic0ns commented 3 years ago

Usually the WorkflowExecutor closes the (TCP) connection for you after the execution of the WorkflowTrace. If you want to keep the connection open (for example to check if the server left the connection open itself), you can config.workflowExecutorShouldClose(false). If you do this, the workflowExecutor leaves the connection open and you can access the TransportHandler in the TlsContext yourself to check the state of connection. Eg. ((ClientTcpTransportHandler)state.getTlsContext().getTransportHandler()).getSocketState();

ic0ns commented 3 years ago

Don't forget to close the connection afterwards yourself.

ayushbindlish commented 3 years ago

I am doing this: But the openssl S_server keeps on waiting for data. And tlsattacker says socket state timeout

2021-04-16 18:41:07,641 main WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender
20000
18:41:10.020 [main] INFO  de.rub.nds.tlsattacker.core.workflow.DefaultWorkflowExecutor - Connecting to 127.0.0.1:4433
18:41:10.035 [main] INFO  de.rub.nds.tlsattacker.core.workflow.action.SendAction - Sending messages (client): CLIENT_HELLO, 
18:41:11.114 [main] INFO  de.rub.nds.tlsattacker.core.workflow.action.ReceiveAction - Received Messages (client): 
TIMEOUT
WorkflowTrace trace = new WorkflowTrace();
        ClientHelloMessage clientHelloMessage = new ClientHelloMessage(tls12Init.getConf().getConfig());

        tls12Init.setClientCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256);
        tls12Init.setWorkflowExecutorShouldClose(false);

        int x = 20000;
        int length = 1;
        while (x > length) {
            System.out.println(x);
            clientHelloMessage.setLength(Modifiable.explicit(x));
            SendAction clienthello = new SendAction(clientHelloMessage);
            trace.addTlsAction(clienthello);
            trace.addTlsAction(new ReceiveAction(new AlertMessage()));
            State state = TLS12Execute.execute(tls12Init.getConf(), trace);
            SocketState socket = ((ClientTcpTransportHandler)state.getTlsContext().getTransportHandler()).getSocketState();
            System.out.println(socket);
            AssertionCheck.checkAbsenceHandshakeMessages(state);
            String len = String.valueOf(clientHelloMessage.getLength());
            len = (len.substring(len.indexOf("=") + 1, len.indexOf("}")));
            length = Integer.parseInt(len);
            x--;
            break;
        }
ic0ns commented 3 years ago

Timeout is tls-attacker speak for the socket is still open. It's a little confusing, we have renamed it for the next version to just say "UP".

ayushbindlish commented 3 years ago

Thanks for clarifying that. @ic0ns