In this blog post we will discuss a case study where we were successful in exploiting a faulty password reset functionality. The end result was that we were able to set a new password on any arbitrary user account. We could do this because of a weak cryptographic implementation, in this case the functionality was utilising Electronic Code Book (ECB) mode encryption. Identifying such flaws during a black/grey-box application pentest can be really tricky and hopefully this blog post will help other people in the industry to find such flaws.
We will first begin with understanding the ECB Cipher mode and why it is not recommended to be used in encryption.
What is ECB?
ECB is the simplest and a popular encryption mode, but at the same time, quite weak. In this mode the plaintext gets divided into blocks and each block produces a corresponding cipher-text block.
Why ECB is bad?
If the plaintext block “notsosecure” is encrypted twice (two separate instances), the same key is used, and the output produced will always be the identical. To understand this further, let’s take a look at some sample code which encrypts data using AES encryption in ECB mode:
In the code below we call the EncryptBlock function to print the cipher-text as hex values for two separate strings:
The second string is created by adding 16 ‘b’s to the first string. Upon running the encryption function the strings get broken into two blocks of 128 bits each and corresponding cipher-text values are generated.
On close observation, we found that the hex values of the blocks corresponding to the string firstname.lastname@example.org is the same in both the cases.
Known Plaintext Attack
A Known Plaintext Attack (KPA) is where an attacker knows the plaintext and its corresponding cipher-text.
We were tasked with testing a popular e-Commerce website and, from a generalised perspective, we were highly impressed with the security features that were in place. However, the password reset functionality caught our attention.
We found that the password reset token remained the same every time a request was initiated from the same user account. Further analysis concluded that the token was “probably” generated by encrypting the user’s email address and the encryption function used some form of block cipher with a 64-bit block.
A sample password reset request received is as follows:
Breaking the Encryption by Analysing the Pattern
email@example.com(victim) was the email ID that we wanted to gain access to and therefore our aim was to get the cipher-text values corresponding to the above email ID. Hence we registered similar email IDs by appending 8 byte characters to the victim’s email ID on gmail.com These email IDs were then used to create an account on the e-commerce app.
We then used the password reset functionality for both these accounts and obtain the reset password links in the corresponding inbox.
Cipher-text received for both the email Ids is analyzed as follows:
The left hand side of Figures A & B show the plaintext i.e. the email IDs and the corresponding cipher-text in hex. The right hand side of the figures shows the block break-up of the plaintext and associated hex of the cipher-text values.
Comparing the block values we can get the cipher-text of the blocks corresponding to firstname.lastname@example.org (see the blocks highlighted in Green, Yellow and Purple colour). It should also be observed that the cipher-text values are same in both the cases. This is due to ECB cipher mode.
Now that we have the cipher-text corresponding to victim's (email@example.com) account, we base64 encode the value and append the token in the password reset URL and initiate a password reset.
Password Reset URL:
Thus the victim’s account can be compromised.
This case study easily helps us conclude that ECB mode is very weak and should not be used. It is recommended to use CBC mode instead. While CBC mode is preferred over ECB, please be mindful of padding Oracle attacks against CBC (https://en.wikipedia.org/wiki/Padding_oracle_attack) . In this specific case, the app developers did not need to use cryptography at all. All they needed was a random token (generated via PRNG) associated with the account, and that would have done the job.