DEV Community

loading...
Cover image for Common attack targeted at web applications

Common attack targeted at web applications

pauneren profile image Pauneren ・5 min read

Understanding and preventing CSRF attacks
What is Cross-Site Request Forgery (CSRF)?
Cross-Site Request Forgery (CSRF) (pronounced sea-surf) is a The attack occurs when a website allows a browser to perform a sensitive action but does not validate that the user that issued that action. This provides the opportunity for an attacker to submit a request to the target web application unbeknownst to the user.

Potential target sites include social media, webmail clients, online banking, and network device administration interfaces.
Key concepts
While a user is logged into the target site, an attacker can coerce the user’s browser to perform actions on the target website.
The vulnerability exists in the affected web application, not the victim’s browser or the site hosting the CSRF.
How the attack work?
The attacker is exploiting how the target web application manages authentication. For the exploit to work, the victim must be authenticated against the target site. For instance, let’s say bank.com has online banking that is vulnerable. If the user visits a page containing a CSRF attack at bank.com but they are not currently logged in, then nothing happens. If the user has logged into the target site, an attacker can coerce the victim’s browser to perform actions on the target website.

GET requests.
For example, if “ bank.com “ is designed to use GET requests for performing actions such as funds transfers (this is bad design but let's use it for sake of demonstration). If the attacker is aware of how to craft the exploit URL, then they can use the img element to get the browser silently load the page.
Below is an example of an HTML image element containing an exploit URL:

img src="http://bank.com/app/transferFunds?amount=500&destination=12345"
This is usually done with one of the following techniques:
sending an unsolicited email with HTML content
planting an exploit URL or script on pages that are likely to be visited by the victim while they are also doing online banking.
The exploit URL can be disguised in several ways.
As an ordinary link, encouraging the victim to click it:

a href="https://bank.com/app/transferFunds?amount=500&destination=12345"
Reset Password
</a

Or as an invisible fake image:
img src="https://bank.com/app/transferFunds?amount=500&destination=12345" style="display: none;">

If this image tag were included in the email, the user would not see anything. However, the browser will still submit the request to the target site.
POST requests
A common misconception is that only allowing HTTP POST requests will prevent CSRF attacks. The attacker can create a form using HTML or JavaScript and use auto submit functionality to submit the POST request without requiring the user to click on a submit button.
Here is an example using an HTML form on the attacker’s site:
https://attack.com/csrf.html

body onload="document.frames[0].submit()">
form action="https://bankcom/app/transferFunds" method="POST">
input name="amount" value="500">
input name="account" value="12345">
/form>
/body>

The attacker would use the following iframe element to silently load the auto-submit form:

iframe style="display: none;" src="https://attack.com/csrf.html">/iframe>

The diagram below illustrates the request flow for a CSRF attack using POST requests.

Alt Text

How can I protect my site against CSRF attacks?

The most common approach is to use randomly generated security tokens called nonces to validate that the request was made by the user.
In PHP we can generate a unique token and insert it into the session array below:
$_SESSION["csrf"] = uniqid(mt_rand(),TRUE);
We can use this value when generating a form or link.

When processing the submitted form, we must first check that the token is the same as the one we generated.

$token = isset($_POST['token']) ? $_POST['token'] : '';
$valid = !empty($token) && ($token === $_SESSION['csrf']);

if ($valid)
{
// Legitimate request
}
else
{
// CSRF attempt
}

Nonce:
In cryptography, a nonce is an arbitrary number used only once in a cryptographic communication, in the spirit of nonce word. They are often random or pseudo-random numbers. Many nonces also include timestamp to ensure exact timeliness. Though this requires clock synchronisation between organisations. The addition of a client nonce(“cnonce”) helps to improve the security in some ways as implemented in digest access authentication. To ensure that nonce is used only once, it should be time-variant (including suitably fine-grained timestamp in its value), or generated with enough random bits to ensure a probabilistically insignificant chance of repeating a previous generated value.

CORS (Cross-Origin Resource Sharing) is a system, consisting of transmitting HTTP headers, that determines whether browsers block frontend JavaScript code from accessing responses for cross-origin requests.

Cross-Origin Resource Sharing (CORS) is an HTTP -header based mechanism that allows a server to indicate any other origins (domain, scheme, or port) than its own from which a browser should permit loading of resources. CORS also relies on a mechanism by which browsers make a “preflight” request to the server hosting the cross-origin resource, to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.
An example of a cross-origin request: the front-end JavaScript code served from https://domain-a.com uses XMLHHttpRequest to make a request for https://domain-b.com/data.json.

For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts. For example, XMLHttpRequest and the FETCH Api follow the same-origin policy. This means that a web application using those APIs can only request resources from the same origin the application was loaded from unless the response from other origins includes the right CORS headers.

The most interesting capability exposed by both XMLHttpRequest or Fetch and CORS is the ability to make "credentialed" requests that are aware of HTTP cookies and HTTP Authentication information. By default, in cross-site XMLHttpRequest or Fetch invocations, browsers will not send credentials. A specific flag must be set on the XMLHttpRequest object or the Request constructor when it is invoked.

In this example, content originally loaded from http://foo.example makes a simple GET request to a resource on http://bar.other which sets Cookies. Content on foo.example might contain JavaScript like this:

const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
}
const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain() {
if (invocation) {
invocation.open('GET', url, true);
invocation.withCredentials = true;
invocation.onreadystatechange = handler;
invocation.send();
}
}
Line 7 shows the flag on XMLHttpRequest that has to be set in order to make the invocation with Cookies, namely the with Credentials Boolean value. By default, the invocation is made without Cookies. Since this is a simple GET request, it is not pre flighted, but the browser will reject any response that does not have the Access-Control-Allow-Credentials: true header, and not make the response available to the invoking web content.

Discussion (0)

pic
Editor guide