Login CSRF

Login CSRF is a type of attack where the attacker can force the user to log in to the attacker’s account on a website and thus reveal information about what the user is doing while logged in.

What can happen?

The risk varies depending on the application and is hard to evaluate from a black-box perspective.

PayPal was once vulnerable to login CSRF and the attacker could make a user log in to the attacker’s PayPal account. When the user later on paid for something online, they unknowingly added their credit card to the attacker's account.

Another, less obvious, example is a login CSRF that once existed in Google, which made it possible for the attacker to make the user log in to the attacker’s account and later retrieve all the searches the user had made while logged in.

If public registration for the application exists, the risk of attacks drastically increases as it’s very easy for the attacker to create an account and thus know the credentials for it.

Example of Login CSRF

Login CSRF is like any other CSRF, the only difference is that it occurs on the login form. If you need more information on this topic, you can just search for CSRF in general.

An example of this vulnerability in PHP could look something like this:

<?php
    if (isset($_POST["user"], $_POST["pass"])){
        // code for checking the user and password
    } else {
        echo '
            <form method="post">
                <input name="user">
                <input name="pass" type="password">
                <input type="submit">
            </form>
        ';
    }
?>

As the PHP code doesn’t validate where the credentials come from, it would be possible to trick the user to visit a page with following code:

<form id="LoginForm" action="http://target/login.php" method="post">
    <input name="user" value="foo">
    <input name="pass" type="password" value="bar">
    <input type="submit">
</form>

<script>
    document.getElementById("LoginForm").submit();
</script>

The browser would send a POST request with the login credentials to the PHP page which checks if they are correct and then log in the user.

Remediation

You need to implement a token system in your code to prevent Login CSRF - see the OWASP CSRF Prevention Cheat Sheet for different recommended methods. The important thing is to make sure the token is something the user has (but not the attacker), so that you can make sure it really is the user submitting a login request.

The easiest remediation for CSRF

The following snippet of code shows what is probably the easiest of the recommended methods, Double submit cookies.

 <?php
    if (isset($_POST["user"], $_POST["pass"]){
        // Make sure the token from the login form is the same as in the cookie
        if (isset($_POST["CSRFtoken"], $_COOKIE["CSRFtoken"])){
            if ($_POST["CSRFtoken"] == $_COOKIE["CSRFtoken"]){
                // code for checking the user and password
            }
        }
    } else {
        $token = bin2hex(openssl_random_pseudo_bytes(16));
        setcookie("CSRFtoken", $token, time() + 60 * 60 * 24);
        echo '
            <form method="post">
                <input name="user">
                <input name="pass" type="password">
                <input name="CSRFtoken" type="hidden" value="' . $token . '">
                <input type="submit">
            </form>
        '
    }
?>

The code will generate a random token and set it both as a cookie and as a hidden-value in the form. When the form is submitted, the code will check if the CSRFToken in the form is the same as the CSRFToken in the cookie and the user will be logged in only if they are the same.

This works as a protection because the attacker can’t know the value of the cookie CSRFToken and therefore can’t send that value in the form. This method is also valid for other kinds of CSRF vulnerabilities, not just login CSRF.

Resources