DVWA - Weak Session IDs

Starting the challenge

Refer to the post start DVWA with Docker to learn how to start DVWA.

I will mostly use Burp Suite to solve the challenges. To configure Burp suite refer to the post configure burp suite for DVWA.

Click on the Weak Session IDs button on the left menu to access the challenge.

Low level

Understanding the application

We reach a page allowing us to generate cookies called dvwaSession.

Weak session ids application

We try the app by clicking multiple times on the button Generate then we look at the associated requests in Burp Suite Proxy > HTTP history.

By selecting the last request and Response > Headers, we can see that when we click on the button Generate, a Set-Cookie command is sent from the server to the browser.

This command defines the value of the dvwaSession cookie.

Exploiting the vulnerability

From what we can see, the value of the cookie in incremented by one everytime we click on the button Generate.

With this knowledge we can predict what future cookies will be distributed and what previous cookies were generated. With these cookies we can steal a valid user session and impersonate a legitimate user to steal information or carry out some malicious operations.

Vulnerable code

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id'])) {
        $_SESSION['last_session_id'] = 0;
    }
    $_SESSION['last_session_id']++;
    $cookie_value = $_SESSION['last_session_id'];
    setcookie("dvwaSession", $cookie_value);
}
?>

We can see that the code on the server simply adds one to the previous session id $_SESSION['last_session_id']++;.

Remediation

To prevent this kind of vulnerability, the session ID should be hard to find for an attacker.

Medium level

In the medium level the cookie is different and might be impredictible. To make sure of that we will generate multiple cookies and perform a statistical analysis on our dataset.

Set-Cookie response

Retrieving a set of cookies

Each click on the Generate button generates a new cookie that we can see in the Set-Cookie header of the server’s response.

When we glance at some of the cookies values, we can observe that they all look alike :

  • 1554976646
  • 1554976644
  • 1554975380
  • 1554975379

It might even seem like the values are increasing.

To get a better understanding of how the cookies are generated, we use the Sequencer feature in Burp.

To do so, we right-click on the request triggering a cookie generation and send it to the Sequencer.

Send to sequencer

We then go to Sequencer > Live capture. This tool allow us to replay the request generating the cookies multiple time and automatically extract the new cookies.

Sequencer config

As we can see in the configuration the sequencer already guessed that the cookie dvwaSession should be extracted. We fill in the configuration by choosing to send a request every 500 milliseconds (to avoid a server overload). We change the parameter Throttle between requests in the Live Capture Options.

We reduce the number of threads to 1 by modifying the parameter Number of threads. Now we will have one request sent every 500ms (2 requests by second).

We click on Start live capture to extract the cookies.

Sequencer live capture

We stop the capture when we have around 50 cookies with the Stop button. We copy the tokens and open a file editor to paste them and have a look at them.

Session IDs analysis

Below is an extract of the cookies retrieved:

1554978129
1554978130
1554978130
1554978131
1554978131
1554978132
1554978132
1554978133
1554978133
1554978134
1554978134
1554978135
1554978135
1554978136
1554978136
1554978137
1554978137
1554978138
1554978138
1554978139
1554978139
1554978140
1554978140
1554978141
1554978141
1554978142
1554978142
1554978143
1554978143
1554978144
1554978144

We notice that :

  • cookies are sequentials
  • cookies are incremented by 1 every two request

Since we send 2 requests every second, we can say that the cookie is incremented by 1 every second. From our experience, the format looks a lot like UNIX time (or Epoch time). When we use a Unix time converter we can see that 1554978142 corresponds to Thu Apr 11 10:22:22 2019 UTC. What we have here is a time measurement encoded in UNIX time : the cookie’s value is the time it was generated.

Now that we know how the cookies are being attributed, we can forge our own and steal someone’s session.

Vulnerable code

Here we can see that the code just calls time() to set the cookie value.

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $cookie_value = time();
    setcookie("dvwaSession", $cookie_value);
}
?> 

Remediation

The cookies should be hard to find. The attacker should not be able to perform a statistical analysis on a dataset to understand how they are generated.

High level

In the high level, the cookies look like this e4da3b7fbbce2345d7772b0674a318d5.

We start by retrieving a list of session IDs. We collect the session ids generated and analyze them. Here is a sample of the tokens. They look like md5 hashes.

e4da3b7fbbce2345d7772b0674a318d5
1679091c5a880faf6fb5e6087eb1b2dc
8f14e45fceea167a5a36dedd4bea2543
c9f0f895fb98ab9159f51fd0297e236d
45c48cce2e2d7fbdea1afc51c7c6ad26
d3d9446802a44259755d38e6d163e820
6512bd43d9caa6e02c990b0a82652dca
c20ad4d76fe97759aa27a0c99bff6710

Let’s try to crack one of these hashed with hashcat. We put the first hash into a file named hash.txt and start hashcat.

./hashcat -a 3 -m 0 hash.txt --increment

Hashcat manages to crack it quickly, the original string was 5. We try to crack the other hashes and we find that the hashes were :

e4da3b7fbbce2345d7772b0674a318d5:5
1679091c5a880faf6fb5e6087eb1b2dc:6
8f14e45fceea167a5a36dedd4bea2543:7
c9f0f895fb98ab9159f51fd0297e236d:8
45c48cce2e2d7fbdea1afc51c7c6ad26:9
d3d9446802a44259755d38e6d163e820:10
6512bd43d9caa6e02c990b0a82652dca:11
c20ad4d76fe97759aa27a0c99bff6710:12

So it appears that the cookies are MD5 sums of an incremented counter.

Vulnerable code

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    if (!isset ($_SESSION['last_session_id_high'])) {
        $_SESSION['last_session_id_high'] = 0;
    }
    $_SESSION['last_session_id_high']++;
    $cookie_value = md5($_SESSION['last_session_id_high']);
    setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}

?>

As we can see from the server code, the cookie value is md5($_SESSION['last_session_id_high']); as we predicted.

Remediation

A proper way to generate hard to find cookies is to generate them randomly. In the Impossible level, the cookie is generated randomly from the mt_rand() function.

<?php

$html = "";

if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $cookie_value = sha1(mt_rand() . time() . "Impossible");
    setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);
}
?>