Rating: 5.0

__Note:__ It was enough for me to read the *ACME_Protocol.docx* to figure out the major flaw and how to exploit it. Take time to read the ACME Protocol first before you read the solution. I enjoyed solving this.

## Solution

### Analyze the Protocol

The protocol can be summarized in the following steps (where `|` is concatenate):

1. To log on, the client first sends the __username__.
2. The server responds with a challenge 8-byte nonce and an encrypted challenge cookie. `AES.encrypt(nonce | username | timestamp )`.
3. The client authenticates by answering the challenge using knowledge of the password. The client passes the answer together with the challenge cookie back to the server.
4. The server issues a session ticket, `AES.encrypt(identity | timestamp)`.
5. The client presents this ticket to establish its identity whenever issuing a command. To log off, the client simply discards the ticket.

The protocol uses a cookie/ticket that is encrypted using __AES CBC__, which contains all the information used to validate a logon request or to authenticate for a command. Both the challenge cookie and the session ticket use the same key.

A sample of the __identity__ is `{"user": "admin", "groups": ["admin"]}`

#### Easier Form of the Problem

Let's say that the challenge cookie _does not have a nonce_, then challenge cookie comes in the form `AES.encrypt(username | timestamp)`.

If we can use the username `{"user": "admin", "groups": ["admin"]}` so that __our challenge cookie becomes a valid session ticket.__

#### Solving the Original Problem

We need to find a way to remove the __nonce__ in the challenge cookie to be able to create valid session tickets.

Let's look at how __AES CBC__ works,

![AES CBC](https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/CBC_decryption.svg/902px-CBC_decryption.svg.png)

Notice that the __IV__ is only used on the first block the of ciphertext, and __the first block of ciphertext is used as the IV of the the second block.__ So given a pair `(IV, C)`, you can construct another pair `(C[:16]',C[16:]')` that will be properly decrypted by the server, but the resultant plaintext will not have the first 16 bytes of the original plaintext.

__With this we can remove the nonce! We just pad our input by 8 bytes so that the first 16 bytes is just the ( nonce | padding )__

Here is a pseudocode to explain
```python
iv, c = AES.encrypt(key, (nonce | padding | identity | timestamp)) # (nonce | padding) should be exactly 16 bytes
iv, c = c[:16], c[16:]
plaintext = AES.decrypt(key, iv, c)
assert plaintext == (identity | timestamp)
```

#### Exploit

So our exploit would be:
1. To log on, the client first sends the __(padding | identity)__.
2. The server responds the encrypted challenge cookie. `AES.encrypt(nonce | padding | username | timestamp )`.
3. The client uses the encrypted challenge cookie to create a valid session cookie..
4. The server issues a session ticket, `AES.encrypt(identity | timestamp)`.
5. The client presents this ticket to establish its identity and get the flag.

With that we can get the flag!
`# TMCTF{90F41EF71ED5}`

__For implementation details of creating a malicious client please see the link__

Original writeup (https://github.com/pberba/ctf-solutions/tree/master/20180915_trendmicro/analysis_offensive_400).