Intro

SadServers is a LeetCode style puzzle for Sysadmins/Site Reliability Engineers/DevOps Engineers or whatever Ops people in IT are called nowadays. The following is a writeup of walking through the challenges given.

New challenges have been added since our last look at the project, so let’s dive in!

Pokhara

A user client was added to the server, as well as their SSH public key. The objective is to be able to SSH locally (there’s only one server) as this user client using their ssh keys. This is, if as root you change to this user sudo su; su client, you should be able to login with ssh: ssh localhost.

admin@ip-172-31-36-133:/$ sudo -u client -i
This account is currently not available.

Right off the bat, it’s clear the user account doesn’t have a login shell. Let’s give it one:

admin@ip-172-31-36-133:/$ sudo chsh -s /bin/bash client

Let’s poke around in the user’s home directory:

admin@ip-172-31-36-133:/$ sudo -u client -i
client@ip-172-31-36-133:~$ ls -lhA
total 24K
-rw------- 1 client client  475 Feb  6 00:24 .bash_history
-rw-r--r-- 1 client client  220 Aug  4  2021 .bash_logout
-rw-r--r-- 1 client client 3.5K Aug  4  2021 .bashrc
drwxr-xr-x 3 client client 4.0K Feb  5 22:48 .local
-rw-r--r-- 1 client client  807 Aug  4  2021 .profile
drwx------ 2 client client 4.0K Feb  6 00:21 .ssh
client@ip-172-31-36-133:~$ ls -lhA .ssh/
total 16K
-rw------- 1 client client  569 Feb  6 00:21 authorized_keys
-rw-r--r-- 1 client client 2.6K Feb  5 22:33 id_rsa
-rw-r--r-- 1 client client  569 Feb  5 22:49 id_rsa.pub
-rw-r--r-- 1 client client  222 Feb  5 22:27 known_hosts
client@ip-172-31-36-133:~$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQopf1DsoscAMwsWJL1V1F1GHom1+qwkp0QlXnfWP+bKwkXZfTj+IIvtEZ3ECyIQa2bMEFdME9aU67vJoF4X3KSvQQijxr9ng5fWhVxvCauYdVi4UU1NtvHtw7RUj+gIIwcqmOg2/wwhRb7zjN53arsaJu0P77VOhwTRYI0fcUX6iE+W6wNvKRBvnZShSla5pCk0x7Ox2wptYfTnbIOx6+me7g9fkctakm1yeujsRbQjJHwkfdLfYhMJkT4wibLvJSooB5WIe62ioCcFbiHEywMrrdKH8oCy8i8wD28S5vh6FTZiZxBX6nL7HModXQI9RV6mZ9TE/ZovWYCk3Cp0675JoWEM94C53S+5eVtZTj4l2ZsYwmc8WaJiullLYdWEYi2jtmnHxsnFQ/YZ/Tf9zndRBVUPKuG84mGzJ5Fs28w0u5SiNeHdS0OOHvAcGnuoweKigt01JRJdt8DZO+N8jCEM/jo1TST131sy1TLyylY6zBe6ID/uoyWkVLc5/iFhM= client@somehost
client@ip-172-31-36-133:~$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDQopf1DsoscAMwsWJL1V1F1GHom1+qwkp0QlXnfWP+bKwkXZfTj+IIvtEZ3ECyIQa2bMEFdME9aU67vJoF4X3KSvQQijxr9ng5fWhVxvCauYdVi4UU1NtvHtw7RUj+gIIwcqmOg2/wwhRb7zjN53arsaJu0P77VOhwTRYI0fcUX6iE+W6wNvKRBvnZShSla5pCk0x7Ox2wptYfTnbIOx6+me7g9fkctakm1yeujsRbQjJHwkfdLfYhMJkT4wibLvJSooB5WIe62ioCcFbiHEywMrrdKH8oCy8i8wD28S5vh6FTZiZxBX6nL7HModXQI9RV6mZ9TE/ZovWYCk3Cp0675JoWEM94C53S+5eVtZTj4l2ZsYwmc8WaJiullLYdWEYi2jtmnHxsnFQ/YZ/Tf9zndRBVUPKuG84mGzJ5Fs28w0u5SiNeHdS0OOHvAcGnuoweKigt01JRJdt8DZO+N8jCEM/jo1TST131sy1TLyylY6zBe6ID/uoyWkVLc5/iFhM= client@somehost
client@ip-172-31-36-133:~$
logout

The keys match, permissions look good? The login should work now, right?

admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:eGRNfwL5WEmr/DyP7hMtKGGT781nAHWWUcLPYrGJEQY.
Please contact your system administrator.
Add correct host key in /home/client/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/client/.ssh/known_hosts:1
  remove with:
  ssh-keygen -f "/home/client/.ssh/known_hosts" -R "localhost"
ECDSA host key for localhost has changed and you have requested strict checking.
Host key verification failed.

Yeah ok - The users’ known_hosts won’t be useful here. Purge it:

admin@ip-172-31-36-133:/$ sudo -u client -i
client@ip-172-31-36-133:~$ truncate -s0 ~/.ssh/known_hosts

Another try:

admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:eGRNfwL5WEmr/DyP7hMtKGGT781nAHWWUcLPYrGJEQY.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
client@localhost: Permission denied (publickey).

Nope. Let’s look at sshd’s logs:

admin@ip-172-31-36-133:/$ sudo -i
root@ip-172-31-36-133:~# journalctl -xe -u sshd
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
-- Journal begins at Wed 2022-08-31 21:25:54 UTC, ends at Tue 2023-02-14 08:58:06 UTC. --
-- No entries --

Great. No logs…

Looking around in /etc we find a curious config file:

root@ip-172-31-36-133:~# cat /etc/ssh/sshd_config.d/sad.conf
DenyUsers client

Go away config file, you are in our way:

root@ip-172-31-36-133:~# rm -f /etc/ssh/sshd_config.d/sad.conf
root@ip-172-31-36-133:~# systemctl reload sshd
root@ip-172-31-36-133:~#
logout
admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/client/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/client/.ssh/id_rsa": bad permissions
client@localhost: Permission denied (publickey).

Ah crud - should have spotted that earlier…

client@ip-172-31-36-133:~$ ls -lhA .ssh/
total 16K
[...]
-rw-r--r-- 1 client client 2.6K Feb  5 22:33 id_rsa

Too wide indeed, it should be u=r,go= or 0600:

admin@ip-172-31-36-133:/$ sudo chmod 0600 /home/client/.ssh/id_rsa

Ok, does it work now?

admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
Your account has expired; please contact your system administrator.

Of course it doesn’t. The author seems to have pulled out all the stops on this one :-). So let’s see what’s wrong with the account’s expiration date…

admin@ip-172-31-36-133:/$ sudo chage -l client
Last password change                                    : Feb 05, 2023
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : Jan 01, 1970
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

Where we are going, we need no stinking expiration dates:

admin@ip-172-31-36-133:/$ sudo chage -E -1 client
admin@ip-172-31-36-133:/$ sudo chage -l client
Last password change                                    : Feb 05, 2023
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

Now it should work, right?

admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
exec request failed on channel 0

Err… huh? What? Frantic googling reveals this is connected to ptys being unavailable. But everything is alright on the system, even forcing an allocation of one with -t doesn’t help…. AAAAH - is it a ulimit thing?

admin@ip-172-31-36-133:/$ sudo -i
root@ip-172-31-36-133:~# cat /etc/security/limits.conf
# /etc/security/limits.conf
[...]
client          hard    nproc           0
# End of file

Ah, the client user may not spawn any processes. Good, remove the limit and all should be well now:

root@ip-172-31-36-133:~# sed -i -e "/client/d" /etc/security/limits.conf
root@ip-172-31-36-133:~#
logout
admin@ip-172-31-36-133:/$ sudo -u client ssh client@localhost 'pwd'
/home/client

Excellent, SSHing works again.

Roseau

There is a secret stored in a file that the local Apache web server can provide. Find this secret and have it as a /home/admin/secret.txt file.

Note that in this server the admin user is not a sudoer.

Also note that the password crackers Hashcat and Hydra are installed from packages and John the Ripper binaries have been built from source in /home/admin/john/run

This is a little different from the other challenges, this puts us more in the attacker’s role.

admin@ip-172-31-43-232:/$ ls /var/www/html
/var/www/html/webfile
admin@ip-172-31-43-232:/$ cat /var/www/html/webfile
cat: /var/www/html/webfile: Permission denied
admin@ip-172-31-43-232:/$ curl http://localhost/webfile
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>401 Unauthorized</title>
</head><body>
<h1>Unauthorized</h1>
<p>This server could not verify that you
are authorized to access the document
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.</p>
<hr>
<address>Apache/2.4.54 (Debian) Server at localhost Port 80</address>
</body></html>

This little bit of reconnaissance reveals that our target is /var/www/html/webfile or http://localhost/webfile. We can’t access it via files or webserver, as the permissions on the file are solid and the web server wants authentication. Let’s look at the webserver’s configuration:

admin@ip-172-31-43-232:/$ cat /etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined


        <Directory "/var/www/html">
                AuthType Basic
                AuthName "Protected Content"
                AuthUserFile /etc/apache2/.htpasswd
                Require valid-user
        </Directory>
</VirtualHost>

So as the challenge intro hinted at john and hashcat, I’m guessing that we can access the .htpasswd file…

admin@ip-172-31-43-232:/$ cat /etc/apache2/.htpasswd
carlos:$apr1$b1kyfnHB$yRHwzbuKSMyW62QTnGYCb0

Jup. Let’s give john something to do then…

admin@ip-172-31-43-232:~$ john/run/john /etc/apache2/.htpasswd
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Warning: Only 34 candidates buffered for the current salt, minimum 48 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
0g 0:00:00:00 DONE 1/3 (2023-02-14 09:33) 0g/s 8733p/s 8733c/s 8733C/s Carlos1921..Carlos1900
Proceeding with wordlist:john/run/password.lst
Enabling duplicate candidate password suppressor
chalet           (carlos)
1g 0:00:00:01 DONE 2/3 (2023-02-14 09:33) 0.6097g/s 40560p/s 40560c/s 40560C/s 050381..song
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

So it’s carlos with chalet. Log in to the webserver and grab the file then…

admin@ip-172-31-43-232:~$ curl -u carlos:chalet http://localhost/webfile
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
admin@ip-172-31-43-232:~$ curl -u carlos:chalet http://localhost/webfile -o -
PK
        MVƪ
secret.txtUT    âcâcux
                      sƪPK
        MVƪ
secret.txtUTâcux
                PKPqadmin@ip-172-31-43-232:~$

Ok… The PK start screams zip file, and file agrees:

admin@ip-172-31-43-232:~$ curl -u carlos:chalet http://localhost/webfile -o - | file -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   215  100   215    0     0  71666      0 --:--:-- --:--:-- --:--:-- 71666
/dev/stdin: Zip archive data, at least v1.0 to extract

Download and extract:

admin@ip-172-31-43-232:~$ curl -u carlos:chalet http://localhost/webfile -o - > out.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   215  100   215    0     0  16538      0 --:--:-- --:--:-- --:--:-- 16538
admin@ip-172-31-43-232:~$ unzip out.zip
Archive:  out.zip
[out.zip] secret.txt password:
password incorrect--reenter: ^C

A password protected zip file… Huh. Google to the rescue, how can I feed that to john?

Like unshadow, John has another utility called zip2john. zip2john helps us to get the hash from zip files. If you are cracking a .rar file, you can use the rar2john utility.

Here is the syntax to get the password hash of a zip file:

$ zip2john file.zip > zip.hashes

The above command will get the hash from the zip file and store it in the zip.hashes file. You can then use John to crack the hash.

$ john zip.hashes

Off we go then…

admin@ip-172-31-43-232:~$ john/run/zip2john out.zip > zip.hashes
ver 1.0 efh 5455 efh 7875 out.zip/secret.txt PKZIP Encr: 2b chk, TS_chk, cmplen=29, decmplen=17, crc=AAC6E9AF ts=14E0 cs=14e0 type=0
admin@ip-172-31-43-232:~$ john/run/john zip.hashes
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
0g 0:00:00:00 DONE 1/3 (2023-02-14 09:36) 0g/s 904900p/s 904900c/s 904900C/s Txtout1900..Tsecret1900
Proceeding with wordlist:john/run/password.lst
Enabling duplicate candidate password suppressor
andes            (out.zip/secret.txt)
1g 0:00:00:00 DONE 2/3 (2023-02-14 09:36) 2.439g/s 1419Kp/s 1419Kc/s 1419KC/s poussinet..nisa1234
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

There it is, andes is the password.

admin@ip-172-31-43-232:~$ unzip out.zip
Archive:  out.zip
[out.zip] secret.txt password:
 extracting: secret.txt

And we’re done.