Over a million developers have joined DZone.

Defenses vs. Injection Attacks

DZone 's Guide to

Defenses vs. Injection Attacks

Learn from a cybersecurity specialist how to defend your web app against the nastiest and most common vulnerabilities out there today.

· Web Dev Zone ·
Free Resource

This article is featured in the new DZone Guide to Web Development. Get your free copy for more insightful articles, industry statistics, and more!

Injection attacks are remarkably common. In fact, they’re the backbone of most exploits; after all, in order to compromise a system, an attacker needs to inject something into the system that executes. We see this same pattern in remote code execution exploits, SQL injection, cross-site scripting, request forgery attacks, and so on. Most modern development platforms support defenses against these kinds of techniques out of the box simply by setting a few configuration parameters. And, the vast majority of developers leave it at that without really understanding what those defenses do.

Well, we’re going to fix that today.

Input Filtering and Content Marking

We can look at these kinds of defenses as falling into two distinct categories: input filtering or content marking. Content filtering involves, well, filtering content. We’ve been using these approaches since, roughly, the beginning of time. Essentially, this involves scanning all submitted content and ensuring that the content contains no potentially harmful strings, characters, symbols, or other input. We’ve used this technique to scan submitted data in web applications for SQL characters, for example, as well as for submitted JavaScript syntax. The idea is that we can capture submitted SQL or JavaScript, and by capturing those symbols, we can stop them from being stored and potentially executed. Content marking takes a different approach. Here, we somehow flag all known good content and then check for that marker prior to execution. This is a common cross-site request forgery defense. Synchronizer tokens are a common defense against this type of attack today, in many different application delivery platforms.

These approaches are common, but still have significant problems. Content filtering is difficult to implement well, and leads to both false positive and negative issues. Granted, many of these implementations today are well-designed and effective, but they’re not free. Implementing the correct filters takes time, thought, and experience; and processing every submitted input string has a significant computational cost, especially at scale. Tagging approaches, fortunately, tend to scale and can be implemented at the application server level, but they also lead to more complexity, require additional processing, and can be difficult to implement.

With that in mind, let’s take a look at the different types of injection attacks and their corresponding attack models to understand how to best craft a defense for each approach.

SQL Injection and XSS Defenses

Today, XSS and SQL Injection attacks are highly focused on filtering. This makes a certain amount of sense—both attack models are the same, though the targets differ. 

Image title

Figure 1: shows the attack models of various XSS and SQL injection attacks.

Stored XSS attacks involve injecting content through the application server into the underlying data store, where the injected script is eventually sent to the target browser. Reflected XSS attacks are usually instigated via some external program, like an email client, chat program, or SMS client that coerces the user to click on a specially-crafted URL with a script payload, which is reflected from an application server back to the client with the trust properties of the reflecting server. DOM XSS attacks inject a script payload into the browser DOM, where it is extracted and executed by the browser. Finally, SQL Injection attacks send specially-crafted data to the application server, which then forwards that data to the underlying data store where that data is interpreted as valid SQL directives. Note that the first stages of stored XSS and SQL Injection attacks are the same - injecting content into the data store.

All mainstream defenses against these attacks use filtering in one form or another but in very particular orders. OWASP goes into detail with respect to what kind of filtering happens in what order to defend against which types of attacks—suffice to say that it’s complex, and you see developers messing the order up all the time (Ever see “&” in a dynamic section of a web site? This is why). Escaping content is straightforward, even if the ways you need to combine the escaping isn’t, but it ends up being pretty obtuse. CSRF defenses are much more interesting and more difficult to understand.

CSRF Defenses

First, in order for any of these defenses to work, you can’t have any XSS vulnerabilities. XSS isn’t required to make CSRF work, but it does give attackers the ability to circumvent every CSRF defense. The simplest way to detect CSRF attacks is to just confirm that the target and origin URLs are the same. If they are, there’s no cross-site activity—nothing to see here, go ahead and fulfill the request. We do this by checking the origin or referrer HTTP header values (or both) and comparing them to the target HTTP header value. While this approach can give you insight into the validity of a request, these headers frequently don’t exist and are modifiable in a variety of ways. This isn’t really sufficient to defend against CSRF, and may not even be necessary, as it’s so easy to alter.

The other three CSRF specific defenses include synchronizer tokens, double submit cookies, and encrypted tokens.

Synchronizer tokens are randomly generated values that an application server inserts into sensitive elements as a hidden field or within a URL (think forms, images, and any other tag that will initiate an HTTP request). The server will then extract this token and compare it to the token saved in the user session, rejecting the request if the two don’t match. Usually, this is maintained for an entire user session, though it can be implemented at the request level as well (though this approach leads to problems, like using the back button or bookmarking a site).

Furthermore, including the token in the URL can lead to token leaking. URLs are frequently saved in logs and browser histories, where they can be accessed by attackers and used to circumvent CSRF protections.

Double submit cookies take advantage of the fact that attackers can’t access cookies when crafting CSRF requests due to same-origin policies baked into browsers. Basically, a server submits a random value as a cookie separate from the session ID cookie. The client then inserts this random value into a hidden field (or similar) where the random value can be validated by the receiving server. This way, the server need not maintain any state; the cookie and the hidden field are delivered by the client on resource requests, and the server has access to both pieces of data, allowing it to validate that they are in fact both equal. Keep in mind though, cookies aren’t always available, and with cookies, you can run into subdomain issues as well.

Encrypted tokens are the final CSRF defense in use today. This is similar to the double submit cookie approach, in that some combination of a user ID, a timestamp, and a nonce are inserted into a data structure that is then encrypted by the server, using a stored key. The token is submitted to the client in a hidden field in generated HTML. The client then uses this encrypted value with any HTTP requests sent to the server, including the value in either HTTP attributes or hidden fields. When the server receives this token, it will decrypt the token with its stored key and compare the extracted values, using the timestamp to protect against replay attacks.

This is the state of the art today with respect to injection attack defenses—either SQL Injection, XSS, or CSRF attacks. When looking at them in order like this, the evolution of synchronizer tokens into double submit cookies, which then branched out into encrypted tokens, becomes clearer. Note that none of these defenses are perfect, some have significant scalability problems, and standard browser use cases (e.g. saving page or using the back button) can cause the defenses to fail and deny service to legitimate users. Nevertheless, you need to protect against these kinds of attacks, and these are the best ways to do it today.

This article is featured in the new DZone Guide to Web Development. Get your free copy for more insightful articles, industry statistics, and more!

web dev ,web application security ,sql injection ,cross site scripting

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}