[Esapi-dev] ESAPI Java and Authenticated encryption implementation

Philippe Arteau philippe.arteau at gmail.com
Wed Aug 21 21:41:55 UTC 2013


The authenticated encryption implementation in ESAPI 2 seems to have logic
flaws.

Expected use of MAC on CipherText (has seen in
https://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/test/java/org/owasp/esapi/crypto/CipherTextTest.java
)
>>>
        //Encrypt
        CipherText ct = ESAPI.encryptor().encrypt(new
PlainText(originalMessage));
        ct.computeAndStoreMAC(sk);

        //Serialize the ciphertext...
        byte[] serializedCt = ct.asPortableSerializedByteArray();

        //Decrypt
        CipherText ctReload =
CipherText.fromPortableSerializedBytes(serializedCt);
        PlainText pt = ESAPI.encryptor().decrypt(sk,ctReload);
>>>

The decrypt() function does a validation prior the decryption:
JavaEncryptor.java
>>>
      boolean valid = CryptoHelper.isCipherTextMACvalid(key, ciphertext);
      if (!valid)
      {
        [...]
        throw new EncryptionException("Decryption failed; see logs for
details.", "Decryption failed because MAC invalid for " + ciphertext);
      }
      [...]
      plaintext = handleDecryption(key, ciphertext);
>>>

The problem is that the MAC validation can be bypassed under certain
conditions.

*Condition #1*: if the Ciphertext is tampered to contains a MAC that is null

CryptoHelper.java
>>>
  public boolean validateMAC(SecretKey authKey)
  {
    boolean usesMAC = ESAPI.securityConfiguration().useMACforCipherText();

    if ((usesMAC) && (macComputed()))
    {
      byte[] mac = computeMAC(authKey);
      assert (mac.length == this.separate_mac_.length) : "MACs are of
differnt lengths. Should both be the same.";
      return CryptoHelper.arrayCompare(mac, this.separate_mac_);
    }if (!usesMAC) {
      return true;
    }
    logger.warning(Logger.SECURITY_FAILURE, "Cannot validate MAC as it was
never computed and stored. Decryption result may be garbage even when
decryption succeeds.");

    return true;
  }

  private boolean macComputed()
  {
    return this.separate_mac_ != null;
  }
>>>

Disabling the MAC validation allow different kinds of attacks that involve
altering the ciphertext. (Oracle Padding Attack, IV manipulation, Direct
block manipulation)

*Condition #2*: if the cipherSpec is tampered to use a different mode that
is not part of combinedCipherModes

CryptoHelper.java
>>>
public static boolean isCombinedCipherMode(String cipherMode)
  {
    assert (cipherMode != null) : "Cipher mode may not be null";
    assert (!cipherMode.equals("")) : "Cipher mode may not be empty string";
    List combinedCipherModes =
ESAPI.securityConfiguration().getCombinedCipherModes();

    return combinedCipherModes.contains(cipherMode);
  }
[...]
public static boolean isMACRequired(CipherText ct)
  {
    boolean preferredCipherMode = isCombinedCipherMode(ct.getCipherMode());

    boolean wantsMAC = ESAPI.securityConfiguration().useMACforCipherText();

    return (!preferredCipherMode) && (wantsMAC);
  }
>>>

*Opinion*
The design to compute the mac for only a portion of the message is kind of
broken. The mac should cover all parameters serialized. Authenticated
encryption implementation should not use logic that support optional MAC.

A proof of concept of the attack described previously is attached.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.owasp.org/pipermail/esapi-dev/attachments/20130821/48f4d767/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: esapi-mac.zip
Type: application/zip
Size: 2660 bytes
Desc: not available
URL: <http://lists.owasp.org/pipermail/esapi-dev/attachments/20130821/48f4d767/attachment.zip>


More information about the Esapi-dev mailing list