quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.54k stars 2.61k forks source link

Form authentication CSRF #29924

Open bh-tt opened 1 year ago

bh-tt commented 1 year ago

Description

I am trying to use the builtin form authentication but I am struggling to add CSRF protection to the login process. The csrf-reactive extension is of no use since the actual login endpoint is not served through JAX-RS. Adding a method to validate a csrf token would improve the (default) security of this authentication method.

Implementation ideas

I would add a quarkus.http.auth.form.csrf-parameter (default csrf-token) and a quarkus.http.auth.form.csrf-cookie-name (or perhaps the default from csrf-reactive extension) as configuration. During the login process (here) the token should be validated against the cookie value, failing the login if the 2 do not match.

This would allow users to simply include the csrf-reactive extension and if the login page is served from a JAX-RS endpoint (for example using a Qute template) the extension will take care of generating and setting the token.

sberyozkin commented 1 year ago

@bh-tt The actual form HTML login page is created by the login endpoint, so the csrf-reactive feature can handle the injection of the csrf token into a login form page. But it is indeed interesting, how that can be verified, can you try quarkus.http.auth.proactive=false ? We might need though to revert CsrfHandler back to being a pre-match JAX-RS filter. If that won't work, then I'd rather introduce a csrf-common and have a vert.x filter variation of it so that it can run in front of the sec chain

bh-tt commented 1 year ago

Setting that property seems to have no effect, I am logged in after sending only j_username and j_password and can access protected paths. Each login also generates an IllegalStateException: Response head already sent. The FormAuthenticationMechanism login endpoint is not a JAX-RS endpoint, so I'm not sure if the request ever reaches the csrf filter. Even then the csrf verification of the login POST request would happen only after the login, while to be secure it should happen before the login. For example, a malicious website visited by a user could still send a large number of POST requests to the endpoint, trigger ratelimits and therefore cause a minor DoS. Validating the csrf token before the login attempt is necessary to prevent attacks of that kind.

sberyozkin commented 1 year ago

That was the idea behind auth.proactive=false, do it before the login is processed, but I see some updates will be needed