Best Practices When Working With Sensitive Data: Securing Your Application

In my previous article, I showed you how to protect your server from attacks and malicious software. This part will focus completely on the third layer of security - your application itself. So here, I will show you techniques that you can use to protect your application from attacks and intrusions.

Using a Database

When communicating with a database and in order for your data to remain safe, keep the following key points in mind:

Always Escape Queries

To stop attackers from using SQL Injection, you have to escape all users' input so they can't inject SQL queries into your application(for example, during a login). In pretty much all of the database drivers, for all languages, there is an option to escape user input. For example in node-mysql for Node.js, instead of doing your queries like this:

You can automatically escape them using this syntax:

Variables from the array provided as a second argument to the query method will be inserted in place of question marks in the query string and will be automatically escaped. The same can be done in PHP using PDO's prepared statements:

Never Trust Content From the Database

Even if you escape your database queries, you never know if a bug in your application has let some malicious code through. If you have written your app in a way to where you always assume that the content in the database is safe, then your users are endangered. For example, this code:

Is unsafe! If something goes wrong and the id of the user contains some SQL injection code, then you are going to have problems. $row['id'] should also be escaped using the escape_string() method, like so:


Use a Salt When Hashing

Now imagine this situation: some genius hackers break through your carefully crafted security and get their hands on your database. They then begin to brute-force all of your users' passwords. If you used a salt when hashing them, you can sleep peacefully and assure your users that their data is safe. Because unless the attacker has a quantum computer in their basement, it will take them years to crack any of the passwords.

Using a salt means that you append a few random characters to the password before hashing (these characters are what is called the salt) and store them with the password. You may think that this is not very secure, since the attacker will know the salt if they gain access to the database. But since the salt is different for every user, even if two of them use the same password their hashes will be different. This forces the attacker to crack them one by one, which makes it very time consuming and usually not worth the time wasted. This also means that the attacker can't use rainbow tables or a dictionary to lookup the passwords.

Salting a Password in Node.js: node-mysql

First you should generate the salt. For example, you could use crypto.randomBytes():

This function will throw an error if, according to the Node.js documentation, "there is not enough entropy to generate cryptographically strong data". In such a case, you should either try again or use crypto.pseudoRandomBytes(), which generates non-cryptographically strong random bytes, but since this will only happen occasionally, we can use it:

Now let's add the data. For simplicity, I'll only use a username, password and salt in this example:

When your user wants to login, you have to get the salt from the database and then check the password:

And that's pretty much it. Now let's see how we can do this using PHP.

Salting a Password in PHP

In PHP this is much simpler, because the built in functions password_hash() and password_verify() automatically uses a salt and the hash returned contains it, so you don't even need another column in the database (or field in case of NoSQL). It would look something like this:

To check the login, you just have to call password_verify(). It automatically gets the salt from the hash so you only need to supply the hash from your database and the plaintext password to compare. The needed code, is as follows:

POSIX: Drop Privileges When You Don't Need Them

This is one of the best defense mechanisms you can use to protect your machine and therefore your users. You need elevated privileges for a couple of things, mainly listening on port numbers lower than 1024 or messing with system files. But you should never run any app as root when you do not need to, just in case the attacker finds a bug in your code that allows them to execute commands on your server and if the code is running as a privileged user, it's game over. The attacker can do whatever they want and will probably be done before you even notice anything. This is why you should drop the privileges as fast as possible. In Node.js it would look like this:

The process.setuid() function will change the user identity of the process to the one passed to it - it can be either a numerical ID or a username string (in the second case, this function will block while getting the ID of the user). The user should be unprivileged and only have access to the app-specific files, to limit the risk of giving the attacker access to anything else on your machine.

An Alternative Way: Using authbind

Some people say (for example in this comment on dropping root privileges), that the solution above is not perfect and they prefer to use authbind instead. It's your decision which one you choose to use and it pretty much depends on your setup. But anyways, authbind is a command that was designed for this purpose - it allows your app to bind to ports lower than 1024 without root privileges (so it's only covering that scenario). To use it, first create a file: /etc/authbind/byport/port, where port is the port number you want to bind to and make it executable by the user you will use, to execute your app. Then switch to your user and start the app like this:

Or like this from root:

With this, you can accomplish the same end goal as with the POSIX solution, just now using authbind instead, if that's what you prefer.

Wrap Up

So hopefully you've picked up some new techniques for working with sensitive data throughout these two articles. In the previous article we started off learning how to protect our data on the server by choosing the right server provider, updating our OS, securing ports and using an antivirus. In this article, we wrapped up our discussion by talking about securing our application itself through the use of proper database security, password salting, and user privileges.

Feel free to share your own security tips in the comments and thank you for reading.

Tags:

Comments

Related Articles