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
Which CSRF token validation is correct? #6735
Comments
AbpAutoValidateAntiforgeryTokenAttribute should be used. I think we should update the documentation. |
When we implement the AbpAutoValidateAntiforgeryTokenAttribute, and an attacker POSTS to our form from an external site, there is no cookie and the validation will be skipped due to the following code in the AbpAutoValidateAntiforgeryTokenAuthorizationFilter:
Based on the comment, we expect the cookie to always exist and determine that the client is a non-browser client if the cookie does not exist. This is unreliable since a malicious web client might not send the cookie, thus skipping the validation. Is this a regression issue that allows for CSRF attacks because the CSRF validation is skipped due to this code? |
So, this can be done using a tool like Postman as well. But, this is how it is designed. |
Could you explain to me how this protects against XSRF attacks?
Thanks in advance. |
We have read the documentation already, as referenced in my initial question, but it doesn't answer my question. Unless we use a token that is part of the form, our endpoint is not protected, because the cookie based validation uses a session cookie that is either correct or does not exist, which in both situations will pass validation. This looks to me like the XSRF-protection does not work properly, unless I'm missing something? |
This could happen if 3rd party website can delete the anti forgery cookie. Normally this shouldn't be possible. |
We don't need to manually delete the token for this attack to bypass validation, since it is a session cookie. It won't exist anymore if the browser was closed since the last visit to the web app. If we did not close the browser after the token was created, it will exist and be automatically added to the request, which will be valid since the cookie was created in the web client. Both situations would pass the validation. |
Do you mean the authentication cookie or anti-forgery cookie ? |
I mean the antiforgerytoken. |
@antheus-s sorry for my questions but I'm trying to understand the case :)
If the browser is closed, you need to visit the page again, isn't that right ? In that case, a new cookie will be generated. Or maybe I totally misunderstand the case here. |
@ismcagdas, no problem of course. Good communication is essential. :P Non-browser clients presumptionIn the current implementation of the AbpAutoValidateAntiforgeryTokenAuthorizationFilter, we skip validation if no CSRF token cookie is sent in the request, because we expect this situation to only occur with non-browser clients. The problem with this presumption is that it is not correct for all situations. If we go to a malicious site with a new browser session, meaning the browser was fully closed and is reopened, and we send a request from the malicious site to a public API endpoint, we do not send the cookie because it does not exist yet until the user has visited the web app. This would make CSRF attacks, such as Login CSRF attacks, possible because we skip validation if the cookie does not exist yet. An issue with storing the token in a session cookieIf we visit the web app, the CSRF token cookie will be created. If the user leaves the web app, but keeps their browser open, the cookie will stay alive since the browser session has not ended yet. If we now visit a malicious site and they execute a request to our web app from their domain, it means that the cookie will be sent in the request from the malicious domain, for example utilizing a hidden form that is submitted from JavaScript or a Fetch API request with credentials included, which would also make CSRF attacks possible because the validation would pass. This would also work with protected endpoints if cookie based authentication is used and the user logged into the app in this browser session. My questionThe things I describe above have let me to believe that CSRF is not working properly. |
@ismcagdas Is this being investigated? For our ISO certification, we need to know whether this is an issue that needs to be picked up. |
@antheus-s we didn't have time to investigate it, sorry. Do you have any suggestion how this should work ? Maybe it can help us to understand the problem in a better way. |
The issue is related to ABP solutions that use cookie based authentication. In my previous comment, I describe that the assumption "No need to validate if antiforgery cookie is not sent. That means the request is sent from a non-browser client." is incorrect. Currently, for example, the user could be logged in from an external site (Login CSRF attack), because as long as the user has not yet visited the app page, the cookie won't exist, meaning that CSRF validation will be skipped. If the user has already visited the app page in their current browser session, then the cookie would be still be valid, meaning that CSRF attacks would still be possible. This issue is caused by the fact that the cookies that are sent in a request are based on the URL of the request, not the current site. So if https://evil.com sends a request to our https://app.abp.com/login endpoint, the validation will pass, because the existing CSRF token cookie will be added to the request. Using some simple JavaScript, we could submit a form on https://evil.com, just by visiting the page, without the user ever noticing, which would have impact on their session in our app. To summarize, we only have protection for situations where someone specifically creates their own cookie with an incorrect token. I suggest that we remove the code that skips validation if the cookie is absent and therefore force non-browser clients to use a different endpoint, which can be made accessible by using the IgnoreAntiforgeryTokenAttribute. In our solution, we made it possible to share protected endpoints by using middleware to enable both token based and cookie based authentication, based on whether a token has been provided. But in my opinion, this is beyond the scope of ABP. |
We migrated from .NET Framework to .NET 6, but still use AngularJS with Razor pages and cookie authentication. Our login page is a plain Razor page that is provided by our AccountController. We noticed that when we use the AbpAutoValidateAntiforgeryTokenAttribute as filter for our controllers, that it does not work on the login page if you delete the CSRF cookies, which also allows for CSRF attacks if you login from a different domain that contains a login form like this one:
If we use the AutoValidateAntiforgeryTokenAttribute from .NET, as a replacement for the AbpAutoValidateAntiforgeryTokenAttribute from ABP, it all works properly.
Based on the documentation, we only need the .NET attribute, yet in the MVC Startup class, I see this:
If I use both, I am able to skip CSRF validation.
What is the correct implementation?
Info:
The text was updated successfully, but these errors were encountered: