My self is steam

Insights into computer security, programming and math


September 11, 2018
The Penguin Still Shows Through

An account of CVE-2018-5548

Sometimes a technical discipline manages to reach the point of providing the wrong answers to the right problems, as in the case of what is commonly misnamed Software Engineering. It may also happen that a whole industry is built on the belief that no answers to the wrong problems is a profitable strategy to respond to the demanding needs of an ever-growing customer base. Historically, such a case is exemplified by the infosec industry. It's a sterile exercise to acknowledge that the industry has reached the point where flame wars about irresponsible disclosure, embargos and branded vulnerabilities are the major pillars of its dialectic. Thirty years after the Morris Worm, we are still dealing with WannaCry, after all.

My little personal contribution to the gallery of infosec failures is the discovery of a vulnerability in F5 BIG-IP. The vulnerability has been assigned CVE-2018-5548.

BIG-IP products can be deployed to function as an Access Policy Manager, which provides, among other things, authentication facilities to web applications. Under such configuration, the appliance conceals redirect location URLs by encrypting them in a query string parameter, probably in the attempt to prevent tampering and forging. This puts the appliance in the situation of behaving as a cryptographic oracle vulnerable to chosen-plaintext attacks (and to a certain extent, chosen-ciphertext), since it allows the attacker to obtain the ciphertexts of arbitrary plaintexts she controls, the plaintexts being the concealed Location header values of HTTP Redirect responses.

The encryption mode of operation chosen by the vendor is ECB, on the security of which many things have been said . Whenever the next talk about Quantum Cryptography hits the news, let's remember that ECB mode of operation is still dropping bodies.

By specifying an arbitrary relative URL on a page requiring authentication by the BIG-IP, we receive the following JavaScript code among the responses:

The code defines the variable ‘requestURI’ to be a further relative URL whose query string contains an ‘orig_uri’ parameter of value apparently encrypted. This variable is used in the decisional process which in the end leads the browser to navigate to the URL:

Attempting to request the URL directly results in a redirection to the relative path we specified in the former request:

It means that there is something in the value of “redirectURI” which refers to the relative path “/azerty”. It is important to understand that this parameter is under the control of the attacker. The parameter is Base64-encoded, and decoding it results in what appears to be random data:

The first hint towards the encryption hypothesis comes from the length of the decoded ciphertext, which is always aligned to multiples of the block size, namely 16 bytes, as it can be seen by increasing the length of the plaintext path:

This suggests padding, in order to ensure that the encrypting chunks of data are always of the same size of the block, assuming that the algorithm is a block-cipher. Our first assumption is then that the URL sent to the authentication provider is encrypted by a block cipher like AES.

Interestingly enough, requesting the same URL produces always the same encrypted string, which suggests two things: the mode of operation is either ECB or CBC with initial values that never change. If we specify a plaintext like “aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa” we obtain five blocks of which three are identical. Only the extremities are different:

This implies that the first and the last block differ somehow, the former mismatch is probably due to additional characters added by the appliance itself and the latter to padding. As it turns out, the appliance is adding at least a total of 6 bytes at the beginning (first block) and at the end (last block) of the URL. This piece of information is not controlled by the attacker.

Since a 16 bytes long plaintext is encrypted to a 32 bytes long ciphertext, it is enough to decrease incrementally the length of the chosen plaintext, one byte at a time starting from 16 bytes, until the corresponding ciphertext length is exactly one block long. Indeed, such a ciphertext is obtained when the plaintext is 10 bytes long or less, implying that 6 bytes are added to the plaintext by the appliance. This is confirmed by the fact that a 26 bytes long plaintext still encrypts to two blocks and a 27 bytes long one to three blocks. Since no more than the controlled input (the relative path) is present in the Location header, the additional bytes must be stripped by the appliance upon decryption, otherwise they would be observable.

A very likely possibility is that the mode of operation used is ECB since all the other modes, when encrypting plaintext blocks, are combining previous intermediate blocks according to a scheme (a xor operation for AES). ECB encrypts each block independently with the same key, which would explain why two identical plaintext blocks are encrypted to two identical cipher blocks. Under the assumption that ECB is used, we attempt to decrypt the first and last blocks of our plaintext payload to see what is added by the server, but in the payload the first and last blocks are not directly controllable, although the blocks in between are. The idea is then to send our payload (minimum of 3 blocks) and to retrieve the corresponding ciphertext; then we alter this ciphertext by replacing the second by a copy of the first block. This way, if ECB is in place, the appliance will decrypt the second block, revealing to us the value of the first block, which containts the bytes it adds at the beginning:

The resulting encrypted string is then used as the parameter in the query string:

The decryption succeeds, the oracle reveals what the BIG-IP adds in the first block. By applying the same technique to the last block, we conclude that it contains just PKCS7 padding. This latter result fully explains the observation of the additional 6 bytes: given that a 10 bytes long plaintext encrypts to a 16 bytes ciphertext, and that the string length of "url=/" is 5 bytes, the only possibility for the last byte is to be a padding byte according to the PKCS7 scheme.

This all means that we can control the full query string parameter of the request: the appliance not only encrypts chosen plaintexts but also decrypts chosen ciphertexts. Furthermore, we have confirmation that the mode of operation of the encryption algorithm is ECB.

The immediate consequence is that the anti-tampering mechanism devised by the vendor is completely defeated. We can in fact ask the oracle to encrypt a string like "aaaaaaaaaaaurl=http://evil.com", and reply the corresponding ciphertext back, from which we remove the first block, making it possible to forge apparently innocent URLs like: https://good.com/vdesk/c_ses.php3?orig_uri=96HDUEK5uKsfv3GYHM/qqBkq99TVlKNforF6/rcrogE%3D which instead redirects to an unguessable external domain:

This unlocked feature, combined with the fact that the destination URL is encrypted and obfuscated, transforms the BIG-IP into the ultimate Phishing factory.

When modernist currents' only goal seems to be the discouragement of artefacts that may be even remotely contaminated by the emotional luggage of popular culture, condemning art to serialized pranks, the true artist is comforted at the idea that he could still seek shelter in the contemplation of the perdurable ECB Penguin classic.