catch the security flaw #2 (flaw and its countermeasure)

In my previous “Catch the Security Flaw” post I wrote about a flawed CAPTCHA implementation. In this post I discuss what are the flaws in that implementation and how to prevent them. Before I go into the exact flaws, let us agree upon a standard notation to describe the flow of data.

C stands for Client. This is the end user. S stands for Server which is the web server in this case.

In the implementation of the flawed CAPTCHA, the data flow is:-

1) C ----> S; GET somepage.aspx

2) S ----> C; Somedata || CAPTCHA Picture || hash (CAPTCHA value)

3) C ----> S; Somedata’ || hash (CAPTCHA value) || CAPTCHA value

In the flawed implementation, hash (CAPTCHA value) is being maintained on the client side as a hidden field. CAPTCHA value is supposed to be entered by the end user in the text box.

If in the 3rd step, Server gets the ”right” CAPTCHA value, it takes the action. To check if the value is “right”, the server simply hashes the CAPTCHA value sent by the client and then compares it with the hash (CAPTCHA value) also sent by the client.

To discuss the flaws, we will look only at the 3rd step. The attacker, to run an automated script, will continually call step 3.

Attack 1:- The client can take any value, say A. Then hash it to get hash (A). It can then continually call step 3 as:-

3) C ----> S; Somedata’ || hash (A) || A

This value A is not the same as in the picture in step 2. It doesn't have to be. The server does not maintain state. Hence it doesn't know that this value A is not the same as the one it had sent in the picture in step 2.

Countermeasure of Attack 1:-

So to prevent this attack, instead of hashing the value, let us encrypt it. The flow now becomes:-

1) C ----> S; GET somepage.aspx

2) S ----> C; Somedata || CAPTCHA Picture || Encrypt (CAPTCHA value, Key)

3) C ----> S; Somedata’ || Encrypt (CAPTCHA value, Key) || CAPTCHA value

Key is the encryption key used to encrypt the CAPTCHA value. This key is known only to the server. Now if the Client takes any value, say A. It does not have the Key to encrypt it to create Encrypt (A, Key). Hence it cannot choose any A and then call step 3. Great!

Attack 2:-

Even if the above countermeasure is put in place, the Client can still call step 3 continually. The Client can once manually see the CAPTCHA picture. Say the value in it is B. It can then call step 3 continually with the same value.

3) C ----> S; Somedata’ || Encrypt (B, Key) || B

Client doesn't know how to calculate Encrypt (B, Key). It does not need to. The Server is not storing any state. Hence the server does not know if this value has been used before.

Therefore, never forget this principle for a CAPTHCA implementation:-

“The Server MUST maintain state in a secure CAPTCHA implementation”

Countermeasure for Attack 2:-

1) C ----> S; GET somepage.aspx

2) S ----> C; Somedata || CAPTCHA Picture =>Server maintains CAPTHCA value

3) C ----> S; Somedata’ || CAPTCHA value  =>Server verifies CAPTCHA value

In step 2, the Server creates a random CAPTCHA value and stores it on the server side. It links this value with a particular Client, say using a session ID. In step 3, the Server verifies if the value sent by the Client is the same as in its state. It then must nullify the CAPTCHA value for that client.

 

Reference:-

An ASP.NET Framework for Human Interactive Proofs