Technological security threats around the world are increasing gradually. Where before it was simply individual credit card numbers being stolen, now it seems almost every day there’s another story of severe breaches where millions of financial records are exposed, like the recent Experian discovery.
Writing secure code is not an easy task. In order to approximate bulletproof code, managers, auditors, engineers, and architects imagine everything that could go wrong with every facet of the code. Though it is not possible to predict every bad curve the hackers will hurl, you must do everything you can to decrease your attack surface, seal holes, and guard against the fallout of a potential breach.
1) Testing Inputs Rigorously
Attackers require a path into your machine, and the simplest routes are via the doors your own code opens. If your program is connected to the Internet, someone will attempt to sneak something past you through those doors.
A good example of a vulnerable path into software is the buffer overflow created by lazy C programmers who will accept any character string until that string hits zero, the last character’s official C symbol.
Long ago, attackers discovered that they could log data packets arbitrarily and write over the memory and the programming stack until they never sent that terminating zero. For instance, a program is waiting for a user to enter his name. Instead of entering the name, the hacker would write an executable command that exceeds the size of the stack. They could rewrite anything and assume control if they were clever with what they had written.
The solution is to never trust the person on the other end of the Internet — test the structure and size of incoming data. Even the environments that are not susceptible to buffer overflow attacks must be tested, because the overly large inputs may cause denial of service or various other operational problems.
Data transport languages, such as JSON and XML, aren’t equipped to check the data in order to prevent these problems, so checking is what the programmer must do to secure their code.
2) Store only what you need
Before you ask for the snail mail address of your customer, ask yourself whether you will send a physical letter to them via the post office, don’t store business or home addresses if email is sufficient for correspondence. The extra information takes up disk space, costs time to process, and makes a target for hackers.
Very often, programmers think like obsessive hoarders, storing anything that stands the least chance of being useful someday. This instinct may help when you have to debug software, but it also leaves a trail of data for anyone to find.
Is every table and column in the database necessary? Make the database tables smaller and the forms shorter when in doubt. Try to simplify everything. Customers will enjoy investing less amount of time filling out forms.
3) Avoid depending just on passwords
Programs that accept dangerously simple passwords are another problem. Programmers are aware of this issue but haven’t been able to find solutions that offer users an easy and flexible solution.
One solution is to implement N-factor authentication that tosses several distinct hurdles in the user’s way when they log in. One example is sending a text message with a random number to the user’s phone and asking them to type the number along with their password. It’s a good solution unless the user is in an area without mobile coverage or their phone battery dies.
Some programs take things a step further and require special hardware that manages the cryptographic keys. These tokens are generally easy to lose and are more expensive than a phone.
These type of extra steps or hardware are not perfect solutions, but they are much better than just depending on a password, even if that password technically has the right mixture of punctuation marks, numbers, and lowercase and uppercase letters.
4) Negotiate requirements
When developers are considering project requirements, they must consider how those requirements might open the door to security problems down the road. The right time to have this discussion with project managers is at the beginning of development, when you can negotiate those requirements.
For example, a requested feature may seem cute, but will it drive you to keep extra sensitive information and enhance the security level needed throughout the program? Is a slick feature worth all those additional headaches?
When the customers are not salivating over the features you have promised them, or when the requirements document is still flexible, then that is the right time to begin securing your code against future breaches. The developers must let the managers know when they see the potential for security issues and inform them what type of features need to be added.
5) Add delays to your code
Many attacks depend on utilizing a bot to relentlessly enter information over and over again, using multiple queries to overwhelm the program. Some bots screen scrape databases, pretending to be a user, while others try multiple potential passwords until the right one is found.
To confound these bots, the trick is to add a delay and to increase that delay progressively over the login process. In many cases, you don’t want your software to be very efficient or very fast; you want it to be quick enough to aid the right humans but too slow for the bots that are attacking to get much accomplished.
With each incorrect password tried, some login programs double the delay. Other databases limit the number of queries that come from each IP address. Some systems send an email request deliberately to slow the process down. It all lies in the interest of security — humans won’t observe the additional one or two seconds, but a bot will be bored to the point of being ineffective.
6) Use more encryption that you think you should
Encryption is often underused as it adds another step to the process and makes debugging much harder. Finding errors in a system can be hard enough; when the data is some enigmatic pile of numbers, it’s even harder.
If it’s inscrutable to you as the developer, it will be the same for hackers.
All popular software applications and major operating systems provide you with the option of encrypting folders or files on your device. When you utilize this option, you’ll need to choose a password that enables you to unlock and decrypt those files.
Locking up databases that store personal data saves you the trouble of worrying about the database, the underlying operating system and the hypervisor that might be running underneath the system.
7) Build walls
The demand for ease-of-use is greater than the demand to add security. People don’t like logging into different system components, but it can be dangerous to connect all of the programs and systems together into a single portal. Everything can be compromised by one weak link.
Although many users may want to traverse the system and achieve what they want with just a single click, the simpler you make it for an authorized user, the simpler you make it for an attacker who slips in.
It can make sense to set apart the highly sensitive operations into a separate system, where users must log in again when they want to use those functions.
Even with the perceived inconvenience to the user, you should build more walls between the login phase and highly sensitive operations in order to provide greater overall security.
8) Use well-tested libraries
Encryption is really hard to perform well, and even the most carefully built code can have backdoors and loopholes. One way to avoid these potential problems is to pull the code for your encryption from a well-tested library.
Reinventing a well-tested library is a mistake in general, but with encryption, it is even more problematic. If you invent your own algorithm for encryption, you may introduce holes into the code that can be exploited by a hacker. It’s better to use tested code from an existing library; these processes have already shown they can pass security testing.
9) Utilize internal APIs
A lesson everybody learns early in their career is breaking down your code into modules and imposing communication via well-designed internal application programming interfaces (API). APIs make it easy for programs to communicate with each other and share data.
APIs are now mainstream because of the software permeating every industry and product. Companies develop and deploy APIs based on individual project requirements, but overall, there are three types of APIs: serverless and codeless, managed, and self-managed.
In the context of security, APIs make it easy to find holes, fix problems, and audit interactions. It’s often easier to analyze parts rather than the whole, so creating internal sub-modules makes sense to help analyze how secure your code is. Modules can be scrutinized separately and then results can be combined to give an overall security review.
An API also offers another layer of security because it acts as a doorway to your database and server; only those with an API key can have read or write access to the program.
10) Get outside auditors to critique your code
While each of us can utilize an editor, your organization should also invest in code audits. These external audits can identify security flaws (as well as other issues with your code) and suggest how to improve the code.
Generally, outside auditors who have more experience identifying security issues will be able to review your code with a more critical and thorough eye, looking for problems you and your team may be too close to see. Plus, as outsiders, they may be able to break ties and unjam internal conflicts because they have the benefit of not being attached to internal factions.
Remember: Safety First
Security is critical, and programmers need to consider building it into their programs from the beginning.
These 10 tips are a starting point. Programmers must continually educate themselves on the latest security practices; you should keep up with new information by reading current publications, taking a class, or following knowledgeable experts.
There are also many books and other valuable sources of information available on the Internet that explain how to generate highly secure code.
Imparting security to your code may take an extra step as you’re building it but you must remember that in the long run, it is better to be safe than sorry.