1

An application has a multifactor login. The user logs in with its e-mail and password, and then the following screen asks for a one time password received via e-mail or generated by a mobile app.

In that second screen there's also a link called "cancel login" that points to, for example /login/cancel. The user can click this to cancel the login process and the sessions/cookies for the process are cleaned up and you would have to start over.

My question is about this kind of 'action' links. Clicking it actually sends a GET request, but not for just displaying a page or retrieving data, but for performing an action in the application. In practice, another website could contain a link or even an image that points to the "login cancel url" of our application and logout unknowing users. Simply said, a CSRF attack.

I use the Laravel PHP framework, and use the built-in CSRF protection for html forms. But I wonder how to implement this protection for GET requests properly. Would it be sufficient to add a query parameter to the url of the action link, and then manually verify the included CSRF token? Also, I wonder if it is acceptable anyway to use links for executing an action in a web application. It works well, but a GET request is semantically not intended for 'saying/executing'. One alternative is that I don't use links but a small form containg a hidden CSRF token field and a submit button that acts as (and is styled as) a link. The form is sent using a POST request then. What are best practises and are there any security guidelines?

2 Answers 2

2

You pretty much answered the question your self, just use a form with CSRF protection. A GET url is easier to abuse by malicious parties (through links and images etc.) but CSRF protection will work just as well and I’m sure Laravel will supports this.

Alternatively you can sign the link and reject any request to the url that don’t have a valid signature.

2

With the proper use of a cookie and a query string parameter, you can emulate what many CSRF mitigation strategies use. Before delving into securing cookies, this is what the process entails:

  1. Set a cookie with some encrypted, random value (the CSRF token). Mark it HttpOnly, Secure, and SameSite. When you do this is up to you. Perhaps at login.

  2. Put the CSRF token in the query string to the log out page.

  3. Upon clicking the log out link, the browser sends two copies of this token: one in the query string, and the other as a cookie.

  4. Prior to executing the logout logic, compare the two tokens. Only if the tokens match should you execute the logout logic. If the tokens do not match, or either of them is missing, respond with a 400 Bad Request.

This prevents CSRF attacks only if you set up the cookie properly. The server should respond something like this when first setting the cookie:

HTTP/1.1 200 OK
...
Set-Cookie: CSRF=abc123; expires=date; Domain=example.com; Path=XXX; HttpOnly; Secure; SameSite
...

<DOCTYPE HTML>
<html>

See MDN for more information.

The URL to logout would be something like https://example.com/logout?CSRF=abc123.

Clicking this link would send an HTTP request similar to:

GET /logout?CSRF=abc123 http/1.1
...
Cookie: CSRF=abc123
...

With the cookie marked HttpOnly, JavaScript cannot access the cookie, so malicious scripts cannot read the cookie and send it somewhere for use later. The SameSite attribute on the cookie means browsers will not send the cookie at all unless the page is loaded from the same origin (protocol + host + port) — see the Same Origin Policy. This prevents drive-by requests embedded as script tags on some hacker's website. Imagine some other web site has this embedded in its source code:

<script src="https://example.com/logout?CSRF=abc123"></script>

The browser will happily make this request, but the CSRF cookie will not be sent, even if the attacker managed to guess the CSRF token. Since the CSRF cookie is not sent, your server would respond with 400 Bad Request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.