Improve mobile app security by turning it into code
Monday, May 8, 2017
Jeff Williams |
Improving mobile app security by using coding to make sure that everything is secure.
Why is application security such a pain? One of the hard problems with application security is that there are a zillion different ways that things can go wrong. Far more than any one person can be expert in. It's unfair to think that a software developer, who is already supposed to be expert in all the latest software languages, frameworks and best practices, should also be keeping up with application security.
So, to "help" developers, security teams often put together documents, like security policies, security requirements, secure coding guidelines, security architectures, abuse cases, security design documents, security standards, security testing guidelines, appsec training and security threat models. I'm guilty of creating many of these documents over the years. And I'm sorry. They're often long and boring, and because every application is a beautiful and unique snowflake, these documents usually don't apply directly without a serious amount of interpretation.
Actually, all these documents are really trying to capture the same thing - how security is supposed to work. Each of these documents is a view of our security expectations, at different levels and interpreted for different audiences. For example, here's a notional look at how SQL injection might look in various documents:
- Architecture: Use an ORM for all database interaction
- Coding Guideline: Use parameterized interfaces, not string concatenation to build queries
- Abuse Case: Send SQL syntax (e.g. ' or '1'='1) to all exposed interfaces
- Training: Here's how to exploit WebGoat using SQL injection
- Threat Model: Attackers can send untrusted data from Internet Zone to Application Zone
- Etc...
Don't get me wrong, it's really important to work out how security is supposed to work. But when we communicate it to development teams in a series of long, complicated, inconsistent documents, it's no wonder that the message doesn't make it.
One way out of this trap is to turn application security into code. Instead of multiple different documents, we can define how security is supposed to be with code that verifies that what we expected is, in fact, true for our applications. Coders, testers, security, compliance and others can all share the same expected model.
Much of what goes into these documents can be turned into repeatable test cases that verify applications. Remember, we're not shooting for simply running a scanner that attempts attacks or searches for a few vulnerabilities. Our goal here is to verify that the application's defenses are 1) present, 2) correct, and 3) used in all the right places.
It's often far simpler to verify defenses than it is to prove that the application isn't susceptible to attack. For example, you can establish quickly that an application only uses parameterized queries to access a database, and is therefore not susceptible to SQL injection. It would take days to use a dynamic scanner to check every header, cookie, parameter and form field in a web application to see if it can be used for SQL injection.
The trick is getting access to the information that can directly verify what we're trying to prove. Source code isn't the answer. That might work for one thing, but be incredibly difficult for another. The code is just one "source" of information about an application. To do this job, we are going to need to see the HTTP traffic in and out of our application, configuration files, libraries, frameworks, data flow, control flow, backend connections, etc.
In theory, if we can turn this verification into code, software projects can build and deploy software with confidence even without involvement from security experts. And since there's currently a massive shortage of application security experts, this is the only way to avoid development pipeline bottlenecks.
Let's take a simple example. Imagine that we want to stop clickjacking. We decide that we are going to us the X-FRAME-OPTIONS header on all our outbound HTTP responses to tell browsers not to allow our pages to be framed. Now, how can we turn that check into code?
Hmm... we could write a static analysis tool to check our code for the proper setHeader() calls. But it's very tricky to tell if this would apply to every page. Why not actually measure the outbound HTTP requests themselves to make sure that we never generate a page without the X-FRAME-OPTIONS header?
There are many ways to get at the HTTP response. We could use a proxy like OWASP ZAP in our test environment. Or we could write a filter that runs as part of our application. It's a simple check to verify that all headers have the right header. In any case, now we can be instantly notified anytime our actual security doesn't match what we expected.
So, you can assemble a platform consisting of various methods to do your application security checking. The platform should run continuously, starting in your development environment and extending across the SDLC. Here's a partial list of ideas for gathering that data and what you can verify with it. Note that every application is different, so be creative about how you can automate security verification.
Remember, you will never be able to verify everything if you only use one type of information. But if you're smart, you'll gather exactly the kind of information that lets you verify your defenses in the most fast, accurate, and cost-effective way. Put another way, using vulnerability scanners to verify safe use of SQL isn't effective. Just like verifying clickjacking defenses by looking at source code isn't smart.
As the software world moves towards DevOps, cloud, containers, continuous integration, continuous delivery and continuous deployment, we desperately need to move to continuous security. We will never be able to get there by using traditional tools that can only be used by experts. Instead, we need to focus on truly automating the verification of software defenses.
This content is made possible by a guest author, or sponsor; it is not written by and does not necessarily reflect the views of App Developer Magazine's editorial staff.
So, to "help" developers, security teams often put together documents, like security policies, security requirements, secure coding guidelines, security architectures, abuse cases, security design documents, security standards, security testing guidelines, appsec training and security threat models. I'm guilty of creating many of these documents over the years. And I'm sorry. They're often long and boring, and because every application is a beautiful and unique snowflake, these documents usually don't apply directly without a serious amount of interpretation.
Actually, all these documents are really trying to capture the same thing - how security is supposed to work. Each of these documents is a view of our security expectations, at different levels and interpreted for different audiences. For example, here's a notional look at how SQL injection might look in various documents:
- Architecture: Use an ORM for all database interaction
- Coding Guideline: Use parameterized interfaces, not string concatenation to build queries
- Abuse Case: Send SQL syntax (e.g. ' or '1'='1) to all exposed interfaces
- Training: Here's how to exploit WebGoat using SQL injection
- Threat Model: Attackers can send untrusted data from Internet Zone to Application Zone
- Etc...
Don't get me wrong, it's really important to work out how security is supposed to work. But when we communicate it to development teams in a series of long, complicated, inconsistent documents, it's no wonder that the message doesn't make it.
Turning Application Security into Code
One way out of this trap is to turn application security into code. Instead of multiple different documents, we can define how security is supposed to be with code that verifies that what we expected is, in fact, true for our applications. Coders, testers, security, compliance and others can all share the same expected model.
Much of what goes into these documents can be turned into repeatable test cases that verify applications. Remember, we're not shooting for simply running a scanner that attempts attacks or searches for a few vulnerabilities. Our goal here is to verify that the application's defenses are 1) present, 2) correct, and 3) used in all the right places.
It's often far simpler to verify defenses than it is to prove that the application isn't susceptible to attack. For example, you can establish quickly that an application only uses parameterized queries to access a database, and is therefore not susceptible to SQL injection. It would take days to use a dynamic scanner to check every header, cookie, parameter and form field in a web application to see if it can be used for SQL injection.
The trick is getting access to the information that can directly verify what we're trying to prove. Source code isn't the answer. That might work for one thing, but be incredibly difficult for another. The code is just one "source" of information about an application. To do this job, we are going to need to see the HTTP traffic in and out of our application, configuration files, libraries, frameworks, data flow, control flow, backend connections, etc.
In theory, if we can turn this verification into code, software projects can build and deploy software with confidence even without involvement from security experts. And since there's currently a massive shortage of application security experts, this is the only way to avoid development pipeline bottlenecks.
Simple Example: Automating ClickJack Verification
Let's take a simple example. Imagine that we want to stop clickjacking. We decide that we are going to us the X-FRAME-OPTIONS header on all our outbound HTTP responses to tell browsers not to allow our pages to be framed. Now, how can we turn that check into code?
Hmm... we could write a static analysis tool to check our code for the proper setHeader() calls. But it's very tricky to tell if this would apply to every page. Why not actually measure the outbound HTTP requests themselves to make sure that we never generate a page without the X-FRAME-OPTIONS header?
There are many ways to get at the HTTP response. We could use a proxy like OWASP ZAP in our test environment. Or we could write a filter that runs as part of our application. It's a simple check to verify that all headers have the right header. In any case, now we can be instantly notified anytime our actual security doesn't match what we expected.
Building a Platform for AppSec Automation
So, you can assemble a platform consisting of various methods to do your application security checking. The platform should run continuously, starting in your development environment and extending across the SDLC. Here's a partial list of ideas for gathering that data and what you can verify with it. Note that every application is different, so be creative about how you can automate security verification.
Remember, you will never be able to verify everything if you only use one type of information. But if you're smart, you'll gather exactly the kind of information that lets you verify your defenses in the most fast, accurate, and cost-effective way. Put another way, using vulnerability scanners to verify safe use of SQL isn't effective. Just like verifying clickjacking defenses by looking at source code isn't smart.
Security as Code Is the Key to DevSecOps
As the software world moves towards DevOps, cloud, containers, continuous integration, continuous delivery and continuous deployment, we desperately need to move to continuous security. We will never be able to get there by using traditional tools that can only be used by experts. Instead, we need to focus on truly automating the verification of software defenses.
This content is made possible by a guest author, or sponsor; it is not written by and does not necessarily reflect the views of App Developer Magazine's editorial staff.
Become a subscriber of App Developer Magazine for just $5.99 a month and take advantage of all these perks.
MEMBERS GET ACCESS TO
- - Exclusive content from leaders in the industry
- - Q&A articles from industry leaders
- - Tips and tricks from the most successful developers weekly
- - Monthly issues, including all 90+ back-issues since 2012
- - Event discounts and early-bird signups
- - Gain insight from top achievers in the app store
- - Learn what tools to use, what SDK's to use, and more
Subscribe here