Cryptography Errors
Many organizations make use of cryptography for securing their applications. A large portion of banking applications rely on some sort of cryptography. When we talk about using cryptography in applications, most of the time developers rely on existing APIs or third party libraries, which can do the job for them. When doing this, there can be several things that can go wrong. While use of cryptography solves many security problems, using it incorrectly is a problem that is commonly seen in many applications. This article delves into some common cryptography errors developers make when using it in their applications.
Learn Applied Cryptography
Insecure key Management
During several penetration tests and code reviews, it was observed that the encryption keys are hard coded along with the encrypted text. Damn Vulnerable Thick Client Application (DVTA), a deliberately insecure thick client application developed in .NET shows a good example of it.
<add key="DBSERVER" value="192.168.56.110\SQLEXPRESS" />
<add key="DBNAME" value="DVTA" />
<add key="DBUSERNAME" value="sa" />
<add key="DBPASSWORD" value="CTsvjZ0jQghXYWbSRcPxpQ==" />
<add key="AESKEY" value="J8gLXc454o5tW2HEF7HahcXPufj9v8k8" />
<add key="IV" value="fq20T0gMnXa6g0l4" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
As we can notice in the preceding excerpt, the encryption key is saved alongside the encrypted text. This type of key management mistakes are often seen with encryption. Just like how the key is hardcoded in a config file, it is possible that the key is saved alongside the encrypted data in databases. In some cases, it is also observed that keys are kept in environment variables.
In addition to storing keys insecurely, there are other insecure key management practices (in cases where they keys are properly protected), which include fetching the key over an insecure channel and not validating who is requesting the key.
Use of insecure cipher modes
There are cases where choosing a wrong cipher mode leads to insecure data encryption. For example, the use of AES-128-ECB, which is a block cipher. ECB stands for Electronic Code Block, which is one of the modes that can be used with AES encryption. The problem with ECB mode is that encrypted data leaks information about the plain text.
Outdated crypto algorithms
There are way too many applications using MD5 and SHA1 algorithms for hashing secrets such as passwords. MD5 and SHA1 are considered broken and there have been warnings by security pros across the internet suggesting to avoid the use of these algorithms. Developers often choose these outdated hashing algorithms for hashing secrets.
A commonly seen scenario is storing credentials using weak hashing algorithms such as MD5 and SHA1. Attackers can perform password cracking attacks to retrieve clear text passwords when credentials are hashed using weak hashing algorithms. It is recommended to use a strong hashing algorithm (such as bcrypt) with the use of salts to make password cracking harder. The following figure shows a database table storing user credentials using the MD5 hashing algorithm.
Insufficient randomness
When developers are required to generate random values in their code, often the random values generated are not so random and they may be predictable. For instance, let us assume that a seed is generated using current system time and it was used to generate a random seed. The system time at the time of encryption is predictable and the same random seed can be re-generated, defeating the whole purpose of creating random values. Why is it a problem?
Let us understand this using a simple python script.
random.seed(1607006154)
print(random.random())
The preceding script uses a function named random to generate a pseudo random number using a seed. The problem with this is, if the seed is the same, the output will always be the same. The following excerpt shows the output of this script when run multiple times.
$ python3 rand.py
0.35463462736172136
//Second run
$ python3 rand.py
0.35463462736172136
//Third run
$ python3 rand.py
0.35463462736172136
//Fourth run
$ python3 rand.py
0.35463462736172136
//Fifth run
$ python3 rand.py
0.35463462736172136
As we can notice in the preceding output, the output is the same every time the random function is called with the same seed.
Rolling your own crypto
When there is a specific security problem, which requires cryptography to solve it, it is recommended to use battle tested and widely accepted crypto libraries instead of re-inventing the wheel by writing your own code to do the same as it can result in bugs.
Learn Applied Cryptography
Conclusion
Use of cryptography is common in applications and developers must understand how to use it properly. Using cryptographic libraries in an incorrect way will defeat the whole purpose of using crypto. In the next few articles, we will discuss how attackers can leverage the use of insecure crypto using some examples followed by some of the security best practices that can be followed to avoid such issues.