Padding Oracle Vulnerability #3
This library does not authenticate ciphertexts, and there is a padding oracle vulnerability. I am procrastinating some math homework, so I'll write out a full description of the attack.
Suppose Mallory has an N-block ciphertext (IV, C1, C2, ..., CN) she wants to decrypt. Suppose also that she can choose ciphertexts to be decrypted, but all she can see is whether the
Mallory can use this to find out the last byte of every plaintext block. Suppose Mallory wants to find the last byte of the plaintext block Pj corresponding to the ciphertext block Cj (call the IV C0).
For quick reference, here is the unpad function:
If Mallory sends the ciphertext (C(j-1), Cj), i.e. the previous block as the IV, and the to-be-decrypted block as the only block in the ciphertext, then
tl;dr: We alter the previous block until the last byte of the plaintext block is known to be 17. We know how it got changed to 17 (by XORing X^1), so undoing that (XORing 17 by X^1) gives Mallory the value of the last byte.
This attack highlights the danger of not authenticating the ciphertext, but in practice it is probably much easier to break, since the client will probably behave differently depending on the contents of the returned string, and thus Mallory would be able to decrypt entire blocks (it will depend on how this library gets used in the specific application).
Here is a working implementation of the attack: https://gist.github.com/defuse/9fbbec08dc792b0ca696
The fix is to authenticate your ciphertexts.
By the way, I am the author of the similarly-named php-encryption. I put a lot of time into making that one secure, and it has had a decent amount of review, so you may want to just replace this code with mine.
Here is a sample application that is vulnerable:
After the discussion we decided that we will no longer support this library. Instead we will switch to php-encryption and this library is also suggested now in readme and on Packagist.