These are practical, straightforward steps that developers can take, with code examples, links to Secure Software. Consider this article a sneak peek at the latest OWASP Top 10 list for developers. If you have questions or suggestions, we’d be happy to hear from you, Just send an email to email@example.com.
One of the most dangerous (and most common) attacks on web applications is SQL Injection: attackers inserting malicious SQL into a dynamic SQL statement. SQL injection vulnerabilities are easy for an attacker to find and exploit using free tools like SQL Map or SQL Ninja, or even manually: try inserting a value like 1′ or ‘1’ = ‘1 into the user name, password, or any other text fields and see what happens. Once SQL injection vulnerabilities are found, they’re easy to exploit.
Luckily, SQL injection is also easy to prevent. You simply need to parameterize your SQL statements, making it clear to the SQL interpreter which parts of a SQL statement make up the command and which parts are data. OWASP has a Cheat Sheet that explains how to parameterize queries in Java (using prepared statements or Hibernate) and in other languages.
The solution to injection attacks is simple in concept: if you can’t clearly separate code from data (which is what you do to prevent SQL injection using a parameterized API), you have to make the data safe before handing it off to an external interpreter, such as an XML parser, an OS command shell, or a browser.
To do this you need to output encode/escape data before handing it to the interpreter so that the interpreter will not recognize executable statements in the data.
All data from outside your program or service, especially data from remote clients, is evil and needs to be validated: files, parameters, HTTP headers, cookies, … It doesn’t matter if the client or the other system validated the data. You need to validate it again.
The basic rules of data validation are as follows:
Deciding who needs what access to which data and to which features—and how these rules will be enforced—should be carefully thought through upfront in design. It’s a pain to retrofit access control later without making mistakes.
Building your bulletproof authentication and session management scheme isn’t easy. There are lots of places to make mistakes, which is why “Broken Authentication and Session Management” is #2 on the OWASP Top 10 list of serious application security problems. If your application framework doesn’t take care of this properly for you, then look at a library like Apache Shiro to provide functions for authentication and secure session management.
Try to enforce multi-factor authentication if you can. If you have to rely on just User IDs and passwords, make sure to follow rules for password length and complexity. If you are using an email address as the User ID, be careful to keep it safe: bad guys will try to harvest email addresses for other purposes.
When storing passwords, you can’t get away with just salting and hashing the value anymore. OWASP’s Password Storage Cheat Sheet explains what you need to do and what algorithms to use.
Protecting data and privacy is about access control (which we’ve already talked about), auditing (which we’ll cover under logging), and encryption: encrypting data in transit, at rest, and during processing.
For web apps and mobile apps, encrypting data in transit means using SSL/TLS. Using SSL isn’t hard. Making sure that it is set up and used correctly takes more work. OWASP’s Transport Layer Protection Cheat Sheet explains how SSL and TLS work and rules that you should follow. The Cheat Sheet on Certificate Pinning explains how you can prevent man-in-the-middle attacks when using SSL/TLS.
The most common mistakes in encrypting data at rest are:
OWASP has another Cheat Sheet on Cryptographic Storage which covers the different crypto algorithms that you should use and when. Libraries like Google KeyCzar or Jasypt will take care of the implementation details for you.
Logging is important for more than troubleshooting and debugging. It is also critical for activity auditing, intrusion detection (telling Ops when the system is being hacked), and forensics (figuring out what happened after the system was hacked). You should take all of this into account in your logging strategy.
Review code for correct logging practices and test the logging code to make sure that it works. OWASP’s Logging Cheat Sheet provides more guidelines on how to do logging right, and what to watch out for.
Know your tools and use them. There are lots of built-in security features in frameworks like Spring Security, Ruby on Rails, .NET, AngularJS, and Play, along with iOS and Android mobile platforms that will take care of common security problems for you, if you use them right. Take the time to understand and use them properly.
Error Handling isn’t sexy, but it has to be done right. Mistakes in error handling and exception handling lead to different kinds of common and serious security vulnerabilities:
Make sure that you have good automated unit and integration test coverage for security features and controls (like authentication, access control, and auditing) and critical business features: code that handles money, private data, trade secrets, and admin functions. This has to include both positive and negative tests.
Other system-level security tests and checks can be automated in CI/CD using tools like Gauntlet, BDD-Security, and Zapper (a Jenkins wrapper over the OWASP Zed Attack Proxy). These tools make it easy to run security tests and provide clear pass/fail feedback.
It’s your code. It’s your job to make sure that it is safe and secure.