Understanding and Preventing CSRF Attacks
While there are many prevailing Cross-site scripting attacks on the internet today, CSRF attacks remain one of the highest according to the OWASP Foundation.
A Cross-Site Request Forgery occurs when an attacker carries out a transaction using a malicious website, email, blog, instant message, or program causing a user’s web browser without their knowledge to perform an unwanted action on a trusted site for which the user is currently authenticated. A malicious HTTP request is slipped into the user's web browser by the attacker so that when it is called, the web application takes the action desired by the attacker.
The impact of a successful CSRF attack is limited to the loopholes exposed by the vulnerable application. For example, this attack could result in the unauthorized transfer of funds, change of password, or purchase in the user’s context.
The security problem is caused by the statelessness of the HTTP protocol, since after a one-time authentication the browser implicitly sends its session data to the server every time. If the CSRF attack goes undetected, the web application becomes vulnerable.
CSRF has the following characteristics:
- Involves websites or web apps that rely on a user’s identity.
- Exploits the site’s trust using that identity and tricks the user’s browser into sending HTTP requests to a target site.
- Involves HTTP requests that have harmful side effects.
While CSRF refers to any form of data change via HTTP request, session riding refers to data manipulation through a valid user session. Session riding is a special case of CSRF where the session identifier is transported using basic/digest authentication or a cookie.
In a nutshell, a typical CSRF attack happens as follows:
- The attacker leads the user to perform an action like visiting a web page or clicking a link. This action sends an HTTP request to a website on the user's behalf.
- The request is processed as a legitimate request from the user if an authenticated session is active on the trusted website.
How are CSRF Attacks Executed?
In the OIDC flow, CSRF attacks can occur against client callback URL where an attacker injects their own authorization code or access token that can induce the client to use an access token associated with the attacker’s protected resources rather than the user’s.
CSRF vulnerability is based on the user's active session which is authenticated using session management.
Typically, Session Management on a web application is based on cookies. With each request to the server, the browser sends the related cookie that identifies the current user's session and the specific actions the user can perform on the website. Any request sent with these HTTP credentials or cookies will be considered legitimate even though the user would be sending the request on the attacker’s command from a different website.
An attacker could authorize an authorization code to their own protected resources on an authorization server. They can then abort the redirect flow back to the client device and trick the user into executing the redirect back to the client. The client receives the redirect, fetches the token(s) from the authorization server, and associates the user’s client session with the resources accessible with the token.
The user accesses resources on behalf of the attacker while the resulting impact depends on the type of resource accessed. For example, the user may upload private items to an attacker’s resources. Or, when using OAuth in third-party login scenarios, the user may associate his client account with the attacker’s identity at the external Identity Provider. In this way, the attacker could easily access the user’s data at the client by logging in from another device with his credentials from the external Identity Provider.
CSRF using GET and POST Requests
Clients MAY use the
HTTP GET or
HTTP POST methods to send the Authorization Request to the Authorization Server.
GET method should not be used to perform state changes and should never cause any data changes.
However, some web apps still use
GET instead of
POST to perform state changes for operations such as changing a password or adding a user.
When the users click the link provided by the attacker using social engineering, they are directed to the attacker’s malicious site. This website executes a script that triggers the user’s web browser to send an unsolicited request without the user being aware. However, on the server side it appears as if the user sent the request because it includes cookies used to verify that the user's identity.
Most state-changing requests are done using
HTTP POST requests. This means that web apps are more likely to accept
POST instead of
GET when a state change is involved. In the case of
POST, the user’s browser sends parameters and values in the request body and not the URL as in the case of a
POST request, as soon as, the page loads.
Preventing CSRF Attacks using OIDC
In OIDC, the ‘state’ parameter is used to mitigate CSRF attacks. In order to prevent CSRF attacks on callback, the client needs to implement CSRF protection by checking that the state parameter exists in the user’s session when an authorization code response arrives in exchange for the access token to the client callback URL.
Important OIDC Standard Considerations
In the OIDC flow, the CSRF attackers initiate the attack during the Authentication Request. Thus, here are some important definitions to know.
An Authentication Request is an OAuth 2.0 Authorization Request that requests the end-user to be authenticated by the Authorization Server.
OpenID Connect uses the following OAuth 2.0 request parameters with the Authorization Code Flow:
|scope||String||Required||OpenID Connect requests MUST contain the |
OAuth 2.0 Response Type value that determines the authorization processing flow to be used, including what parameters are returned from the endpoints used. When using the Authorization Code Flow, this value is
|client_id||String||Required||OAuth 2.0 Client Identifier valid at the Authorization Server.|
|redirect_uri||String/url||Required||Redirection URI to which the response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered at the OpenID Provider. The Redirection URI MAY use an alternate scheme, such as one that is intended to identify a callback into a native application.|
|state||String||Optional but Recommended||Opaque value used to maintain state between the request and the callback. Typically, Cross-Site Request Forgery (CSRF, XSRF) mitigation is done by cryptographically binding the value of this parameter with a browser cookie.|
In the case where the OIDC flow is initiated by an IdP, the CSRF attack cannot be prevented by them because the
state parameter needs to be generated and managed by the client in order to correlate the
state with the application user’s session.
One possible solution which can be performed by the client to mitigate CSRF attacks in IdP initiated OIDC requests, is by verifying the ‘Referer’ headers of the incoming HTTP requests.
Custom Request Headers
Custom HTTP headers such as
XMLHttpRequest. If a request comes into a REST endpoint without the custom header, then the request will be dropped.
To use custom headers as a CSRF defense, a site must issue all state-modifying requests using
X-Requested-By header with the value
XMLHttpRequest. Google Web Toolkit also recommends that web developers defend against CSRF attacks by attaching a
X-XSRF-Cookie header to
XMLHttpRequest that contains a cookie value. The cookie value is not actually required to prevent CSRF attacks since the mere presence of the header is sufficient. For example, to defend against login CSRF, the site must send the user’s authentication credentials to the server via
This works because
XMLHttpRequest does not allow an attacker to make a request to a third-party domain by default. Thus, it is not possible for an attacker to forge a request with a spoofed
X-Requested-With header. You can simply verify the presence of this header and value on all your server-side AJAX endpoints in order to defend CSRF attacks. This approach does not require UI changes or server-side state changes which is particularly useful for REST services.
XMLHttpRequestor similar technology.
A request with custom headers causes the browser to automatically send a request to the endpoint using the
OPTIONS verb. If the server-side application recognises the
OPTIONS request, it will reply with a header showing which headers will be allowed from the calling domain.
The attempt to send
X-Requested-With in a cross-domain POST results in an OPTIONS request requesting this header be allowed.
If the server-side is not explicitly configured to allow this (i.e. no
Access-Control-Allow-Origin to allow the domain and no
Access-Control-Allow-Headers to allow the custom header), The header is not allowed because the domain is not configured for CORS.Therefore if CORS is not allowing the attacker’s domain to send extra headers, it mitigates CSRF.
Here are the steps to follow:
1. Set the custom header in every AJAX request that changes the server-side state of the application. Example:
2. In each server-side method handler, ensure a CSRF check function is called.
3. The CSRF function examines the HTTP request and checks that
X-Requested-With: XmlHttpRequest is present as a header. If it is present, it is allowed. If it isn’t, an
HTTP 403 response is sent and logged in the server-side.
We've come to the end of our discussion on Preventing CSRF Attacks. If you have any questions or need to know more, please contact our support team for further assistance.
We'll be happy to help. Thank you!