Learn to build secure software
Gábor Pék (Avatao CTO)

We are writing millions of lines of code day by day, but only a few of us take security into account. We exactly know that it’s really easy to put security aside as it takes more investment than just inserting the very first working answer from Stackoverflow. The time pressure of an approaching deadline is a good excuse to go fast when establishing software security, and quality. Everybody says that security is important, but the reality is that we’ll always find a good reason to neglect it if it is not built in entirely
into our Software Development Life Cycle (SDLC).
Starting off
Thinking with the mindset of a security guy does not come instantly, we have to train ourselves to design and implement something which is fairly good as software and does not expose too many low-hanging vulnerabilities (here is an advice from Parisa Tabriz, security expert at Google). I want to share with you some takeaways that we experienced while developing our Avatao platform.
It is not easy to keep in mind all the attack vectors and be up-to-date with all the vulnerabilities that Google raises on a daily basis. No matter what stack you write code for, as software security issues are all around us. If you are a Java developer, for example, your managed code will probably not contain buffer overflow vulnerabilities, but if you are not familiar with race conditions your code can easily fail here. Thus, you have to be aware of the security pitfalls of the technology you use and the risks you take when you write your code. Long story short, here are the most important takeaways that I have in mind.
Software security by design
Security should be an integral part of your SDLC from the very first moment. I know that it is almost impossible as we rely on huge piles of 3rd party and legacy codes. Still, the earlier you take steps towards this integration, the better code quality you can reach in terms of security. There are many references and guides online (e.g., OWASP, NIST) that can be helpful. Don’t forget: no matter what software development model (e.g., Agile, Waterfall) you use, security should cover each phase of your software life cycle.
A good code does not necessarily mean that it is secure
Let me give you an example. Take a look at the following code. It simply compares an ID with its correct counterpart. The id_check
function returns 0 if the input ID is correct, and any non-0 value otherwise. To achieve this, it first compares the length of these IDs, then simply puts each character into upper case and calculates the distance between those characters. Semantically, the functionality seems to be correct, however, from the perspective of security, it is not good.
inline char upper (c)
{
return (c >= 'a') ? c-('a'-'A') : c
}
int id_check (char* id, char* correct_id)
{
char d
if (strlen (id) != strlen (correct_id))
return 2
while (*id) {
d = upper (*id++) - upper (*correct_id++
if (d > 0)
return 1
if (d < 0)
return -1
}
return 0
}
Problem #1 – Information Leakage
The original id_check
the function returns different values based on where the check failed: 2
if the input’s length is incorrect, and -1
or +1
depending on whether the first differing character is smaller or larger than the correct character. With this information, an attacker could guess the length of the correct ID by sending in larger and larger inputs until the function returns with something other than 2
. After guessing the length, he could guess the ID one character at a time (e.g., by incrementing the character until the return value changes from -1
to +1
, or by using a binary search algorithm).
Problem #2 – Timing-based side-channel attack
An attacker could also gain information about the ID by measuring the time it takes for the program to respond. Let’s assume that it takes the CPU 1ms to complete each character check. In that case, checking ABCDXXX
against ABCD1234
takes 5ms, because the program exits after the 5th character ('X' != '1')
. However, checking ABCD1XX
against ABCD1234
takes 6ms, because the program only exits after the 6th character ('X' != '2')
. The attacker could once again guess the characters one at a time by trying all possible characters since the character with the longest response time will be the correct one.
One might be tempted to add random delays to the function in order to prevent these kinds of attacks, but those can be easily filtered out by averaging multiple measurements of the same input.
The fix
The correct solution is to go through all characters instead of stopping after the first differing chars.
...
if (strlen (id) != strlen (correct_id))
return 1
while (*id)
d |= upper (*id++) ^ upper (*correct_id++
return d != 0
...
Threat modeling
As the saying goes “Think like an attacker”. No matter what software component we talk about it is always good to have a threat model in mind. Threat modeling motivates you to identify all the information that might affect softqware security. A good threat model helps you to collect and categorize weaknesses that your software can have.
We suggest you to have a threat model in each phase of your SDLC. For example,
before you start writing even a single line of code for your brand new web service, it’s worth investing some time into the security pitfalls of available programming languages and web frameworks. Personally, I really like Angular 4 (released a few weeks ago) where security was taken into account from the very beginning.
You can read more about threat modeling here.
Code review
I am sure that you also do a code review before you merge into your production branch. In my opinion, this is the last point when you can catch something really nasty before it flies into public. The pain and cost to find and fix a vulnerability demonstrated above are really expensive from this point on. Not to talk about the case when an able attacker finds it. So my advice is that you should take code review seriously because a developer with a good sense of security can save you a lot of time and pain.
My final thought is that we can achieve huge improvements in security by just simply taking care of the most obvious things. Don’t forget, the very first hit returned by Google to your search query may not be the right answer to your problem.
Secure SDLC with challenges covering the most popular languages below:
Share this post on social media!
Related Articles
Best practices to prevent IDOR vulnerabilities
Learn about Insecure Direct Object Reference and the steps you can take as a developer to make sure your applications are safeguarded against cyberattacks.
Interview with Davide Balzarotti
Having the right security mindset is important, so we asked an expert about learning security and building security awareness!
Vulnerabilities in authentication and authorization
Authentication and authorization both can be associated with common security vulnerabilities. Here are some ways to prevent them!