Can you please help me to resolve CSRF issue found during using asp.net 2.0.
Issue description :
[1 of 3] Cross-Site Request Forgery
Severity: Medium
Test Type: Application
Vulnerable URL: https://somesite/somepage.aspx
Remediation Tasks: Decline malicious requests
Reasoning:
The same request was sent twice in different sessions and the same response was received.
This shows that none of the parameters are dynamic (session identifiers are sent only in
cookies) and therefore that the application is vulnerable to this issue.
I would suggest reading up on CSRF in order to identify what you want to protect and why. Basically, the issue with CSRF is that an attacker can impersonate you and get back your data. You change this by passing in session information in the request, not just from the cookie. This makes your session secure from this type of attack. Here is a better explanation than I can give:
http://palisade.plynt.com/issues/2008Jun/cross-site-request-forgery/
Here is a two-part article on security issues (including CSRF) and how to address them:
http://palisade.plynt.com/issues/2009Dec/secure-coding-aspdotnet/
http://palisade.plynt.com/issues/2010Apr/secure-coding-aspdotnet-p2/
There is also a CodePlex project called AntiCSRF that makes it easy to fix these types of problems (although it hasn't been updated in a while):
http://anticsrf.codeplex.com/
Related
Is it safe to build an API to provide CSRF one-time use token to avoid CSRF attack? Will this open a new vulnerability?
I have one more doubt regarding the traditional approach of including CSRF. I wonder that providing the csrf token in the form can be scraped and attack may be implemented by the attacker. Please correct me if my thought process in incorrect.
First of all you need to understand how a CSRF attack looks like. Someone can send you a link to http://malicious.com/whatever.html. You open this site and there will be an invisible form, that will send a POST request to http://example.com/account/1/delete. You will be logged into example.com on some other tab, so assuming the session is handled via a cookie, the cookie gets automatically attached and you execute a request you never intended to and are even unaware of.
We can mitigate the CSRF issue via different means, on of the being anti-CSRF tokens. The idea is that there is some kind of secret malicious.com will be unaware of and that can not easily be guessed. Please note, that in the CSRF scenario your means of attack are making people open some link. You have no access to the content of what they are seeing. You just send them a link and expect some requested to be executed with their access rights.
I am working in a Razor pages project. In ASP.NET Core, #Html.AntiForgeryToken() is applied for preventing cross-site request forgery (XSRF/CSRF) attacks.
And I read an article about it:
https://www.red-gate.com/simple-talk/development/dotnet-development/anti-forgery-validation-asp-net-core/
This defense strategy works just as long as the controller’s code that handles the POST double-checks that it is receiving a hidden field named __RequestVerificationToken and a cookie with the same name.
By using postman, I can just simply copy the cookies value and the antiforgery token, and append it with the request so that I can post without visiting the page. And the cookies and token can be used repeatedly.
My question is, how can I do to prevent users/hackers calling the handlers/controllers without visiting the page and ensure that the token only can be used one time?
Do I have to write my own solutions for this? Or Microsoft already provided a solution?
The antiforgery token prevents csrf attacks. It does this by denying post requests that only contain the cookie. If the attacker has access to the antiforgery token then it is over. This is why the token must change when you log in. And it must be invalidated when you log out. It doesn’t necessarily need to change for each request.
https://owasp.org/www-community/Anti_CRSF_Tokens_ASP-NET
There are many strategies. Microsoft does not recommend you add the token to your cookies collection, but if you do, you must use HTTPS. As you know, cookies are exposed in each request. You can strengthen them with HttpOnly and Secure. But if you add HttpOnly, you can't read it yourself.
A better approach is to use headers because your header won't persist after the request is over.
As for Microsoft, here's a good resource: enter link description here
i have a scenario running with an own CALDAV-server and CALDAV-clients like (iOS-calendar, mac-Calendar, Android sync adapter, Thunderbird/Lightning, Outlook Sync, ...)
The authentication so far works via basic auth (https and the "Authentication"-Header).
The CALDAV-clients store the user/password in their configuration.
So far so good, but the issue comes now once the password of the user/account either gets changed, reset, expired, etc.
The server has a restrictive password policy enforced, which locks the account after x failed attempts (e.g. 10).
What is happening now obviously is, that once the CALDAV-client configuration was not updated it continues to use an old password.
The server responds with an 401 not authorized - ok, thats fine apparently again.
But the Clients still continue to use the outdated password. It would be nicer to stop polling and present the user with a dialog that his credentials are not valid anymore. But the clients are out of my control so nothing can be directly done here.
The result: after 2-3 iterations (as most clients tries multiple request in one sync iteration) the account on the server of the user is locked due to too many failed login attempts.
That is not nice. The issue seems to be generic and known as "stale passwords".
A solution could only be a better client handling (out of scope here) or a oAuth-token handling. But i was not able to find anything that standard CALDAV-clients supports this. Only google calendar seems to enforce an oAuth2 authorization before allowing CALDAV communication.
So the question is, is there a good way to improve the bad experience of locked accounts?
Some special 401 response which tells the clients to forget the password or not using it again?
constructive feedback highly welcome.
Edit:
for macOS and ios calendar i found a strange behavior (bug) causing and/or enforcing the described situation.
A standard 401 response will cause the clients to bring up the password dialog as expected and described above. The clients stop polling until a new password is entered - as desired.
In my case the 401 response body contained an inline base 64 image (img src="data..."):
This doesnt lead to a password renewal dialog! Just a "something goes wrong" error state.
The clients are continuing to poll! Locking the accounts after some tries ;(
A solution for this problem than will be to remove the inline image but for me it sounds like a bug that an inline image in the 401 response provokes a different behavior on the client.
Some special 401 response which tells the clients to forget the password or not using it again?
Well, 401 is that response. If the client receives a 401 it knows the the login/password combination it provided doesn't work anymore, and shouldn't retry with the same. Obviously the clients don't do this, partially because:
On the other side your servers x-failed-attempts locking doesn't work with stateless protocols for obvious reasons. HTTP doesn't have that feature builtin. Locking the account is a side effect a client doesn't have to expect when running idempotent HTTP requests.
Assume the client is downloading 10 batches of items concurrently. If the credentials invalidate during this, the account would immediately be locked :-)
Summary: You can't use basic auth naively with backends that lock accounts after n-tries.
Google and iCloud both use token based auth schemes (Google OAuth, iCloud a proprietary one). You can't expect those to work in other clients. E.g. while the Apple clients support OAuth for Google, I don't think they support that for other account types.
So what can you do
I'm reading your question so that you own the account server and that the account locking is intentional and desired. (I.e. it is not a side effect of a different (e.g. SSO) backend system you reach out to.)
I think in this case it should be reasonable to rework your account system to allow unlimited login attempts with just the old password.
The lock-after-n-attempts measure is to protect against people trying different passwords. In your case it is always the same and as a bonus it also matches the old password.
There are a lot of different variations of this approach.
Is it necessary to use CSRF Protection when the application relies on stateless authentication (using something like HMAC)?
Example:
We've got a single page app (otherwise we have to append the token on each link: ....
The user authenticates himself using POST /auth. On successful authentication the server will return some token.
The token will be stored via JavaScript in some variable inside the single page app.
This token will be used to access restricted URLs like /admin.
The token will always be transmitted inside HTTP Headers.
There's NO Http Session, and NO Cookies.
As far as I understand, there should(?!) be no possibility to use cross site attacks, because the browser won't store the token, and hence it cannot automatically send it to the server (that's what would happen when using Cookies/Session).
Am I missing something?
I found some information about CSRF + using no cookies for authentication:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
"since you are not relying on cookies, you don't need to protect against cross site requests"
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
"If we go down the cookies way, you really need to do CSRF to avoid cross site requests. That is something we can forget when using JWT as you will see."
(JWT = Json Web Token, a Token based authentication for stateless apps)
http://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services
"The easiest way to do authentication without risking CSRF vulnerabilities is to simply avoid using cookies to identify the user"
http://sitr.us/2011/08/26/cookies-are-bad-for-you.html
"The biggest problem with CSRF is that cookies provide absolutely no defense against this type of attack. If you are using cookie authentication you must also employ additional measures to protect against CSRF. The most basic precaution that you can take is to make sure that your application never performs any side-effects in response to GET requests."
There are plenty more pages, which state that you don't need any CSRF protection, if you don't use cookies for authentication. Of course you can still use cookies for everything else, but avoid storing anything like session_id inside it.
If you need to remember the user, there are 2 options:
localStorage: An in-browser key-value store. The stored data will be available even after the user closes the browser window. The data is not accessible by other websites, because every site gets its own storage.
sessionStorage: Also an in browser data store. The difference is: The data gets deleted when the user closes the browser window. But it is still useful, if your webapp consists of multiple pages. So you can do the following:
User logs in, then you store the token in sessionStorage
User clicks a link, which loads a new page (= a real link, and no javascript content-replace)
You can still access the token from sessionStorage
To logout, you can either manually delete the token from sessionStorage or wait for the user to close the browser window, which will clear all stored data.
(for both have a look here: http://www.w3schools.com/html/html5_webstorage.asp )
Are there any official standards for token auth?
JWT (Json Web Token): I think it's still a draft, but it's already used by many people and the concept looks simple and secure. (IETF: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-json-web-token-25 )
There are also libraries for lot's of framework available. Just google for it!
TL;DR
A JWT, if used without Cookies, negates the need for a CSRF token - BUT! by storing JWT in session/localStorage, your expose your JWT and user's identity if your site has an XSS vulnerability (fairly common). It is better to add a csrfToken key to the JWT and store the JWT in a cookie with secure and http-only attributes set.
Read this article with a good description for more info
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
You can make this CSRF protection stateless by including a xsrfToken JWT claim:
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
So you will need to store the csrfToken in localStorage/sessionStorage as well as in the JWT itself (which is stored in a http-only and secure cookie). Then for csrf protection, verify that the csrf token in the JWT matches the submitted csrf-token header.
I'm writing a REST-ish API service the provides the ability to interact with the end user's data in other 3rd party services (themselves REST APIs) via OAuth. A common example might be publishing data from my service to a third-party service such as Facebook or Twitter.
Suppose, for example, I perform an OAuth dance with the end user and Facebook, resulting in some short-term access token that my service can use to interact with the user's Facebook account. If that access token expires and the user attempts to use my service to publish to Facebook, what sort of error do I return to the user?
401 doesn't seem quite right to me; it seems that 401 would apply to the user's auth state with MY service. 403 seems much more appropriate, but also quite generic.
401 is the way to go. Two excerpts from the RFC2616 which defines the HTTP protocol:
Section 10.4.2 (about 401):
If the request already included Authorization credentials, then the 401
response indicates that authorization has been refused for those
credentials.
This seems to be appropriate for expired tokens. There are authentication credentials, but they're refused, so the user agent must re-authenticate.
Section 10.4.4 (about 403):
The server understood the request, but is refusing to fulfill it.
Authorization will not help and the request SHOULD NOT be repeated.
This should be used when the resource can't be accessed despite the user credentials. Could be a website/API that works only on US being hit by a asian IP or a webpage that has been declared harmful and was deactivated (so the content WAS found, but the server is denying serving it).
On OAuth2, the recommended workflow depends on how the token is being passed. If passed by the Authorization header, the server may return a 401. When passed via query string parameter, the most appropriate response is a 400 Bad Request (unfortunately, the most generic one HTTP has). This is defined by section 5.2 of the OAuth2 spec https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-26
There's nothing wrong with being generic, and it sounds like a 403 status would be relevant - there is nothing stopping you from providing a more human readable version that elaborates in a bit more detail why.
I think the following is a comprehensive list if you have some level of ambition when it comes to error responses.
400 Bad Request
For requests that are malformed, for example if a parameter requires an int between 0-9 and 11 has been sent. You can return this, and in the response body specify parameter x requires a value between 0 and 9
401 Unauthorized
Used only for authorization issues. The signature may be wrong, the nonce may have been used before, the timestamp that was sent is not within an acceptable time window, again, use the response body to specify more exactly why you respond with this. For the sake of clarify use this only for OAuth related errors.
403 Forbidden
Expressly to signify that an operation that is well formed, and authorized, is not possible at all (either right now, or ever). Take for example if a resource has been locked for editing by another user: use the response body to say something along the lines of Another person is editing this right now, you'll have to wait mmkay?.
403 Forbidden can also have to do with trying to reach resources. Say for example that a user has access to a resource /resource/101212/properties.json but not to /resource/999/properties.json, then you can simply state: Forbidden due to access rights in the response body.
404 Not Found
The requested resource does not exist. Or the URL simply does not successfully map to an API in your service. Specify in response body.
405 Method Not Allowed
This is to represent that the API can not be called with for example GET but another method must be used. When this is returned also you MUST return the extra response header Allow: POST, PUT, etc.