Skip to content

TLS Client

ic0ns edited this page Apr 28, 2017 · 5 revisions

Simple TLS Client

If you want to connect to a server, you can use the TLS-Attacker client command:

$ java -jar TLS-Attacker-1.2.jar client -connect localhost:4433 -cipher TLS_RSA_WITH_AES_128_CBC_SHA

The client allows you to define various parameters, which are documented in:

$ java -jar TLS-Attacker-1.2.jar client -help

This includes for example:

  • max_fragment_length: Maximum fragment length definition for the max fragment length TLS extension (possible byte values 1,2,3, or 4)
  • named_curve: Named curves to be used, divided by a comma, e.g. SECP192R1, SECP256R1, SECP384R1, SECP521R1
  • server_name: Servername used in the SNI TLS extension.
  • tls_timeout: This indicates the maximum number in milliseconds the client waits for the server TLS message response. The default value is 400, which is pretty high for localhost tests, but can be too low for network tests. Play with this value to speed up your tests and use e.g. 30 for OpenSSL running on localhost or 50 for JSSE on localhost.

TLS Client Authentication

Client-based authentication is also supported, just use it as follows. First, start the OpenSSL s_server:

$ cd resources
$ openssl s_server -key rsa1024key.pem -cert rsa1024cert.pem -verify ec256cert.pem

Then start the client with:

$ cd Runnable/target
$ java -jar TLS-Attacker-1.2.jar client -connect localhost:4433 -cipher TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -keystore ../../resources/ec256.jks -password password -alias alias -client_authentication

Custom Protocol Flows

You can use TLS-Attacker to execute customized protocol flows. You can define them in an XML message and then execute (given the file is called config.xml):

$ java -jar TLS-Attacker-1.2.jar client -workflow_input config.xml

A simple ECDHE RSA protocol flow definition would look like this:

<workflowTrace>
    <protocolMessages>
        <ClientHello>
            <messageIssuer>CLIENT</messageIssuer>
            <supportedCompressionMethods>
                <CompressionMethod>NULL</CompressionMethod>
            </supportedCompressionMethods>
            <supportedCipherSuites>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</CipherSuite>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</CipherSuite>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</CipherSuite>
            </supportedCipherSuites>
        </ClientHello>
        <ServerHello>
            <messageIssuer>SERVER</messageIssuer>
        </ServerHello>
        <Certificate>
            <messageIssuer>SERVER</messageIssuer>
        </Certificate>
        <ECDHEServerKeyExchange>
            <messageIssuer>SERVER</messageIssuer>
        </ECDHEServerKeyExchange>
        <ServerHelloDone>
            <messageIssuer>SERVER</messageIssuer>
        </ServerHelloDone>
        <ECDHClientKeyExchange>
            <messageIssuer>CLIENT</messageIssuer>
        </ECDHClientKeyExchange>
        <ChangeCipherSpec>
            <messageIssuer>CLIENT</messageIssuer>
        </ChangeCipherSpec>
        <Finished>
            <messageIssuer>CLIENT</messageIssuer>
        </Finished>
        <ChangeCipherSpec>
            <messageIssuer>SERVER</messageIssuer>
        </ChangeCipherSpec>
        <Finished>
            <messageIssuer>SERVER</messageIssuer>
        </Finished>
    </protocolMessages>
</workflowTrace>

If you want to duplicate a specific insert specific message, for example insert a second ChangeCipherSpec message, just modify the XML protocol flow like this:

<workflowTrace>
    <protocolMessages>
        <ClientHello>
            <messageIssuer>CLIENT</messageIssuer>
            <supportedCompressionMethods>
                <CompressionMethod>NULL</CompressionMethod>
            </supportedCompressionMethods>
            <supportedCipherSuites>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</CipherSuite>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</CipherSuite>
                <CipherSuite>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</CipherSuite>
            </supportedCipherSuites>
        </ClientHello>
        <ServerHello>
            <messageIssuer>SERVER</messageIssuer>
        </ServerHello>
        <Certificate>
            <messageIssuer>SERVER</messageIssuer>
        </Certificate>
        <ECDHEServerKeyExchange>
            <messageIssuer>SERVER</messageIssuer>
        </ECDHEServerKeyExchange>
        <ServerHelloDone>
            <messageIssuer>SERVER</messageIssuer>
        </ServerHelloDone>
        <ECDHClientKeyExchange>
            <messageIssuer>CLIENT</messageIssuer>
        </ECDHClientKeyExchange>
        <ChangeCipherSpec>
            <messageIssuer>CLIENT</messageIssuer>
        </ChangeCipherSpec>
        <ChangeCipherSpec>
            <messageIssuer>CLIENT</messageIssuer>
        </ChangeCipherSpec>
        <Finished>
            <messageIssuer>CLIENT</messageIssuer>
        </Finished>
        <ChangeCipherSpec>
            <messageIssuer>SERVER</messageIssuer>
        </ChangeCipherSpec>
        <Finished>
            <messageIssuer>SERVER</messageIssuer>
        </Finished>
    </protocolMessages>
</workflowTrace>

When running the client with this configuration, you can see it issues two ChangeCipherSpec messages and sends it to the server.

To have a good template for TLS protocol flows, you can execute the TLS client and output the TLS protocol flow into a file:

$ java -jar TLS-Attacker-1.2.jar client -workflow_output /tmp/config.xml

Such a TLS worklow output contains many additional data (e.g., original values for crypto parameters and secrets), but you can safely use this configuration file.

Custom Protocol Messages

The above given protocol modification just inserts a new ChangeCipherSpec message. It is however also possible to execute arbitrary modifications on message variables.

Imagine that the previous command resulted in a TLS workflow including the following ClientKeyExchange message:

        <ECDHClientKeyExchange>
            <completeResultingMessage>
                <originalValue>
  10 00 00 42 41 04 76 E8  EA 4B A2 CE 59 59 4B 79 
  BF CE 85 85 7B 4E 9E 52  E1 45 6F C7 77 6D 06 38 
  B7 63 F4 EB 31 65 08 F0  AE BC F1 A3 A4 2B AA E0 
  51 6C 12 94 DC 4C 08 EB  78 79 A7 52 CD 90 39 8E 
  51 BB 64 08 80 30 </originalValue>
            </completeResultingMessage>
            <goingToBeSent>true</goingToBeSent>
            <messageIssuer>CLIENT</messageIssuer>
            <records>
                <Record>
                    <contentType>
                        <originalValue>22</originalValue>
                    </contentType>
                    <length>
                        <originalValue>70</originalValue>
                    </length>
                    <protocolMessageBytes>
                        <originalValue>
  10 00 00 42 41 04 76 E8  EA 4B A2 CE 59 59 4B 79 
  BF CE 85 85 7B 4E 9E 52  E1 45 6F C7 77 6D 06 38 
  B7 63 F4 EB 31 65 08 F0  AE BC F1 A3 A4 2B AA E0 
  51 6C 12 94 DC 4C 08 EB  78 79 A7 52 CD 90 39 8E 
  51 BB 64 08 80 30 </originalValue>
                    </protocolMessageBytes>
                    <protocolVersion>
                        <originalValue>03 03 </originalValue>
                    </protocolVersion>
                    <sleepAfterMessageSent>0</sleepAfterMessageSent>
                </Record>
            </records>
            <fragmentLength>
                <originalValue>0</originalValue>
            </fragmentLength>
            <fragmentOffset>
                <originalValue>0</originalValue>
            </fragmentOffset>
            <includeInDigest>true</includeInDigest>
            <length>
                <originalValue>66</originalValue>
            </length>
            <messageSeq>
                <originalValue>0</originalValue>
            </messageSeq>
            <type>
                <originalValue>16</originalValue>
            </type>
            <masterSecret>
                <originalValue>
  4F 47 90 3E EC AB FA 33  72 00 C3 34 19 08 36 77 
  46 8C 5F 4B 2D 84 93 3A  DB 4B 04 83 54 00 86 4D 
  CA B9 F4 9F E4 39 53 F6  73 1B BA 40 36 BC B5 DB </originalValue>
            </masterSecret>
            <premasterSecret>
                <originalValue>
  22 28 CA AE 81 5E 93 7D  62 B7 F0 35 34 C5 9E 0B 
  C5 24 FC 20 84 0D F7 1A  6B 9B E6 5B CF 7C A7 82 </originalValue>
            </premasterSecret>
            <ecPointEncoded>
                <originalValue>
  76 E8 EA 4B A2 CE 59 59  4B 79 BF CE 85 85 7B 4E 
  9E 52 E1 45 6F C7 77 6D  06 38 B7 63 F4 EB 31 65 
  08 F0 AE BC F1 A3 A4 2B  AA E0 51 6C 12 94 DC 4C 
  08 EB 78 79 A7 52 CD 90  39 8E 51 BB 64 08 80 30 </originalValue>
            </ecPointEncoded>
            <ecPointFormat>
                <originalValue>4</originalValue>
            </ecPointFormat>
            <publicKeyBaseX>
                <originalValue>53784441699640646333746776021277690235595633404770848422191843322940132897125</originalValue>
            </publicKeyBaseX>
            <publicKeyBaseY>
                <originalValue>4043752081994838743283507235440741717841032447321866288820950543321971327024</originalValue>
            </publicKeyBaseY>
            <publicKeyLength>
                <originalValue>65</originalValue>
            </publicKeyLength>
        </ECDHClientKeyExchange>

This protocol message contains all information about the premaster secret, public key parameters as well as record data. In order to execute the protocol flow with a modified message, for example a message with an invalid publicKeyLength, you can define this value as follows:

<publicKeyLength>
    <integerExplicitValueModification>
        <explicitValue>70</explicitValue>
    </integerExplicitValueModification>
</publicKeyLength>

When using this value in the protocol flow, the publicKeyLength value will be explicitly set to 70 during the message processing, independently of the real public key length. The resulting ClientKeyExchange message would simply look like this (you do not have to preserve all the values and fields):

        <ECDHClientKeyExchange>
            <messageIssuer>CLIENT</messageIssuer>
            <publicKeyLength>
                <integerExplicitValueModification>
                     <explicitValue>70</explicitValue>
                </integerExplicitValueModification>
            </publicKeyLength>
        </ECDHClientKeyExchange>

Similar modifications can be performed for other fields in the ClientKeyExchange message, like fragmentLength or length. Note that publicKeyBaseX and publicKeyBaseY are of type BigInteger and thus need other modifications, e.g.:

<publicKeyBaseX>
    <bigIntegerAddModification>
        <summand>1</summand>
    </bigIntegerAddModification>
</publicKeyBaseX>

If you want to edit byte arrays, use for example the following modification:

<premasterSecret>
    <byteArrayExplicitValueModification>
        <explicitValue>
            4F 3F 8C FC 17 8E 66 0A  
        </explicitValue>
    </byteArrayExplicitValueModification>
</premasterSecret>

More examples on modifications can be found in: Modifiable-Variables

If you want to execute custom TLS workflows from Java, you can take a look at the implementation of some attacks here: https://github.com/RUB-NDS/TLS-Attacker/tree/master/Attacks/src/main/java/de/rub/nds/tlsattacker/attacks/impl

TLS Server

You can also use a server from TLS-Attacker:

$ cd Runnable/target
$ java -jar TLS-Attacker-1.2.jar server -port 4444 -keystore ../../resources/rsa1024.jks -password password -alias alias

Currently, only one TLS handshake will be produced, afterwards you need to restart the server again.

Clone this wiki locally