Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strengthen CSRF validation. #48

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Strengthen CSRF validation. #48

wants to merge 1 commit into from

Conversation

ghost
Copy link

@ghost ghost commented Oct 21, 2018

While doing CSRF validation, CppCMS is using "_csrf" value from the session. The "_csrf" value itself is generated in session_interface::save member function for new sessions. Validation will succeed if "_csrf" session value is empty or "_csrf" session value equals to "_csrf" POST data (or header value).

In normal situations, this works as expected because the form must be rendered before it is submitted. In the first GET request, session is initialized and "_csrf" value is set. In the subsequent requests, the _csrf value will exist in the session; thus validation will be in place.

Now, let's consider this situation:

  • Attacker gets all information about the form by inspecting HTML code.
  • Then post form data with cURL without any session cookie values and hidden "_csrf" variable and header.
    In this case, CppCMS will consider these requests as new session. But since "_csrf" value in the session is not generated until the response is written back; CSRF validation will succeed silently.

Maybe, we should change validate_csrf_token's logic as:

  • if session[_csrf] empty, then return false.
  • if token is empty, then return false.
  • if session[_csrf] == token, return true; otherwise return false.
    After this change, if the session is new and it's POST method and form::load is called; CSRF validation will throw an exception (as expected).

Thank you.

@artyom-beilis
Copy link
Owner

the point is that if there is no cookie than there is no log-in/log-in session and thus the request isn't CSRF since it does not bring any credentials with it.

By design - no session - no CSRF validation since there is no forgery without session.

@ghost
Copy link
Author

ghost commented Oct 21, 2018

But isn't it supposed to protect POST request even if there is no cookie, no log-in?

With the current form, if attacker knows the structure of the form, then can POST directly with cURL and validation will be no-op. My opinion is that framework should give 403 error and force client to make a GET request at first.

@artyom-beilis
Copy link
Owner

If I know the session content/cookie I can create perfect request even with the CURL.

Why we add csrf. To prevent unintended POST for users that are logged in and have session. You need to protect your forms when somebody unauthorized tries to POST something and he does not have permission (this is why session exists)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant