Cloud storage and encryption revisited: Bitlocker attacks (part II)


Instead of adopting one of the standardized narrow block cipher modes for Bitlocker, Windows 8 removed the diffuser and reverted to plain CBC mode. This bizarre change greatly simplifies crafting controlled changes to binaries to obtain arbitrary code execution. Suppose we know the sectors on disk where a particular application resides and we know exactly which version of that application it is. Now the PE format for Windows executables contains many sections- some of them meta-data/headers, others resources such as strings and icons. More interestingly, there are the portions which are truly “executable;” they contain the stream of instructions that will run when this application is invoked. Being able to manipulate even a small number of instructions in that stream achieves code execution.

There are several practical difficulties along the way. As pointed out, CBC mode does not permit changes with surgical precision- we can control one full block of 16 bytes but only at the expense of having no say over the preceding one. But one can repeat the same trick with the next two adjacent blocks, getting to control  one out of two blocks in each sector. That calls for an unusual way to organize shell code: divide it into small fragments of 14 bytes or less, with 2-byte relative forward jumps at the end to skip over the next block that is outside our control. (As the analog of return-oriented programming, this could be jump-oriented programming.) We also need to locate a candidate block that can be used as entry point into the shell code. Recall that controlling block N requires that we modify block N-1; that means code linearly executing through block N-1 may crash or do strange things before reaching block N. Instead we need to find a point in the binary where a branch or call target lands at the beginning of a nicely aligned 16-byte block. Considering that most functions will be aligned at 8 or 16 byte addresses, this is not a significant hurdle.

Exploiting this against a local Bitlocker-protected boot volume is straightforward, as demonstrated in the iSEC research: choose a binary that is guaranteed to be executed automatically on boot without user action- such as winlogon– along with a code path in that binary that is guaranteed to be hit. For removable drives and cloud storage, it is less clear whether these conditions will arise in practice. Such volumes typically contain “data”- documents, presentations, music, photography etc. instead of executable files that can be readily infected with shellcode. (Exception being whole-system images meant for recovering from an OS corruption.) But one can not rule out more sophisticated attacks; the definition of what counts as “executable” is itself encoded in the filesystem metadata, which can be modified with the same technique for modifying file contents. For example the user may have uploaded a Word document with “doc” extension to the cloud. But if we change the extension to “bat” and modify the contents appropriately to create a valid batch file, we get code execution.

There is another challenge that makes exploitation harder for the cloud case: knowing exactly where on disk the file targeted for modifications resides. This is easier to determine for local attacks where disk layout is based on a fixed template. If we know the victim is using a particular Dell laptop with factory-installed Windows image, we can order an identical laptop with same size disk and examine which sectors the target binary occupies on that Window installation. (This will not work for files that are replaced. For example if an OS update brings in a new version of some system binary, chances are it will not be updated in place. Instead it will be recreated by assigning new sectors from unused space— sectors whose locations are unpredictable because they are based on the pattern disk usage up until that point.) By contrast volumes synced to the cloud do not have a fixed structure, directory pattern or naming convention that can be used to estimate where interesting data may have ended up.

Still, none of these problems qualify as a systemic mitigation. If anything the remote storage scenario illustrates why it is necessary to move beyond the core assumption in FDE, namely that each sector must encrypt to exactly one sector, with no room for expansion to accommodate integrity checks. That is a reasonable assumption for local disk encryption for reasons articulated in the Elephant diffuser whitepaper: compatibility when encrypting existing volumes, performance overhead from having to read/write multiple sectors if integrity checks were stored separately and resulting requirement for transactional updates. None of these constraints apply to cloud storage. It may be possible to retrofit required data expansion into protocols such as iSCSI to salvage full-disk encryption. A more pessimistic conclusion is that FDE is not the right framework for creating private storage in the cloud, and different file-system level approaches may be necessary.