Encoding/Decoding/Crypting and buffer lengths

This code snippet has a somewhat common bug.  I've seen this bug in all sorts of buffer manipulation code, not just cryptography, so I thought I'd share this.

     CryptoStream cs = new CryptoStream(myStream, myTransform, CryptoStreamMode.Read);
     byte[] fromEncrypt = new byte[inputByteArray.Length];
     cs.Read(fromEncrypt, 0, inputByteArray.Length);
     String decodedString = encoding.GetString(fromEncrypt);

On the surface this code looks fine, and for the most part it does what its supposed to.  The problem is that sometimes decodedString has a bunch of extra nulls (or other data) appended to the end of it.

What happened is that this code snippet ignores the return value from cs.Read that indicates how many bytes were output.  In fact, this case is sort of assuming that the decrypted data will be the same size as the encrypted data.  When calling encoding.GetString() the index returned from cs.Read needs to be used, ie:

    int decryptedSize = cs.Read(fromEncrypt, 0, inputByteArray.Length);
    String decodedString = encoding.GetString(fromEncrypt, 0, decryptedSize);

Since the decryptedSize is being ignored, GetString is evaluating all of the input byte buffer size, including the bytes after the decrypted size, which is all since it was a newly created buffer.  If the buffer had been reused it could've been any random gibberish.

For what its worth, this kind of bug can cause security bugs.  If a previous call left data in a buffer, a later call could append additional data.  Its easy to imagine a packet where a user's asking for account history or something complicated.  A later packet could ask for simple ping or query, but the previous user's request could be appended, causing a command to be reexecuted or to be executed with the other user's permissions or some such.

This doesn't only happen to the decryption APIs.  I've seen numerous cases where people ignore the return value(s) of a function.  This bug can be particularly insidious because the code might appear to work in simple or test cases and might not be revealed until edge cases are encountered.  Some strings might decrypt to the same size, and a Console.WriteLine() to show the result may not reveal the bug

Comments (0)

Skip to main content