26-02-2019 / From 0 to pentesting hero

Random vs SecureRandom

Every service that has a login mechanism should also have the option to reset the password.

But how to do it right?

Password reset functionality usually works more or less like this. The user provides the email address associated with the account on the website.

At this point, the server checks whether such user exists in the database.

If so - it generates a unique string, which is then saved and sent in an email.

Then the user opens the email and clicks on the link that contains this unique key.

The server verifies if a unique string exists in the database - and if everything is correct, you can change the password.

So how to generate this unique string? Probably we will think of using the Random1 function that lets us generate unique sequences of numbers.

So, the implementation may look as follows.

package com.company;
import java.util.Random;
public class Main {
    static Random r = new Random();
    static String getToken() {
        return Integer.toString(r.nextInt());
    }
    public static void main(String[] args) {
        System.out.println(getToken());
        System.out.println(getToken());
        System.out.println(getToken());
    }
}

Each time someone wants to reset their password, the getToken() function is called and its result is then saved to the database.

So where is the vulnerability today?

The random class is a pseudo random number generator.

This means that based on a small amount of information - the so-called seed - it generates deterministically consecutive pseudo-random numbers.

Satirical random function explanation
https://xkcd.com/221/">https://xkcd.com/221/

The seed can be defined by the user - or, like in our case, set automatically by Java.

So it is enough to guess what seed was used to be able to generate the next token on your own computer.

To guess the seed we will use the code from the Stack Overflow2.

To guess the seed, it needs 2 consecutive numbers generated by the given random class instances.

How to get it? In the case of password reset functionality, it is very simple.

It is enough to ask for the reset of the account to which we hold the permits, and the third time try to reset the admin account.

Next, we read the first 2 values ​​from the email that we have access to.

I will simulate this process using the GetToken function 3 times.

I will now introduce the first two values ​​into the seed recovery class.

Recover seed in practice

As you can see, after a few seconds we received the potential value of the seed as well as the next pseudo-random number.

In our case, it is exactly the same as the one we received after the third call to the gettoken function.

In fact, this would be a unique identifier that could be used to reset the administrator password.

Of course, we assume here that we are lucky and no one else has done the same action between our attempts.

So how do you protect yourself against this problem?

Always use the SecureRandom3 class because the values ​​returned by this class can not be predicted.

SecureRandom

The same problem also exists with the RandomStringUtils class

RandomStringUtils
https://github.com/alex91ar/randomstringutils/blob/master/The%20Java%20soothsayer.pdf

There, however, the process of guessing the seed takes a bit longer.

Generating random values on a computer is not as easy as rolling a dice in reality.