In the age of information, a secure application is no longer a luxury. Every day we hear more and more about data leaks, ransomware, and other kinds of cyber-attacks. These attacks cost millions, and in some cases, they cost lives.
Securing applications is a massive effort encompassing all parts of the software creation process. In this article we will look at some common practices we could follow as developers to make an application more secure.
First, repeat after me: Users are not to be trusted.
A humorous tweet I found illustrates this beautifully:
A QA engineer walks into a bar and orders a beer. Orders 0 beers. Orders 99999999999 beers. Orders a lizard. Orders -1 beers. Orders a ueicbksjdhd. First real customer walks in and asks where the bathroom is. The bar bursts into flames, killing everyone.
This funny tweet shows that we, as developers could never guess what a user will do to the application. It may be a simple, innocent mistake of entering a wrong value. It could also be a malicious actor trying to bring down the application using SQL injection. Whatever it is, it may break the application.
So what can we do about that?
- Authenticate and authorize
- Any method exposed should be authenticated and authorized (and only in that order) and each user should have the lowest privilege that they need.
- This means that unless a user really needs a method, they should not have access. The less access someone has, the better.
- With the rise of personal devices such as smartphones, two-factor authentications are now a visible and recommended addition.
- Validate inputs
- Validating inputs is a big topic; it could even be a chapter in a book (https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/input.html). The main thing is that we define what we will accept, and reject anything else.
- Sanitizing data (elimination of unwanted characters from the input by means of removing, replacing, encoding, or escaping the characters) should always be done, both to inputs and outputs (like calling other system).
- Some issues, like buffer overflow and SQL injection, can be mitigated by this practice.
- Obfuscating sensitive data
- Sensitive data must not be sent or received as plain text and must be obfuscated in some way. One example of this is that passwords should never be stored in plain text. A way to do this is by using a one-way hash to store the password and comparing the hash from the input with the stored hash to validate it.
- As a consideration for RESTful APIs, just remember that any call to an API will show the URLs. This means that if the user has privilege to access /v1/users/1 (where 1 is the ID) he could very well get data with other IDs by inspecting the network tab on the browser. One way to deal with this is to obfuscate the ID by using some random generated token. This token is mapped in the database to an ID. User will only communicate using this token so it will be extremely hard to guess what the other IDs are.
KISS (or Keep It Simple, Stupid)
The next thing we should strive for when building an application is keeping everything as simple as possible. An uncomplicated design helps in making a secure application. A more complex design means that what we must do to secure our application becomes more complicated. This will, in turn, create a lot more holes to be fixed. So if you feel that your code is becoming convoluted, try to make it simpler. You can try splitting that code into chunks that are simpler to handle or that reverse to face opposite direction the way the code flows. Do try using design patterns and established best practices.
Leverage your tools
One more thing that we could do in our effort to have a secure application is by leveraging our tools, either the ones we already have or getting additional ones.
Does your coding follow best practice and does it contain any code that could lead to vulnerabilities? You could use Static Analysis Software Testing (SAST) tools such as Sonarqube or Sonarlint to check your code while you code.
Do your open source dependencies has known vulnerabilities? Is there any dependency license expired? You can use Software Composition Analysis (SCA) tools such as Snyk and WhiteSource.
There are both free and paid tools for both types. There are even IDEs that offers parts or even full solution tools for these kinds of tools. Use it, leverage it. It will help automate those small yet annoying things that really matters in keeping an application secure.
Note: The examples here are not sponsors, just some examples from the top of my head.
And now you might be wondering, is that it?
No, no, no, the practices mentioned in this article is but a drop of water in the ocean that is software security.
So, what to do next?
One website and project will appear in most articles and websites talking about software security. The Open Web Application Security Project (OWASP) (https://owasp.org/) is a nonprofit foundation that works to improve the security of software. The project website contains a wealth of information and guides in creating secure software. One of the most cited resources there, the OWASP top ten web application security risk (https://owasp.org/www-project-top-ten/) the security risks and how it works, and gives a guide in preventing it.
The top 10 secure coding practices in the SEI CERT website (https://wiki.sei.cmu.edu/confluence/display/seccode/Top+10+Secure+Coding+Practices) is also a valuable resource. The site also includes coding standards for C, C++, Java, Perl, and Android programming.
David A. Wheeler, the Director of Open-Source Supply Chain Security at the Linux Foundation, has authored a free book on Software Security. It can be accessed on https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/.
And for those who are more studious (or trying to do some paper on software security), there is always the Cyber Security Body of Knowledge or CyBOK (https://www.cybok.org/media/downloads/CyBOK-version-1.0.pdf) for really (and I mean really) in-depth reading about software security.
Diaz Dwiastamika - Analyst