In a previous article, I talked about the Open Web Application Security Project (OWASP) Top 10, which is a list of the most common categories of vulnerabilities that affect Web applications. In that article, the IBM X-Force Ethical Hacking Team demonstrated the attacker’s point of view by exploiting various flaws in Web applications.
This time around, let’s take the defender’s side. How could a software developer or software architect build a secure application from the ground up? Is that even possible?
The ROI of Software Defenses
Indeed, it has been demonstrated that building secure defenses early in the development life cycle greatly reduces the cost of fixing a security defect. A National Institute of Standards and Technology (NIST) study has developedan estimate that shows the cost of fixing a defect in various stages of development. The table below is from that report:
Let’s make a simple calculation based on the NIST estimate. If the cost of implementing the software defense before the code is built is $100, then the cost of implementing this defense by fixing a defect reported by a customer will be $3,000.
That specific report doesn’t take into consideration the cost of a security breach. A 2013 report by the Ponemon Institute found that the average incident in the United States costs $5.4 million.
Also, keep in mind that the NIST estimate only takes into consideration the lifetime of a single bug. However, security countermeasures can be implemented in such a way that they are part of the framework.
In the example below, you can see how an input validation routine can be applied to several code paths at once. Consider that the number of code paths equals the number of potential defects, that each of them is a potential security breach waiting to happen. It will only cost you $100 to implement that input validation routine.
The return on investment of taking such an approach to software development is not always obvious because developers don’t always connect the dots between what they code and what happens when the defect is found in the real world.
Those architects who spend the extra $100 to improve their application security are the unsung heroes. Without anyone’s knowledge, they have potentially saved their organization millions of dollars.
In my experience as both an ethical hacker and an incident response lead, I have come to witness firsthand the difference between an application developed with security in mind and an application built with no security considerations. For the secure app, only 10 defects were found through penetration testing. But for the insecure app, there were more than 100 defects found through penetration testing.
The method of building software defenses as part of software design is called threat modeling. Threat modeling is an exercise in envisioning potential security attacks on the application and coming up with software defenses, or countermeasures, to prevent such attacks.
Let’s perform this exercise in its most basic form. If you are developing or defending a Web application, keep in mind the OWASP Top 10. The following is a set of countermeasures that will help you prevent these attacks:
This falls under the OWASP attack categories of injection, cross-site scripting, insecure direct object reference and invalidated redirects and forwards.
This one is a basic tenet of software programming: Always check that the data coming from the user is valid. In my experience, I have seen applications accept alphanumeric characters and symbols for a numeric ID parameter. These flaws allowed attacks such as SQL injections, where the numeric parameter could be exploited to exfiltrate data from a database.
Input validation is a very simple, low-cost technique. If the input is supposed to be a numeric value, make sure the string is only composed of characters 0–9.
There is such a thing as incorrect input validation — as is the case with blacklisting. For instance, imagine you are trying to prevent a cross-site scripting attack by rejecting all input that contains double quotes. A skilled attacker can use single quotes or no quotes whatsoever to thwart this validation. Input validation should always be done using white-listing — for example, by allowing only alphanumeric characters.
There are cases when input validation can’t prevent everything. There will be cases when you need to allow hazardous values to go through, and there are other countermeasures for those cases. However, by implementing input validation as a default first defense, you have greatly reduced the attack surface. Input validation can make the difference between 10 and 100 security defects, which would be about $270,000 using the NIST calculation.
Parameterized Command Calls
These fall under the OWASP attack category of injection.
If you must allow values coming from the user to contain characters that could construct shell or SQL commands, using the parameterized command calls is a simple way to prevent them from executing. The following is an example:
SQLCommand command = new Command(“select * from users where user='” + request.getParameter(“user”) + “‘ and password='”+request.getParameter(“password”) + “‘”)
This query can be exploited like this:
select * from users where user=”or 1=1– and password=’password’
java.sql.PreparedStatement stmt = connection.prepareStatement(“select * from users where username=’?’ and pass = ‘?'”);
Parameterized command calls can also be part of a framework interacting with the database or the operating system. I have seen many development teams build code database accessors automatically based on the database schema. That build process should create the already parameterized statements.
This falls under the OWASP attack category of cross-site scripting.
For example, HTML encoding ensures HTML markup characters provided by the user do not alter the content of the page.
Request Token Checks
These fall under the OWASP attack categories of cross-site request forgery, reflected cross-site scripting, broken authentication and session management.
This countermeasure prevents many types of client-side attacks. It makes HTTP requests to the application expire, independent of cookies preventing attackers from storing such requests in malicious sites or emails.
For example, the request below cannot be stored in an external site so long as the value of the CSRF token expires:
POST https://mysite/transferMoney HTTP/1.1
Cookie: JSESSIONID = c3625d6826a0e46cf6c51b7499bc63c8;
Ideally, this token should be contained in an HTTP header or the body of a request so that it doesn’t show up in the browser history or is inadvertently sent to a third party in an email. Also, the value of the token should be different than the value of the session cookie.
This countermeasure can also be made part of a REST framework, ensuring all requests coming in contain valid tokens.
This falls under the OWASP attack categories of sensitive data exposure, broken authentication and session management.
This countermeasure can be deployed to data both in motion and at rest. When data is in transit between the client and the Web application, or between the application and some other third party, it should be encrypted by using a secure communication protocol. This prevents attackers from listening in on the wire.
When the data is at rest is stored in a database or a configuration file, it should also be encrypted or hashed. This thwarts attackers who try to break in from escalating privileges or gaining access to sensitive information.
These are only a few software defenses to put in place, but they are very important. However, if you do start to implement them or think about them early in the development life cycle, you are well on your way toward developing a secure application. Don’t forget to test these defenses to make sure they work correctly by performing static and dynamic security scans and manual penetration tests.
Image Source: iStock