[π] ngx-cookie-service makes CSRF challenge hard to solve
See original GitHub issueπ Bug report
Description
Sorry for the long description, but I think this is a tricky oneβ¦
Current situation
The CSRF Challenge is hard to solve in its current state, as it requires the use of seriously outdated browsers (see issue #1421) for the attack to work. While this was initially thought to be a consequence of changing cookie defaults (SameSite=Lax
instead of SameSite=None
) advocated by initiatives such as Incrementally Better Cookies (see #1421), the behavior cannot be attributed only to this.
Another explanation
A closer look revealed the following connection to a third-party dependency:
- The CSRF Challenge was included in Juice Shop with PR #1322 and introduced with release 10.1.0 in March 2020.
- The same release switched from the NPM package
ngx-cookie
tongx-cookie-service
for the handling of cookies in the JavaScript frontend, see commit 1c68c55d78c1c8745a5d6002c84786c3abb5e9e4. - In the same month,
ngx-cookie-service
switched the default for new cookies toSameSite=Lax
, see https://github.com/stevermeister/ngx-cookie-service/commit/0cb4839f50b7effd1dee9abe64e4110363f44ccb.
This resulted in a changed behavior when setting new cookies.
Role of e2e tests
As Google gradually rolled out SameSite=Lax
in Chrome during the same time, the failure in the e2e test as discussed in #1421 was attributed to that rollout and not to the changed behavior of ngx-cookie-service
.
Current impact on the CSRF challenge
The frontend sets the token cookie using the set
method of CookieService
: https://github.com/bkimminich/juice-shop/blob/e07059edd3b4ed0527add13d0dd5c8570daa3bcc/frontend/src/app/login/login.component.ts#L78
The optional SameSite
parameter is not specified by the frontend, which causes ngx-cookie-service
to set it to Lax
before passing the call to the cookie API of the browser. The default behavior of the browser does thus not matter, as it is only considered when the value for SameSite
is left unspecified.
Overall, the CSRF challenge is thus unnecessarily hard to solve, as it requires very old browser versions which do not have support for the SameSite
attribute (e.g. Firefox versions < 60). In comparison, even versions of Firefox as of February 2021 still set cookies with SameSite=None
by default and it should thus still be reasonably easy to solve the challenge.
Suggested solution
To make the challenge solvable with more browsers, the frontend should use a cookie library which keeps the SameSite
attribute unspecified when setting the token cookie. ngx-cookie-service
will always specify a value before calling the browser API and is thus not suitable. Explicitly specifying SameSite=None
is not an option, as it also forces the Secure
flag to be set, which breaks usage on localhost
and other unencrypted deployment scenarios.
Is this a regression?
No. The issue exists since the CSRF challenge was released in Juice Shop 10.1.0.
π¬ Minimal Reproduction
- Verify that the browser used for the test defaults to
SameSite=None
, e.g. using https://samesite-sandbox.glitch.me/ - the entry for βCross-site?β in the first line should say βsetβ. - Follow the steps for the documented challenge solution.
- Observe that the cookie is not sent in the request to the profile page, the challenge is not solved.
π₯ Exception or Error
The exception for missing session cookie is shown.
π³ Your Environment
Tested with release 10.1.0 and the latest develop branch.
Additional Information
Tested with Firefox 73.3.0esr on Kali Linux.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:27 (20 by maintainers)
Top GitHub Comments
Okay @bkimminich! Iβll come up with a PR shortly.
Hands down, this is probably the best bug report Iβve ever read in my entire professional and open source carreerβ¦ π
π Looks like weβre looking for a slightly less security aware cookie module then! Ideas are welcome.