If there’s one constant in the modern era, besides the near-ubiquity of technology — or perhaps because of it — it’s security. Actually, it’s security breaches.
In the last 12 months alone, there have been attacks on LinkedIn, there was massive account fraud at Tesco Bank, and a DDoS attack on Singaporean ISP, StarHub.
Whether the breaches involve utility services, such as power stations or the websites and web-based applications which we all commonly use on a daily basis, it’s hard not to feel exposed, wondering if there is anything which we can do.
As a software developer, security is something which, I’ll be honest, concerns me yet I’ve not been as diligent with as I should be. But in recent times, it’s risen to near the top of my consciousness, alongside software craftsmanship.
Given that growing sense of unease, I sought out to learn how to protect better the application’s which I am involved in developing.
Use a Web Application Firewall
The first idea that came to mind was to use a web application firewall (WAF). It makes sense, right? Firewalls have, for the longest time, been considered a critical line of defense against attacks from outside of an organization.
If you’re not familiar with the term, a WAF is a special-purpose firewall for HTTP/S-based applications. Quoting OWASP:
It applies a set of rules to an HTTP conversation. Generally, these rules cover common attacks such as cross-site scripting (XSS) and SQL injection.
While proxies generally protect clients, WAFs protect servers. A WAF is deployed to protect a specific web application or set of web applications. A WAF can be considered a reverse proxy.
A WAF is better than a standard firewall, as it can filter and inspect traffic analogous to a conversation for an application. As such, they’re a firewall customizable to the needs of a particular application.
However, they’re a mixed bag of a solution. For example, when a WAF inspects traffic, they have only limited contextual information to work with as they only see one raw packet at a time. This individual packet won’t mean a lot from an inspection perspective. Does it have any bearing on the previous one? Is it related to the one afterward?
What’s more, when analyzing packets WAFs use a set of patterns to analyze incoming packets against. Depending on their configuration WAFs can either be overly permissive or worse, overly protective, generating false positives or false negatives.
Consequently, using WAFs for application protection can be a rather brute-force — or blunt — approach. What’s more, they are hard to configure, unless you’re a security or networking expert, something not many software developers are. Then, in addition, firewall configurations need to be maintained. It’s not a set-and-forget affair.
But, they have the potential to block up to 62% of current attack vectors, such as SQL injection, Cross-Site Scripting (XSS), and Cross-site Request Forgery (CSRF).
What’s more, over the course of time, as the application evolves the configuration can be continuously refined. Then there’s their ability to perform virtual patching when a defect in an application is discovered. Virtual patches are a way to temporarily patch an application defect without having to change any application code.
Web Application Firewalls Are Not Perfect
Sounds like a, largely, ideal solution, right? Well, after investigating them further there may be more drawbacks than there are advantages — depending on your available budget.
They Can Generate False Positives and False Negatives
Let’s look at potentially the most serious two. When inspecting traffic, as I touched on earlier, WAFs assess packets against a set of predefined patterns to determine what to do with it. Let’s take the one below as an example, taken from an excellent talk on web application firewalls:
if ($path == "/admin") {
if ($ipaddr == $internal_ipaddr)
[block request]
else
[allow request]
}
In this pattern the WAF is checking if the path requested within the application is /admin
as well as the IP address of the client making the request. If the request is to /admin
and, oddly, if the client’s IP address is on the internal network, then the request will be blocked. However, if the client’s IP address was from outside the network, then the request would be let through.
Here, we see an example of a rule that will generate a false negative. This is a rule where a malicious request was not correctly detected, and therefore not correctly defended against. Then there are false positives, where a request which is actually legitimate, are marked by the WAF as being malicious and therefore blocked.
Can Easily Be Bypassed
Now what about being able to bypass the protection which a WAF offers? Remember, that most WAFs use software, which in turn may have vulnerabilities, which can be abused. WAFs commonly do what’s referred to as fail open or fail close in the event of too much traffic.
A fail open is where the WAF reverts to monitoring only, or less, effectively letting all traffic through. A fail close is the opposite. All traffic is blocked. In either case, either by implementing a DoS or a DDoS attack, you could break through the WAF, or cause it to prevent access to the application entirely.
Then there are a number of other ways to bypass, or abuse, them or the rules which they implement. How about faking where the request is coming from, by sending an X-Forwarded-For
header.
But let’s say that there was a rule that validated a field, but it was case-sensitive. You could send a custom request using mixed-case, and bypass the rule, allowing the request to get through to the protected application, perhaps breaking it. These are just a few ideas. There are an extensive number of others.
No Protection Against 0-Day Exploits
While WAFs can protect against known vulnerabilities, they can’t against 0-day exploits. A 0-day exploit is a vulnerability in an application which is unknown to an application vendor, yet is known to an attacker. The attacker can then make use of it to exploit the application, providing no opportunity for the vendor to rapidly defend against it. Given that, there is no way that a WAF could protect against these types of attacks.
The Complete Solution Cost
Despite the fact that WAFs are much more attuned to applications, that doesn’t mean that out-of-the-box they “Just Work”tm. Like standard firewalls, they need to be configured and maintained.
In some ways, they need even more work to be setup correctly than a standard firewall, as knowledge of the application is required to ensure that they protect the application properly.
In practice, WAF’s require both security and application experts to be set up and exploited to best effect. If you don’t have the expertise in-house, then you’re going to have to outsource the work. Given that, they’re not a cheap solution.
Professionals experienced in these areas don’t come cheap, and with good reason. Considering the assets which their work protects, you don’t want an amateur fumbling around.
Maintenance
Like many things, web application firewalls also need to be maintained. Once they’re set up, they need to be supported. Consider how often web applications change, how often new features are demanded, how often the computing landscape shifts from month to month.
Developers, as a rule, are a very creative bunch of people. We love to try new things, experiment with new technologies, trends, and ideas. What’s more, marketing departments are always encouraging customers to become ever more demanding.
Combine all of these factors, and you end up with applications which can change on a daily basis. Given that, if you’ve deployed a WAF as part of your application’s security policy framework, features can no longer be designed and implemented in isolation. The impact of those features needs consideration in tandem with the WAF.
Take the virtual patching functionality I mentioned before. Let’s say that one or more patches are in place to handle defects in the application and that a patch is being deployed to fix it. Then the WAF’s configuration needs to be updated as part of the release process and ideally documented.
Then there are new attack vectors and zero-day exploits to consider. In short, like a standard firewall, someone needs to stay up with broader security challenges, along with the changing security surface of your application(s), and maintain the WAF accordingly. Neither are trivial processes.
All of these changes, as rapid as they are, as you can imagine, compound the central challenge of WAFs – false positives and negatives. I’m not saying these things as a recommendation against using a web application firewall, but to keep the discussion properly grounded.
Performance
Now let’s consider performance, ever a critical consideration, one which varies based on a variety of factors, including how the WAF is implemented. WAFs come in many shapes and sizes.
Each of them has different performance implications, outside the scope of this article to discuss to any significant level of depth. So, I’ll be broad, yet concise.
Will you put the application behind a WAF which inspects all traffic to and from the application, before being allowed to continue? Alternatively, will it operate in a less active role of monitoring, yet not interfering with the application traffic?
In the former case if the rules are incorrect, legitimate traffic could be blocked, effectively breaking the application. It could also introduce sufficient latency that the application is effectively broken.
The latter case while not actively protecting the application at that moment, would likely not have the same performance impact.
How about integrating the WAF into the web server(s) hosting the application, such as a module like ModSecurity for the Apache, Nginx, and IIS web servers?
Alternatively, how about proxying requests from your web server, which doesn’t have a WAF, through another instance which does? What are the implications here?
In either instance, there is going to be a performance impact on the ability of the web server to serve concurrent requests. That goes without saying.
Given that, to maintain the ability to serve the same or a similar level of requests, either more web servers or more hardware is required.
To some degree, depending on the architecture of the application, this could potentially be mitigated using tools such as Varnish to cache static content, content which doesn’t need to be inspected by a WAF.
But this, in turn, will add extra complexity, overhead, and cost. Given that, which configuration is right for your application and available budget?
Runtime Application Self-Protection (RASP) as a Viable Alternative
What about an alternative? What if an application could do its own monitoring and, when necessary, defend itself? What if we instead took a different approach to securing applications? What if, instead of considering security from the perspective of everything outside being a threat, but anything inside is ok, we look at it a little differently?
That is sort of what RASP is. RASP implementations sit inside an application’s runtime environment, such as Ruby, the JVM or .NET Common Language Runtime. Given that, they’re much closer in nature to the application, needing to be developed specifically for the application in question.
As a result, they can forgo broad pattern analysis and instead look at an event in progress, along with a large amount of information about the application, such as its runtime configuration, and react accordingly. Some of these situations may include logins and database or external service access.
This kind of protection is especially useful in the modern age, as the definition of where the application perimeter lies is particularly difficult when an application can be accessed from almost anywhere.
However, this extra security layer, like any extra layer in an application, will involve extra execution overhead. Given RASP’s context-specific nature, this overhead may be acceptable. But it may not. Regardless, it would always have to be assessed as part of the application development process.
Finally, RASP is not security-focused application development. It’s still a layer upon or around an application, designed to protect it, in part from itself. Even if it protects against all major categories of vulnerabilities, including 0-day attacks, it should still be used in addition to a strong security development culture.
Security Conscious Development Practices
Before we finish up, there’s one other point worth considering, one which is paramount to building secure applications. In a recent article, Lenny Pruss makes a case for the DevOpsification of security.
Specifically, he proposes that:
…today’s security paradigm must be application-centric, developer-driven and built from the inside-out.
It’s a philosophy with which I wholeheartedly agree. While protecting applications from the outside, to protect them from malicious intent is necessary; it can never be the only approach.
Developers learned to create better quality applications through integrating test-driven development practices. Developers also learned to build applications quickly and more reliably through integrating DevOps practices.
So, in turn, must developers learn to create more secure applications by integrating secure application development practices as part of a standard development approach. By doing so, can we work toward a more holistic approach to building more secure applications?
In Conclusion
That’s been a run through on two potential ways to protecting your web applications from attacks, one which considered some of the upsides, as well as some the downsides.
Also, it gave a short overview of using RASP as an alternative to mitigate the cost, performance, and maintenance overheads of said solutions.
It then finished up by looking at the increasing responsibility which developers need to take on board.
I hope that it helps you make an informed decision about protecting your applications from malicious users.
If you’d like to know more about Sqreen, I encourage you to check out the documentation, or sign up for a free trial.
About the Author
Matthew Setter is an independent software developer and technical writer. He specializes in creating test-driven applications and writing about modern software practices, including continuous development, testing, and security.