App security has become as nebulous a term as “cloud” and “DevOps.” There are a variety of application-related security concerns that must be addressed across development, operations, and the network that all fall under this single moniker. To better understand app security, it becomes important to recognize the different layers that comprise application security – the app security stack, if you will – by defining the parameters of each layer and assigning some measure of responsibility to the various teams who must take up its banner.
This is increasing important as attacks continue to expand their reach beyond what developers control — the application itself — to include what developers do not necessarily control — platforms and protocols.
Roughly that means the application security stack is built from three distinct layers: application, protocol, and platform.
The application layer concerns itself mostly with application logic and data handling. Application layer security revolves around concepts such as validation of input and output and logic flow. The OWASP Top Ten is an excellent resource for understanding the most common application layer security challenges and includes the most commonly exploited vulnerabilities such as SQLi and XSS, among others. While these common security mistakes can be addressed with solutions upstream from the application – such as web application firewalls – they are best resolved in application code by careful application of secure coding practices.
Logic errors are more difficult to resolve outside the application. That’s because the logic dictating flow between pages, tasks, and processes are generally fully contained within the application code itself. Ensuring proper flow and preventing users from abusing the ability to manually key in the URIs associated with most applications (and APIs) today is paramount to preventing access without the proper data available. Also falling into this category is prevention of parameter tampering. Applications relying on cookies or query parameters in URIs are particularly susceptible to this form of attack. While stateless application design is becoming preferable to traditional stateful design, careful attention to maintaining parameter integrity should be a key design factor, recognizing that client-side state is more vulnerable to this type of attack than its server-side alternatives. Encryption of client-side parameters can help prevent tampering, but there are operational consequences to adding this layer of security to the architecture.
Application client-side security is a growing issue, as the ability to inject malicious, obfuscated code into web applications via compromised ads and browsers has become almost trivial. This is an insidious, difficult to detect attack on applications as it often occurs on unmanaged client software over which neither developers nor operations has any control. There are a variety of mechanisms to combat this type of attack, both clientless and agent-based, which should be considered to prevent hijacking of this often-overlooked part of most applications.
Primary Responsibility: Developers
Secondary Responsibility: Operations/Network
The protocol layers of an application have become a critical concern for those dealing with application security. It is difficult to split protocols from the platforms that support them. In the case of application security, we can do so by identifying the difference between exploitation of protocol behavior from exploitation of platform handling. Protocol behavior deals with the expected behavior of a given protocol. For example, HTTP is a reply/request based protocol in which a client sends a request and expects a response. Protocol exploitation involves using this proper behavior to cause an unexpected result.
HTTP-based Distributed Denial of Service (DDoS) rely on nothing more than proper behavior of HTTP. With flood-type attacks, a high volume of HTTP GET requests is sent to the application in question. These requests are legitimate, valid HTTP GET requests but are sent by attacks at a volume designed to overwhelm the application server in the hopes of preventing legitimate users from accessing the application.
The opposite of a “flood” attack is a “slow” attack. In these, the same proper HTTP behavior is exploited by attackers who make requests and then very slowly receive responses. And by very slowly we’re talking about 2800 baud rate slow. This causes the server’s send queues to remain in use and forces the server to open new connections to serve other users until there are no connections available. This is a resource consumption attack that simply exploits a perfectly acceptable and secure web or application server to cause availability problems for legitimate users.
Now, the problem is that the behavior of HTTP does not generally fall under the purview of developers. After all, they didn’t write the HTTP handlers, they rely on platform- provided, industry standard software for that. This means the responsibility for detecting and dealing with such attacks falls on the operations/network teams, upstream, where such behavior can be dealt with.
When developers choose to address these resource-consuming attacks, their best option is to use authorization-based services upstream to allow or deny these requests. Such services can be deployed as network-services or as “pre-entry” application services. The key design factor here is that the service not reside on the application server itself, as that defeats the solution of conserving resources by preventing requests in the first place.
Primary Responsibility: Operations/Network
Secondary Responsibility: Developers
Applications, whether web or native mobile, still require logic to run on the “server-side” of the world. That means some kind of platform, e.g. Apache, is in use. When platforms are exploited it is commonly the case that it relates to how the platform handles certain protocols. As with most exploits, there are generally one of two goals behind an attack exploiting a platform vulnerability: data or denial of service. And they always target an application, which makes it a critical part of application security, particularly in the case of those driven by data exfiltration attempts.
For example, the infamous Apache Killer took advantage of how Apache mishandled an HTTP Range header that could cause excessive memory and CPU usage, ultimately resulting in a denial of service condition. More recently, Heartbleed exploited a defect in the OpenSSL library implementation of TLS/DTLS (transport layer security protocols) that resulted in the leaking of data in memory from the server to the client, and vice-versa.
These types of vulnerabilities are well outside the control of developers and, for the most part, operations as well. Platform security requires constant vigilance to determine the existence of such vulnerabilities and a subsequent plan to address. That plan is almost always the application of a hotfix from the platform vendor in question.
In cases where the platform is mishandling an HTTP header, it can be possible for developers to implement a fix if they (1) have access to the source code or (2) are able to apply such a fix before the platform processes the header. In some cases, operations may be able to configure the platform in a way that avoids processing of the header in question, or otherwise manipulates it to avoid the condition that would trigger a problem once processed. The ability of developers and operations to address these types of platform vulnerabilities depends highly on what specific pieces of a protocol are being exploited.
Network teams, in these cases, have a far better chance of preventing exploitation as they often have the tools at their disposal to inspect and filter attempted exploits upstream and thus prevent them from reaching the server in the first place. Such mitigations should be temporary, as the best response is to apply whatever patches are required when they become available. But in the meantime, mitigating upstream, in the network provides operations and developers with the time they need to resolve in a more permanent fashion.
Primary Responsibility: Network/Operations
Secondary Responsibility: Developers
This is by no means an exhaustive exploration of potential application attacks. Most application security concerns, however, fall into one of these three layers of the application security stack and thus provide a good starting point to understanding where to apply the proper mitigations and when.
More Security Goodness
If you want to see other articles in the guide, check out: