Hi Alexander,

Alexander Lebedev wrote:
> I want to implement CSRF check with haproxy.
> I want to check cookie value matched the header value and deny request
> if they're didn't equal.

The ACLs are only equipped to compare a dynamic value (e.g. from a
fetch) with a statically define value. It is not possible to compare two
dynamic values.

There is a workaround for this however. It consists in building a
specific dynamic value and checking if that suits your requirements.

The following example shows how this can work. At first, we are building
a new temporary header containing the value from the cookie and the
header concatenated. We have to use a header here since the
concatenation is a log-format statement which is not allowed for
`http-request set var`.

In the ACL, we then check this concatenated value using a specific
regular expression, It checks if the matched string contains the exact
value two times, separated by the equal signs we added in the header value.

When I build this some time ago, we had to declare a back-reference in
the regex for this to work. I'm not sure it is still required, but
shouldn't hurt in any case.

# Build the temporary header
http-request set-header X-CHECK %[req.cook(token)]==%[req.hdr(token)]

# Deny the request if the header value is not valid
acl valid_csrf_token hdr(X-CHECK) -m reg ^(?<cookie>.+)==\1$
http-request deny unless valid_csrf_token

# Cleanup
http-request del-header X-CHECK

This should more-or-less work for your use case.

Two caveats apply:

(1) Your CSRF scheme seems a bit unconventional. For this to be secure,
please also ensure that the cookie is set to HttpOnly and ensure that
that the value your client sets in the header can not be gathered from
outside your origin (and is esp. not indirectly gathered from the cookie
by the client).

(2) The comparison of the values in the ACL is not done in constant
time. That means checking the values takes more or less time depending
on the inputs. An attacker can use this to check a lot of values and
measure the response time of HAProxy. With some statistical checks, an
attacker can learn the value of the user's cookie by triggering several
(probably: a lot) requests and measuring these tiny timing differences.
To actually be secure, you should instead perform the CSRF check in your
application and ensure you use a constant-time comparison algorithm there.

Best,
Holger

Reply via email to