tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <ch...@christopherschultz.net>
Subject Re: Using CsrfPreventionFilter with GET-based <form> submissions
Date Wed, 13 Nov 2019 16:25:43 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Peter,

On 11/12/19 18:52, Peter Kreuser wrote:
> 
> 
> Chris,
> 
>> Am 13.11.2019 um 02:35 schrieb Christopher Schultz
>> <chris@christopherschultz.net>:
>> 
>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
>> 
>> Peter,
>> 
>>> On 11/10/19 19:05, Peter Kreuser wrote: Chris,
>>> 
>>>> 
>>>> Am 09.11.2019 um 03:58 schrieb Christopher Schultz 
>>>> <chris@christopherschultz.net>:
>>>> 
>>>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
>>>> 
>>>> All,
>>>> 
>>>> I'm playing with the CsrfPreventionFilter and things are
>>>> working well in the following situations:
>>>> 
>>>> <a href="url">link text</a>
>>>> 
>>>> and
>>>> 
>>>> <form method="post" action="url"> ... </form>
>>>> 
>>>> As long as the URL has been passed through
>>>> request.encodeURL().
>>>> 
>>>> However, this one is causing me a problem:
>>>> 
>>>> <form method="GET" action="url"> ... </form>
>>>> 
>>>> This builds a form like this:
>>>> 
>>>> <form method="GET" 
>>>> action="https://host/path?org.apache.catalina.filters.CSRF_NONCE=[.
..
>>
>>>> 
]">
>>>> 
>>>> 
>> ...
>>>> </form>
>>>> 
>>>> Neither Firefox nor Chrome will send the query string present
>>>> in a <form> action attribute if the method="GET". The method
>>>> must be "POST" in order for this to be sent. This is due to
>>>> the HTML standard[1].
>>>> 
>>>> Short of changing all <form> methods to "POST", is there any
>>>> way around this?
>>>> 
>>>> I have read the code for CsrfPreventionFilter and it does
>>>> not appear that the nonce if stored anywhere except in the 
>>>> CsrfResponseWrapper for the request (and the session's nonce 
>>>> cache, but that isn't request-specific).
>>>> 
>>>> Would it be inappropriate to add the CSRF_NONCE to the
>>>> request attributes so that application code could use it
>>>> directly if necessary? Something like this:
>>>> 
>>>> <form method="get" action="url"> ... <input type="hidden" 
>>>> name="org.apache.catalina.filters.CSRF_NONCE" value="<%= 
>>>> request.getAttribute("CSRF_NONCE") %>" /> </form>
>>> 
>>> If i remember correctly, this is the way struts handles CSRF 
>>> Tokens.
>> 
>> I'm not sure what Struts has to do with this. I'm using Tomcat's
>> CSRF filter which apparently cannot work with GET-based forms.
>> I'm not saying that a GET-based form is a good idea, but we have
>> a bunch of them so I'm looking into how they can be effectively
>> used with this implementation of a CSRF filter.
> 
> I just wanted to point out that struts implements the CSRF
> protection only with a hidden field. That’s a bit of a hassle, plus
> you have to handle this per form. Wether it is a POST or a GET.
> 
>> I'm really surprised this hasn't come up, yet. Maybe nobody
>> actually implements CSRF protection, or maybe nobody uses
>> Tomcat's filter to do it, or maybe nobody uses GET-based HTML
>> <form>s. But I can't believe that I'm the only person in the
>> world who is trying to use all three at once.
>> 
>>> However there the nonce comes directly from the session . Not 
>>> request.
>> 
>> The nonces are stored in the session, otherwise this wouldn't
>> work. But each request generates a new nonce, and that one would
>> be the "request's nonce".
> 
> That’s another difference to struts and a bit of a nuisance, the
> nonce is only created once (and there is no cache). Once you remove
> it or generate a new nonce, all requests from “old” forms Will
> fail. But that is another story.

LOL. So it's another session id?

> But nevertheless the GET problem would be interesting to figure
> out. I will try this once I’m back from vacation.

It's easy to solve with the Tomcat CSRF prevention filter, but the
filter definitely needs a patch to help the application out.

It should be easy to put the "most recent" nonce into the request
scope and then all is well: the application can use it if necessary.

I'm thinking something simple like this:

diff --git a/java/org/apache/catalina/filters/Constants.java
b/java/org/apache/catalina/filters/Constants.java
index 4fe41cd0e8..eba743fb6f 100644
- --- a/java/org/apache/catalina/filters/Constants.java
+++ b/java/org/apache/catalina/filters/Constants.java
@@ -28,6 +28,9 @@ public final class Constants {
     public static final String CSRF_NONCE_SESSION_ATTR_NAME =
         "org.apache.catalina.filters.CSRF_NONCE";

+    public static final String CSRF_NONCE_REQUEST_ATTR_NAME =
+        "org.apache.catalina.filters.CSRF_REQUEST_NONCE";
+
     public static final String CSRF_NONCE_REQUEST_PARAM =
         "org.apache.catalina.filters.CSRF_NONCE";

diff --git
a/java/org/apache/catalina/filters/CsrfPreventionFilter.java
b/java/org/apache/catalina/filters/CsrfPreventionFilter.java
index fff5c2fedb..501c680d74 100644
- --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java
+++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java
@@ -128,6 +128,7 @@ public class CsrfPreventionFilter extends
CsrfPreventionFilterBase {

             nonceCache.add(newNonce);

+
request.setAttribute(Constants.CSRF_NONCE_REQUEST_ATTR_NAME, newNonce);
             wResponse = new CsrfResponseWrapper(res, newNonce);
         } else {
             wResponse = response;

Feedback welcome.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAl3MLocACgkQHPApP6U8
pFhXBg/9Egd0P0FlzfLgl2ygDB4BmJ3YCIsY65mNJedW2+1srj1JL/sa3BhMjA1+
xFAUz4fuYxQff0E61v36HWDkjqyHKUCpN5fBGtxrTg+z03igzH9Jj/Ru5dMUTl+f
mE7Ooyyy45S7/RGAZqKZnN2BccU1P8vZPIhAWNzuLteN6bX2uQPQmlGbwdoIIVq9
vufTHAiCD+lrBgAKVKKeUT2YvjDNckuA8VsE9IdHJBlnUvqxZdzgxy19S1qpNRBs
xvoU/z44Ouyqbdglj04pc1u5zhlWLn8zn54cO+UHbCuavsD7zyjl9/vPjqgx3gOk
8YZbB9VhnD9EpBdy8rbGWJYo12NvyuypnxsG3usGH7sjY9lNEn5VeXXtUGaRW9OK
NT0U/nK8y8vaeS8mTMD3exaaVzDC/7yTvVV29ij3NnyH8fldMQg1FN4CJL9+iPRQ
jO7yx61XZwtrJA2e6l1BIkiXsazCIMp3ZTPfjLse9QRyAhtfo3SFgtgqP19wZaME
rU+C/IuTxbPspGBS2GGNx/YYUt3rvTauEeH/cv/KK7u3HVD0t+mUeNvuYvYCzq6V
6grLKZmlXKuaVfPS7SV/4pGlRnvcVDZKBX3/x2HnNgUxqP0z2tA/oHArXzAd4Zlp
hN4ZFDBFsnA8RdFCKTR3jb6xkZywadmkEG24O2WwYxZOhHtRooY=
=gRAP
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message