Psifi-Solutions / csrf-csrf

A utility package to help implement stateless CSRF protection using the Double Submit Cookie Pattern in express.
Other
120 stars 18 forks source link

csrf token cannot be overwriten on brave browser whlie redirecting via external link #71

Closed Sertturk16 closed 2 months ago

Sertturk16 commented 2 months ago

When accessing this route via an external link, the following code does not overwrite the _csrf cookie. Although the token I generate and send as a render parameter changes each time, the _csrf cookie does not update when I arrive via an external link. The cookie updates after first refresh. It only happens in brave browser.

Here is my csrf.js

export const { generateToken, doubleCsrfProtection, invalidCsrfTokenError } = doubleCsrf({
  cookieName: '_csrf',
  cookieOptions: {
    secure: true,
    httpOnly: true
  },
  getSecret: () => env.CSRF_SECRET,
  getTokenFromRequest: (req) => req.body._csrf || req.headers['x-csrf-token'] || req.query._csrf
})

Here is my route

...
return res.render('password/reset', { csrfToken: generateToken(req, res, true) })
...
Sertturk16 commented 2 months ago

Also "brave://flags/#brave-ephemeral-storage" disabling ephemeral storage here solves the problem

psibean commented 2 months ago

First of all, the code sample you shared, you've introduced the exact same vulnerability that csurf has:

getTokenFromRequest: (req) => req.body._csrf || req.headers['x-csrf-token'] || req.query._csrf

This makes you vulnerable in the same way as csurf (suspect to other configuration and environment). You absolutely shouldn't do this. You should be more explicit, e.g.:

getTokenFromRequest: (req) => {
    if (req.is('application/x-www-form-urlencoded') || req.is('multipart/form-data')) {
        return req.body._csrf;
    }

    return req.headers['x-csrf-token'];
}

You should be 100% explicit in how you get the token out of the request and only get it from the specific place you're expecting it to be. Additionally, providing a csrf token via query parameter has been highly recommended against for an extremely long time.

Also "brave://flags/#brave-ephemeral-storage" disabling ephemeral storage here solves the problem

You likely do not want to disable this, I would not consider this to be a solution, this may have potential security implications.

the _csrf cookie does not update when I arrive via an external link.

There are some security implications at play here, but I don't really have enough context on your situation to comment.

Is your external link just a direct link/href to your app? Or is it a link that makes a request and is then given a 302 redirect?

When you navigate using the external link and you view the GET request in the Network tab of the console, does it have the Set-Cookie header on the response to the GET request? Does it have any indication that the browser rejected it?

Do you have CORs configured? Is the external site running on https?

Sertturk16 commented 2 months ago

Thanks for pointing out, I've missed out when trying to keep up with new features, thanks to you we've modernizing that part. Also 302 redirection question is bullseye, 3rd party email app was altering our link which is the root of the problem.