Bibliobibuli
Introduction
For this challenge we are directed towards an RFC index at http://bibliobibuli.ctf which allows one to search through a catalog of RFCs each of which can be read at a URL of http://bibliobibuli.ctf/?f=rfcs/rfc1337.txt.
Finding the backdoor
Based on the format of the URLs it is natural to assume that the RFC are backed by files somewhere, and indeed it turns out that these files are accessible at http://bibliobibuli.ctf/rfcs/rfc1337.txt and even a directory listing is possible at http://bibliobibuli.ctf/rfcs/ and this reveals a x.php file in this directory which can be executed. Using the original RFC viewer it is possible to retrieve the file at http://bibliobibuli.ctf/?f=rfcs/x.php.
It turns out that this file is an already installed backdoor which, when called without parameters or session, generates a pair of encryption and decryption keys which are both stored in the session and sent back to the client under asymmetric encryption. When called with an active session and a POST parameter c
it attempts to decrypt the contents of c
with the sessions decryption key, execute the resultant command, and then encrypt the output of the command using the encryption key. The initial decryption happens using the PHP openssl_decrypt
1 function in AES-256-CBC
mode. If this decryption fails, the script returns 500
and dies. As this the AES-256-CBC
mode does not contain any authenticity checks, the only way this can fail is with a padding error. This exposes a padding oracle
The exploit
As exploiting a padding oracle can generate a great deal of requests and take a fair amount of time, we cache results between execution to make development more tolerable and the organisers slightly more happy.
|
|
First we perform initial setup. As we can choose the last block of our ciphertext freely, we pick something identifiable so that the organisers know who to complain to if we are hammering their services too hard. Then either load state from disk, if it exists, or we initialise a new session and zero-block memoization.
|
|
This is then the function which exploits the padding oracle. Stepping through the 16 possible paddings we determine what the value of the previous ciphertext block must be in order to generate a plaintext block of all-zeros. This works as the previous block of ciphertext is xor’d with the output of decrypting the current block of ciphertext to produce the plaintext. Thus any changes in the previous ciphertext are reflected in the current plaintext.2 We can xor our own content into this zero generating ciphertext in the next step to run commands.
|
|
Here we take the zero-block function and put it to work to execute a command. We start by applying padding to the command and then from the back generate zero-blocks using the padding oracle and xor our command into it.
|
|
Finally we use all of this to deliver a PHP reverse shell as we have good reason to believe that PHP is installed. We start with a newline as the fixed IV of the backdoor forces us to have an initial block of garbage in the command which we need to not interfere with our shell.
$ nc -lvnp 9001
Listening on 0.0.0.0 9001
Connection received on XXX.XXX.XXX.XXX 42644
cat /flag
Profit!