Tags: aes-cbc aes cbc iv cbc-bit-flipping
Rating:
duudududduduud
==============
### Info
- Original Link: [http://54.169.92.223/](http://54.169.92.223/)
- Hint: `backup.bak?`
- Flag: `AceBear{From_Crypt0_m1sus3_t0_Rc3_______}`
### What do we have?
![Landing Page](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/01%20-%20login%20screen.png)
- We arrive at a page that asks us to login
- We are able to register an account
- We are able to login with that account
- The website reminds us that we are not an admin, clearly we need to login as an admin
### Let's solve it
![Backup File](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/02%20-%20backup.bak.png)
- Naturally, we use the hint, and of course, find a `backup.bak` file
- All of the code is here, it's just a matter of figuring out what's what
- I've kept a copy of the code which can be found [here](https://github.com/ash47/CTF-WriteUps/tree/master/AceBear%20Security%20Contest%202019/duudududduduud/backup/web01) (note that I removed a .git directory that appeared to be not relevant, and was 60MB)
![Login Logic](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/03%20-%20login%20logic.png)
- Naturally, us wanting to login as an admin and all, we take a look at `login.php`
- On line `10` we can see there is an SQL injection via the username parameter
- The username is fed in via the `session_remember` cookie
- The cookie is actually fed into a `check_cookie` function
![AES Stuff](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/04%20-%20aes%20stuff.png)
- This quickly leads us to `lib/connection.php`
- The first thing we notice is line `10` which is clearly where our flag will be -- We need to read the contents of this file
- Up next, we can see our `check_cookie` function
- This function takes 2 arguments, a string to decrypt and the secret key, which we don't know
- The first argument is based64 decoded, and then AES decrypted, most notable here is that the IV and the KEY are the same -- if we can get the original IV, we can get the key
![Critical Flaw](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/05%20-%20critical%20flaw.png)
- Let me draw your attension back to `login.php` and show you a critical flaw here
- If the SQL query doesn't return EXACTLY 1 row, be that for any reason, then the server will output the AES decrypted string :O
- Worst case, we can brute force our way to victory, best case, we can do some AES CBC magic
![AES CBC Diagram](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/06%20-%20classic%20aes%20cbc%20diagram.png)
- Here's a diagram of how AES CBC actually works, and I'll explain the important parts of decrpytion here
- AES is a block cipher, meaning that it breaks all of your data into fixed blocks, and encrypts them block by block
- Starting from the second block onwards, the decryption happens as follows:
- The block is decrypted using the secret key
- This generates some garbage text
- The garbage text is then XORed with the CIPHER TEXT of the previous block (which we fully know, obviously) which results in the plaintext
- It stands to reason then, if we modify the cipher text of the 1st block, it will directly affect the contents of the second block
![Simon Smells](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/07%20-%20simon%20smells.png)
- I put this theory into practice and wrote a small script that allows you to modify the ciphertext of the first block in a special way that lets you control the plaintext of the second block
- As you can see, I was able to make the decrypted contents of the second block read `Simom Smells`
- From here, I can easily put an SQL injection payload into the second block
- The main issue is, I need a MUCH LONGER query than what can fit into a single block
- My next idea, is, I can inject into every SECOND block (i.e. blocks 2, 4, 6, 8, etc)
- If I inject part of an SQL injection statement into the first block, and the end it with a `/*`, it won't matter what the third block decrypts to
- In the forth block, I can start it with a `*/` put some more SQL injection magic, then end it with a `/*` and continue this process until I have a full payload, and then ultimately end it with a `--` to comment out the rest of the junk
![Payload works](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/08%20-%20payload%20works.png)
- I sent the server a bunch of `A`s and got the decrypted form of that for use within my script
- I wrote a small script in NodeJS to generate this token for me which can be viewed [here](https://github.com/ash47/CTF-WriteUps/blob/master/AceBear%20Security%20Contest%202019/duudududduduud/web01_tool.js)
- The token ultimately injected the following into the blocks: `' UNION /*XXXXXXXXXXXXXXXX*/ SELECT /*XXXXXXXXXXXXXXXX*/ 'lol',1 -- /*XXXXXXXXXXXXXXXX*/a/*`
- Note that the `XXXXXXXXXXXXXXXX` are blocks that I couldn't control
- We do a union select with username = `lol` and `admin` = `1`, we know the syntax of the SQL command from reviewing the source code of the `login.php` from earlier
- The server allocates us a cookie which gives us admin access
![Confirmed as admin](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/09%20-%20confirmed%20admin.png)
- We use the cookie and confirm that we are actually an admin
- We get a hint that says something isn't implemented right for admins
- Naturally, we notice the upload button at the top of the screen
![Upload Page](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/10%20-%20upload%20page.png)
- We browse to the upload page and confirm that it's working, nice! We truly are an admin!
![Code Review](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/11%20-%20critical%20code.png)
- We have the code, let's just see how it works
- Line `47` shows us that it looks for a `manifest.json` file
- Line `48` shows us that there must be a parameter within the `manifest.json` file that is `type` = `h4x0r` and we must have `name` set to anything
- We can trivially make this file, and then we should be able to upload ANYTHING at that point `{"type": "h4x0r","name": "pwned"}`
- Add any web shell you please
![Got the flag](https://raw.githubusercontent.com/ash47/CTF-WriteUps/master/AceBear%20Security%20Contest%202019/duudududduduud/12%20-%20got%20the%20flag.png)
- With a webshell uploaded, it's just a matter of running the `cat` command with the correct path to the orignal `lib/connection.php` file
- We can see that the key is in here, and the flag itself
### Something extra
- You can technically recover the original IV via this poor implementation of AES CBC via XORing the right things together with a specially crafted payload
- I thought it was more fun doing an SQL injection attack like this, and may attack would still work even if the IV wasn't the same as the key
- This was super cool and fun