Broken Cryptography in Android Applications

Broken Cryptography in Android Applications

In this blog we are going to discuss Broken Cryptography in Android Applications. When application developers wish to use encryption in their apps, they have to be aware of broken cryptography attacks. This blog discusses how vulnerabilities caused by faulty encryption might be introduced into Android apps. We’ll also look at some of the ways an attacker might take advantage of these flaws.

We will be discussing these vulnerabilities.

Hashing Algorithms with Flaws

Hash functions convert arbitrary input into fixed-length values in a predictable manner. It’s simple to compute the hash from the input, but determining the actual input from the hash is extremely difficult (if not impossible). Hash functions are used to verify integrity, but they do not ensure authenticity. For demonstration purposes, we are using a vulnerable application PIVAA application and for viewing the source code we are going to use Jadx tool.

The MD5 hashing method is included in the PIVAA application, which allows users to hash any string they enter.

Vulnerability: MD5 hashing shouldn’t be used for important data like passwords

This feature isn’t necessarily a vulnerability because of how it’s done in the PIVAA app, but it’s crucial to remember that weak hashing algorithms like MD5 and SHA-1 are vulnerable. The following problems plague MD5:

  • MD5 hashes can be cracked much faster as compared to other more recent hashing algorithms. An attacker should be slowed down by password hashing techniques.
  • When two text inputs create the same hash, MD5 hashes are sensitive to collisions.

We can see how the hashing functionality is implemented by statically examining the application’s code.

broken cryptography
PIVAA Code

The following is a breakdown of the hash function:

  • The hash function accepts two string values: one for the hashing method and another for the text to be hashed.
  • To handle any exceptions, a “try catch” statement is defined.
  • The “MessageDigest” class is used to implement a message digest algorithm’s functionality (i.e., MD5).
  • The data (text) given is processed using the “update()” function.
  • To convert an object to a string, use the “String.format(format, object)” function. The hexadecimal number “percent 032x” implies pad with 0 to a length of 32 characters. The object is the method’s second parameter.
  • To finish the hash computation, the “digest.digest()” function is used.

Let’s build an MD5 hash of a string input using the PIVAA application to highlight the MD5 hashing algorithm weakness:

broken cryptography

We can carry out a dictionary attack on the hash a try to convert back to plan text by using crackstation.

broken cryptography
crackstation.net

The MD5 hash took 3 seconds to crack – “Test me.” There are various approaches, but this one demonstrates how simple it is to crack MD5 hashes that have not been salted.

Mitigation

  • When trustworthy hashing is necessary, use stronger hash algorithms such as SHA-256, SHA-3, bcrypt, scrypt, and so on.
  • Make sure to salt password hashes, which is an extra data input that aids in password storage security.

Implementation of Weak Encryption

Sensitive data exposure, key leakage, failed authentication, insecure sessions, and spoofing attacks can all come from weak encryption algorithm usage. MD5 and RC4 are two encryption or hash methods that are known to be weak and should not be used.

The appropriate usage of parameters, in addition to selecting safe encryption or hash techniques, is critical to the security level. The ECB (Electronic Code Book) mode, for example, is not recommended for use in asymmetric encryption.

The PIVAA application uses AES encryption in combination using ECB mode.

It’s vital to understand how AES-ECB works in order to understand why it’s unsafe. The following diagram shows how AES-ECB encryption works.

BROKEN CRYPTOGRAPHY
AES-ECB Encryption

The following is an explanation of the diagram:

  • The encrypted message is divided into blocks of bytes (AES is a block cipher).
  • In ECB mode, the key is used to encrypt each block of plaintext separately.
  • This is insecure because if the plaintext input is the same, the identical ciphertext will be generated.

We can see the code used to conduct AES encryption using ECB mode by statically analyzing the PIVAA application’s source code.

PIVAA Code

Breaking down this method from top to bottom, it takes a single string parameter and then declares a “try catch” statement to handle any exceptions. The Java class “SecretKeySpec” creates a secret key from an array of bytes. Because a hardcoded key is supplied, the implementation of this class is likewise susceptible.

PIVAA Code

The “getInstance()” function of the “Cipher” Java class returns a cypher object that implements the provided transformation (i.e., “AES/ECB/PKCS5Padding”). Before the cypher object can be used, it must first be created by calling the “init()” function, which provides the mode (1) and secret key (skeySpec). After that, the plaintext is encrypted using the “doFinal()” function.

pivaa code
PIVAA Code

Finally, the method encodes the encrypted string in base64 and returns it. The “System.out.println()” function also prints this base64 encoded text to the standard output.

pivaa code
PIVAA Code

Using a hypothetical situation, we can show this problem with the PIVAA application. We obtained an encrypted ciphertext created by the application in this case, as seen below.

				
					DMy2IlPGmV+cI1mpKZf+zg==
				
			

We can try a plaintext attack on this ciphertext. This effectively implies that we can estimate what the original content was by entering random characters and comparing the encrypted output to the ciphertext we were able to obtain.

broken cryptography

Vulnerable Application

The last key was the same result as the ciphertext which we are looking for. The encrypted plaintext was the phrase “Test me” as we now know.

Mitigation

ECB mode should not be used for cryptographic operations. Instead, for cryptographic operations, use the code below:

				
					Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
				
			

Even if ECB mode is not specified, the following code will default to it:

				
					Cipher cipher = Cipher.getInstance("AES");
				
			
Usage of Weak Initialization Vector

In cryptography, an initialization vector (IV) or starting variable (SV) is an input to a cryptographic primitive being used to provide the initial state. The IV is typically required to be random or pseudorandom, but sometimes an IV only needs to be unpredictable or unique. Randomization is crucial for some encryption schemes to achieve semantic security, a property whereby repeated usage of the scheme under the same key does not allow an attacker to infer relationships between (potentially similar) segments of the encrypted message. For block ciphers, the use of an IV is described by the modes of operation.

The PIVAA application uses AES encryption in CBC mode, but with a known initialization vector (IV). An initialization vector (IV) is required as an initial input to the cypher in the CBC, OFB, CFB, and PCBC modes.

Vulnerability: A plain text attack can be used to exploit predictable IVs.

To properly comprehend why a predictable IV renders an encrypted object vulnerable to crypto-analysis tools, it is necessary to have a broad understanding of how AES-CBC works (e.g., a Chosen-Plaintext Attack). The AES-CBC encryption is demonstrated in the image below.

The following is an explanation of the diagram:

  • The encrypted message is divided into blocks of bytes (AES is a block cipher).
  • Each message block is encrypted using the same key and the AES method.
  • Before being encrypted using AES, the ciphertext output from the first message block is XORed with the plaintext output from the second message block. Each succeeding message block follows the same pattern. This is done to eliminate duplication in plaintext message blocks, when the same key is used to encrypt the same input several times and the same output is produced each time.
  • XOR with an Initialization Vector is the initial message block (M0) (IV). We initiate the CBC process with an IV to eliminate message block recurrence. If we used the same key to encrypt the same input multiple times without an IV, the first message block would always generate the same output. It would then be XORed with the following message block before AES encryption.

We can examine the PIVAA application’s source code statically and see the function that performs AES encryption in Cipher Block Chaining (CBC) mode.

PIVAA Code
PIVAA Code

Breaking down this method (encryptAES_CBC_PKCS5Padding) from top to bottom, it takes a single string parameter and then declares a “try catch” statement to handle any exceptions. Each time the function is used, the “IvParameterSpec” Java class is used to define an Initialization Vector. We can see that a hardcoded value has been utilized in the Initialization Vector. +

PIVAA Code

The Java class “SecretKeySpec” creates a secret key from an array of bytes. Because a hardcoded key is supplied, the implementation of this class is likewise vulnerable.

PIVAA Code
PIVAA Code

The “getInstance()” function of the “Cipher” Java class returns a cypher object that implements the provided transformation (i.e., “AES/CBC/PKCS5Padding”). The “init()” method must be implemented before the cypher object can be used, and it specifies the mode (1), secret key (skeySpec), and Initialization Vector (IV). After that, the plaintext is encrypted using the “doFinal()” function.

PIVAA CODE
PIVAA Code

Finally, the method encodes the encrypted string in base64 and returns it. The “System.out.println()” function also prints this base64 encoded text to the standard output.

PIVAA Code

We can now illustrate how to attack this vulnerability in the application since we have a better grasp of what the application’s code is doing. Let’s pretend we were able to obtain a string of ciphertext created by the PIVAA application, such as the following:

				
					DMy2IlPGmV+cI1mpKZf+zg==
				
			

We don’t know what the encrypted content is, but we can try a selected plaintext attack based on what we know about how the application utilized a weak initialization vector. This effectively implies that we can estimate what the original content was by entering random characters and comparing the encrypted output to the ciphertext I was able to obtain.

Vulnerable Application

As can be seen above, we produced the same result as the ciphertext. The encrypted plaintext was the word “password,” as we now know.

Mitigation
  • Initialization Vector should be unpredictably unpredictable.
  • Random should be the initialization vector.
  • Initialization Hard coding vectors is not recommended.
  • Initialization java.security.SecureRandom should be used to generate the vector. Instead of java.util.Random .

In this blog, we’ve seen how attackers can use Android applications and take advantage of weak cryptography implementations. This isn’t a detailed list of potential encryption flaws in Android apps, but it does highlight some of the identifiable concerns. For more information refer OWASP_MSTG-v1.4.0 Cryptography . For learning more about Android pentesting, check out our Android Pentesting Methodology series. Don’t forget to stay connected with Redfox Security for more insights into Cybersecurity.

Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. If you are looking to improve your organization’s security posture, contact us today to discuss your security testing needs. Our team of security professionals can help you identify vulnerabilities and weaknesses in your systems and provide recommendations to remediate them.

“Join us on our journey of growth and development by signing up for our comprehensive courses.