Skip to content
Advertisement

Cross-origin CSRF token check fails

I have website www.example.com which loads iframe from www.another.com. The page being loaded contains a HTML and JS which triggers an AJAX call to self (www.another.com). Both of these sites are behind HTTPS.

The iframe loads perfectly fine, the script is executing, BUT, when I click submit (which is part of iframe), I get that www.another.com rejected my request due to invalid CSRF token. The form within iframe does contain a token field, which has a value (some hash).

The ajax call works fine when I go directly to www.another.com.

From what I can grasp so far when ajax call arrives at the server it does not have session started, so it fails to find a token to match.

I use Symfony 4.4 with NelmioCorsBundle to ensure proper CORS. The config looks like this:

nelmio_cors:
    defaults:
        allow_credentials: false
        origin_regex: false
        allow_origin: ['https://www.example.com','https://www.another.com']
        allow_methods: ['GET', 'OPTIONS', 'POST']
        allow_headers: ['Origin','Referer']
        expose_headers: []
        max_age: 3600

Failing ajax request has a following headers: enter image description here

Is there any way to work around this?

Advertisement

Answer

Found a solution.

The domain www.another.com was sending Cookie header with SameSite=lax. That means that those cookies are not to be included unless top-level navigation is initiated. In the case of iframe AJAX call, that just won’t cut it.

A workaround for this is to disable SameSite in framework.yml.

session:
        cookie_samesite: null <--- THIS

I am well aware of potential security ramifications, but:

  • the AJAX POST endpoint is protected by CSRF token,
  • Both of these sites are HTTPS

… so I guess I am going to be fine. Am I?

I am really looking forward to hearing if there is a more serious problem than the one I outlined above 🙂

Another matter I wanted to point out is how my CORS configuration was not really irrelevant. All of my requests are “simple” ones, and thus do not trigger preflight requests.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement