relation between cross site request forgery and login - csrf

I was wondering if there is any relation between login and cross site request foregry ?
My question is, are there sites that have no login required but still require to be protected from CSRF ? Can you give an example

For CSRF to be effective, your site just needs to be able to act on behalf of someone in a way that doesn't require explicit authentication or validation.
Signed in users via auto-login cookies are the most popular CSRF attacks, but e.g. newsletter subscription forms may be just as vulnerable and can cause people to receive unwanted emails from your system to confirm their subscription.
So to answer your question, although login and CSRF are related, they are not exclusive to each other.

CSRF attacks exploit the authenticity of a client’s requests as an attacking site is able to forge requests that are executed by the client in behalf of the client and thus enjoy the server’s trust in the client’s requests. So the server assumes that any request from a client is intended behavior of the user that controlling the client. CSRF exploits this implicit trust.
At this point it is not necessary that the client is authenticated. Although authenticated users generally have special privileges that attacking sites are aiming for, the main goal of CSRF attacks is sending arbitrary requests in behalf of the user without their knowledge. So target sites can also be any site where you need a different originator than the attacking site (e. g. polls, unique visitors, malicious activities, etc.).

Related

Restrict REST API access to only registered site

I have an old question that maybe is asked here many times, but still we are in 2022 maybe there is some better approach to solve this problem.
I have an API that is used by some websites (clients) that is registered in this API, Those clients use this API to display the list of services for private and public users without any authentication.
When the client registered in the API a personal access token is given to send it for each request before using the API to limit abuse of this API.
The problem with an access token in public side, is anyone can intercept it and use it outside of the site generated for wish will cause a lot of cost.
Even if I reduce the lifetime of token to 10 min I still have the risque of abusing with it.
Is there any way to better secure this API other than authenticate the client for each request to get the fresh token with a lifetime in seconds?
To better illustrate the question above this is the use case:
The malicious user connects to the first registered site as the site list the services to the public users, the malicious user intercept the token in the header to the API
The malicious user come to his unregistered site and use the token
All this step can be automatised by the malicious user.
Edit:
I cannot change the client implementation or ask him for any change, I search something to reduce abuse not at 100 % but to make abuse a little complicated, like using origine domaine name, CORS, ...
The vast majority of access tokens used today are bearer tokens. This means that the resource server will accept the token if it is valid, and doesn't care about who has sent that token. You are right, this means that a malicious user can steal your token and use it to call your API. There are more ways for an attacker to steal access tokens, not only MITM attacks (which, as noted in the question's comments are pretty much mitigated by using TLS). You can have XSS attacks if the tokens are made available to a Javascript app, or Man-in-the-Browser attacks, where the token is stolen by a malicious code running in the browser.
These attacks are usually mitigated by using short-lived access tokens (even less than 10 min) and putting rate-limiting in place. This usually is enough to prevent abuse. You can always add additional layers of protection, e.g. drop a token if the caller's IP changes, etc.
If you need stronger protection, then you can have a look at sender-constrained access tokens. These are tokens, that can be used only by the legitimate client. Sending such a token requires the client to present additional proof of possession. This is then verified together with the token itself.
There are different possibilities for implementing sender-constrained tokens, e.g. Certificate-bound tokens or DPoP.

Stateless REST API with CSRF and XSS protection

Is it possible to protect stateless REST API from both XSS and CSRF attacks?
Currently, I'm using JWT token stored in secure/httpOnly cookie for stateless authentication. This should protect the API from most common XSS attack: stealing cookies with XSS-injected JavaScript and sending them to the attacker.
However, this doesn't protect the API from CSRF attack, where attacker would trick the authenticated user to follow a link to the particular web API call to actuate adverse transaction on behalf of the victim. How could I protect the API from this attack without introducing server side state?
Also, is it true XSS vulnerability would inheritedly allow CSRF type attack in the following scenario: Injected JavaScript would retrieve CSRF token from the client side state, DOM or the browser storage and prepare a malicious ajax call to the server. Browser would still automatically include the httpOnly cookie for the same origin request. Is there a way to get protected from this other than protecting from the XSS vulnerability in the first place?
Stateless anti-forgery tokens
The first question is about preventing CSRF without server-side state. The current approach for stateless anti-forgery tokens is the double submit cookie pattern.
CSRF attacks depend on the browser automatically sending the API's own cookies back to it, regardless of where the request originated. The attacker doesn't have or need access to the cookie contents. They only need to trick the user into loading malicious HTML. The double cookie pattern adds a new requirement: the attacker must know and separately send the contents of the anti-forgery cookie.
There are ways for an attacker to overwrite the anti-forgery cookie with their own. So you may want to look at some additional security hardening for this approach. Especially HMAC signing the anti-forgery token to prevent token substitution. Using HSTS and the __Host cookie prefix to ensure transport security and proper cookie scope. And having the client provide the anti-forgery token in a custom header.
The custom header ensures the request must be sent from JS, since HTML-tag-based CSRF attacks cannot set custom headers. Being sent from JS also triggers additional protections. For cross-origin requests it triggers SOP on the browser and CORS validation on the server. The server can also do basic Origin validation.
Regarding the scope of CSRF attacks, here is a note from the OWASP CSRF link at the top.
Forcing the victim to retrieve data doesn’t benefit an attacker because the attacker doesn’t receive the response, the victim does. As such, CSRF attacks target state-changing requests.
XSS question
Yes, an XSS attack could happen that way. Once a malicious script is loaded into JS, it has free reign to use anything accessible to Javascript. Including app code/memory, browser storage, and cookies. Even though HttpOnly cookies are not readable, they can still be sent in requests. A non-targeted attack might look for key data in locations used by popular frameworks. And might try to probe for popular/discoverable API frameworks on the server. A targeted attack means the attacker studied your system and crafted a custom payload for it.
The primary vector for XSS is unsanitized external data (user input, database values, etc.). To prevent XSS, check out these guidelines from OWASP. Of note is that front-end frameworks like Angular, React, Svelte, Vue, and others have built-in XSS protection. Because they sanitize data before rendering it. Example: an attacker enters an HTML string into an input. When it is later displayed, these frameworks HTML-encode the string. So left and right angle brackets are replaced with < and > and so on. This causes the browser to evaluate the string as text instead of runnable HTML. But you can still mess it up in different ways if careless.
XSS attacks can also come from external resources. Maybe a compromised CDN or NPM script. If your deployed code takes dependencies on NPM libraries, pay extra attention to NPM audit warnings. One attack pattern is to attach a small loader (easier to go unnoticed), which will fetch attack payloads at runtime. A CSP policy can help prevent this. Specify an allowed list of resources -- your app assets and API URLs -- and block all others. CSP can also prevent data exfiltration.
For both CSRF and XSS
For attacks on your API, you can additionally employ server-side mitigations. IP-based throttling / temporary bans, unusual activity grey-listing and alerting, etc.
For especially sensitive operations, one strategy is to use an escalated authorization. This could take the form of requiring the user to re-authenticate or use a 2nd factor like a one-time password. This can block automated attacks since it requires active user intervention.
To mitigate attackers using existing escalated authorizations (which may also be in a cookie or app memory), they can have short expirations and be limited to specific operations. To go even further, the approved operations + relevant data can be signed. This will prevent malicious scripts from reusing an escalation to execute the same kind of operation with different data. Even further, these sensitive operations can be idempotent. So if an attacker does resend already-executed operations, they will not cause any additional changes in the system.
Zooming out
Try to engineer your systems to be as uninteresting as possible to hackers. Use trusted external services for sensitive needs like credit cards and credentials. Ideally (from a security perspective) the hacking risk would be reduced to just data vandalism/loss. So in the worst case that a breach happens, it would have little long-term impact. And it could be recovered with common practices, including routinely tested backups. And then further mitigations added for the specific attacks used.
Tread especially carefully with user-to-user interaction. Since this adds more targets and pivot points for hackers -- your user base. The most security-conscious eyes should be on these pieces. Not only for technical dangers like user-to-user XSS attacks, but also social ones. Human weaknesses are the most well-known and easiest to exploit.
Lastly, there is no sense investing in mitigations which have low risk/consequences in your situation. So do not take everything here as a requirements checklist. It's not a complete list anyway. Focus on your biggest risks first. Reevaluate periodically.
You can generate a token (e.g. a UUID) and put it into the jwt token as well as send it back to the client. Then the client sends it during every each request in a header. Then the server can compare the token in the header and the token in the jwt token to make sure the request comes from the client who was aunthenticated.

How does a CSRF attacker authenticate?

Lets say an attacker controlling site B is exploiting the session a user has with site A.
I know that the attacker is able to exploit the trust server A has for the user, but I don't understand how. Explanations of CSRF I have read make it seem like when the attacker makes a request to site A that the browser automatically includes the necessary authentication information because there is an active session and thus the attack is successful.
The 'browser automatically includes the authentication information' is what doesn't make sense to me. In applications I've worked on auth tokens or cookies are sent explicitly by the client code. So if the client code is specifying what header the token is being sent in for instance, how could the attacker know this?

Without Same Origin Policy could an evil site read the CSRF token?

From wikipedia about Same Origin Policy
https://en.wikipedia.org/wiki/Same-origin_policy
The same-origin policy helps protect sites that use authenticated sessions. The following example illustrates a potential security risk that could arise without the same-origin policy. Assume that a user is visiting a banking website and doesn't log out. Then, the user goes to another site that has some malicious JavaScript code running in the background that requests data from the banking site. Because the user is still logged in on the banking site, the malicious code could do anything the user could do on the banking site. For example, it could get a list of the user's last transactions, create a new transaction, etc. This is because the browser can send and receive session cookies to the banking site based on the domain of the banking site.
This part i understood but now...
The user visiting the malicious site would expect that the site he or she is visiting has no access to the banking session cookie. While it is true that the JavaScript has no direct access to the banking session cookie ...
Because the session cookie is httpOnly flagged?
... it could still send and receive requests to the banking site with the banking site's session cookie. Because the script can essentially do the same as the user would do, even CSRF protections by the banking site would not be effective.
Same Origin Policy prohibits Cross-Origin reads. Thus, if we assume that SOP is not enforced, the malicious site could read the CSRF token from the response? Is that the reason why wikipedia is saying that even CSRF protections would not be effective?
Yes, you've understood it. Without the SOP, the malicious script would simply request whatever page has the CSRF token, read it, and then use that token to construct its unsafe requests.
So SOP and CSRF protection are both necessary to protect the user in a world where the browser sends authentication cookies with requests from foreign domains.

Why Having a CSRF protection in a REST context doesn't make sense?

Someone to explain please (hopefully with simple words for newbies) why a web application built upon a RESTful API can be CSRF exempt?
I received such assertion after asking: Serializing FormView data in JSON, but honnestly I can't figure out why?
Thanks in advance
CSRF or Cross Site Request Forgery, in layman terms, is meant to allow only selected sources(your own website) to submit data to particular url. It prevents misuse of your functionality by other websites or robots.
Say, I have an url for registration, /registration/, but I don't want to allow external submission of POST data to /registration/. So, I would provide a crsf cookie(depending on host and other stuff) when GET request is issued for /registration/, and ensure that same cookie is provided with POST request. This will ensure that users who have requested the registration form(i.e. genuine web users, not robots), would be able to register. It is not completely full-proof, but ensures some level of security.
Now, We don't use CSRF in API's due to following:-
Technically, CSRF is stored as cookie, since browser is not the intended client of API's, it is of no use.
Secondly, API's are supposed to use specialized client and user authentication, thereby eliminating the need for using any CSRF protection.
Thirdly, Restful api's are supposed to be stateless, therefore the order of API calls should not matter, which is essential for working of CSRF.
Note:-
If you have frontend framework like Angular or intend to use api's on browser too, then it is perfectly ok to use CSRF. In that case you are suppose to write two types of authentication for your apis.
Token Based Authentication - for non-browser clients
Session Authentication - for browser based clients (With csrf)
In this case, any request to api must authenticate with atleast one of the authentication.
According to owasp.org:
Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious Web site, email, blog, instant message, or program causes a user's Web browser to perform an unwanted action on a trusted site for which the user is currently authenticated.
This is not an issue for REST Web services because either:
1) you usually want your service to be accessible from multiple applications (Mobile app, browser, etc.)
2) you have to provide a direct authentication for each request, so this kind of attack is not applicable for REST services. The authentication is done by your application (let's say javascript) and no directly by your browser (sending the session id), so even if a malicious application redirect the user to your webpage, it cannot automatically trigger your javascript function to perform the request (and the authentication).