Welcome back to our series on Application Security! If you haven’t had a chance to check out our previous post that focuses on application-level security, we encourage you to give it a read-through. Otherwise, if you’re ready to go full steam ahead, then read on.
In today’s post, we’re going to focus entirely on the database - the thing that actually stores all of your sensitive data. There are several database types out there, ranging from more traditional SQL databases to graph databases, key/value stores, document-driven databases, and a slew of other NoSQL databases. While it’s possible to store all of your data in other manners, such as in flat files that you manually serialize and deserialize to interact with, that’s not a recommended practice, so we won’t be talking about that today.
Just like with your application, there are a bunch of things you can do to make your database more security-hardened, and a lot of the time, developers just don’t do them. Securing your database isn’t always an obvious thing to do, and it certainly isn’t something your users will ever notice - but one day, if you become the target of a nefarious hacking attempt, you’ll be glad that you took the time to secure all your data. At Clevyr, we take security seriously! We want to share all of that knowledge with you - so get ready to improve your database security because we’re about to review all the best practices regarding SQL injection prevention, password storage, database backup policies, and database encryption.
One of the most common ways that services get compromised is through a SQL Injection attack. SQL injection is where you exploit your user input capabilities to execute a custom SQL query in the database. OWASP (the Open Web Application Security Project) listed SQL Injection as the top web security threat of 2017, and it’s such a well-known threat that there’s even an XKCD comic about it:
So, in all honesty, if you’re using a modern framework to build your web, mobile, or software application, it likely already has the tools to protect you against SQL injection; you just have to use them!Suggestion: Use an ORM! At Clevyr, we opt for the ORMs we mentioned above and others depending on what languages and frameworks we’re using for the project. All of the mentioned ORMs support issuing raw SQL queries with built-in sanitization so that you don’t end up in a situation like little Bobby Tables’ school.
Storing passwords is one thing that developers usually do an okay job of compared to other security-focused things, and that’s because it’s a pretty obvious thing. Everyone knows that passwords are sensitive data, and if I could log in to a database and read everyone’s passwords in plain text, then that’s a big problem. That said, we’re still going to review this topic from square one and go over what you need to do.
Hashing passwords prevent nefarious attackers from reading what the passwords are even if they got a hold of the database itself. Password hashing refers to the idea of running a hash function on a user’s password, which will generate a new set of unique characters based on the original input. The hashed password (also known as a “digest”) is then stored in the database, as opposed to the plain password itself. Ideally, a user-unique salt is also incorporated in your password hashing process, which helps add additional security - especially for users who use weak passwords or the same password on multiple sites.
A significant point to make is that hash functions are different from encryption; encryption is encoding some sort of data with the idea of eventually being able to decode it back into the original message, whereas hash functions (which are a type of one-way function) can only encode data, NOT decode it. This might make them seem strange and/or difficult to use, but they’re perfect for storing sensitive data such as authentication credentials because your application usually doesn’t care about the specific data itself; it just cares that the authentication data your user is providing matches up with what you have stored in the database.
One additional benefit of a hash function is that you can hash any length of string, and your hash function will always create a digest of a set length (i.e., 64 characters). This removes any sort of database character limit issues for passwords, so your application could handle very lengthy passwords (read more about ideal Password Requirements in our previous post).Suggestion: At Clevyr, we recommend using a secure and tested slow hash function such as bcrypt or argon2 to hash all your incoming passwords. Both bcrypt and argon2 support automated key-stretching and salt processing by appending these related values within the same generated value that you store in the database, so there’s no extra work or architecture for you to set up. The reason you want a slow hash function is to prevent hackers from being able to quickly run the hash algorithm during a brute force attack (SHA-256, for example, is an excellent hash algorithm but is also a fast-running one, and thus not recommended for password hashing).
Backups are one of those things that most people don’t think about until it’s too late - and that’s not a good thing. One of the various scenarios could happen where you need to restore from a backup: a ransomware attack occurs overnight, production servers malfunction unexpectedly, hardware issues, etc. But what kind of backup do you need? Do you need one with the most recent data - or have you hacked unknowingly three weeks ago and need a backup from before then? Or are you getting audited for data from 4 years ago, and your normal database isn’t expected to store data that old?
Regardless of what backups you need, there’s one key thing you need to know: backups are hard, and most people don’t think about that. Most non-tech users don’t think about backups; they just assume that they magically exist and always store “all the data”! As folks in the IT industry, we know that’s not the case. To build a proper backup policy, here’s a checklist of what you need to consider:
Figure out what data you want to backup (it’s better to select too much than too little).
Store backups from previous days, months, and years.
Backup your data to multiple locations - including at least one cloud provider.
Ensure that only authorized users can access the backups in each location.
Test your backups somewhat regularly to make sure they are storing what you want, AND so you can learn how to restore backups quickly.
Lastly, we’ll cover encrypting your database. When we talk about database encryption, there are usually three things to consider:
data at rest (i.e., data that is stored at the file level)
data in use (i.e., data that is housed in database memory)
data in transit (i.e., data that is communicated to client applications)
The primary use case of database encryption is to protect against malicious users from getting Personally Identifiable Information (PII) and other sensitive business information (such as customer names, addresses, product data, etc.). Anything that could link up a person or entity of some sort with data that they wouldn’t want to be released to the public should be considered for encryption. And if you’re building an application that needs to meet HIPAA compliance or government clearance, then there are likely minimum requirements for how your data needs to be encrypted.
For all it’s worth, database encryption does have some negatives that need to be considered. For starters, encryption involves introducing an additional layer of data processing, which will slow down many interactions with your database a little bit (making them anywhere from 3% slower and up). So if you have a lot of data that may be important, but can’t be linked to any other unencrypted data in a meaningful way, then there’s probably little benefit in encrypting it. The big item to note here is that, most likely, not all of your data needs to be encrypted from a security standpoint.Nerd Alert: Historically, data at rest and data in transit were the two most significant topics regarding database encryption, but now as database servers are allocated more RAM, the amount of data they can hold in memory (i.e., “in use”) is astounding - which makes memory another place that you need to secure.
In general, we recommend evaluating your application’s needs to see what types of encryption you need. Some applications may not need encryption at all! If you seek explicit compliance of some sort, then at a minimum, we would recommend implementing transparent database encryption (TDE) to relatively easily encrypt data at rest if your database supports it. Encrypting data in transit is also relatively easy, as most databases support SSL communication (your client application will need to support it as well). However, to encrypt data in use, or if you have concerns about a “bad actor” getting access to your data via social engineering or other tactics, then none of these security measures so far will protect against that.Suggestion: To have well-rounded security in your database encryption, you’ll likely need to encrypt actual values in your database columns with a key that is secretly held outside of the database. This way, your data in use will be encrypted, and even if a nefarious user got access to your database server, they wouldn’t be able to understand or decrypt the sensitive data without the key.
As mentioned above, you likely don’t need to encrypt everything - just PII and other sensitive data. However, this encryption style becomes more of a burden because all of your client applications (including the DBMS client you likely often use to view the data) will need to have a workflow to decrypt and encrypt data back into the database. None of that needs to be overly difficult, but it does add additional complexity that needs to be considered.
Phew, you made it to the end (or jumped to this part to see how long the post actually was)! Truly, these topics are a brief overview, but hopefully, they give you some food for thought over how you can begin to secure the data-side of your business applications.
In part 3 of the series, we’ll talk about Social Engineering and various ways to protect yourself from less-technical threats and more people-oriented threats (which encompasses a large portion of how many threats happen).
Stay tuned - and if you need help securing your databases in the meantime or have any specific questions about the topics covered here, give us a call at Clevyr (844) 425-3897 or drop us a message at [email protected].