Potato Writeup - Proving Grounds
Last updated May 10, 2026 • 3 min read
Discovery
Three open TCP ports: SSH on 22, HTTP on 80, and ProFTPD on port 2112. The FTP service allows anonymous login and already lists an interesting file: index.php.bak.
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Potato company 2112/tcp open ftp ProFTPD | ftp-anon: Anonymous FTP login allowed (FTP code 230) | -rw-r--r-- 1 ftp ftp 901 Aug 2 2020 index.php.bak |_-rw-r--r-- 1 ftp ftp 54 Aug 2 2020 welcome.msg
Enumeration
FTP — Source Code Leak
Download everything from the FTP share anonymously:
index.php.bak saved [901] welcome.msg saved [54]
index.php.bak contains the login source for the admin panel. The password comparison uses strcmp():
<?php
$pass= "potato"; //note Change this password regularly
if($_GET['login']==="1"){
if (strcmp($_POST['username'], "admin") == 0 && strcmp($_POST['password'], $pass) == 0) {
echo "Welcome! </br> Go to the <a href=\"dashboard.php\">dashboard</a>";
setcookie('pass', $pass, time() + 365*24*3600);
}else{
echo "<p>Bad login/password!...</p>";
}
exit();
}
?>
strcmp() in PHP returns 0 (truthy-false) when comparing a string to an array — a classic type-juggling bypass. Passing password[] as an array instead of a string causes strcmp() to return NULL, which evaluates as equal to 0.
Directory enumeration finds /admin/ with a login form and a /admin/logs/ directory.
Admin Login Bypass
<html><body> Welcome! </br> Go to the <a href="dashboard.php">dashboard</a>
Directory Traversal — Password Disclosure
The dashboard's log viewer at /admin/dashboard.php?page=log POSTs a file parameter. It reads and displays the selected file with no path sanitisation — a directory traversal. Reading the live index.php reveals the actual current password set in the running application:
Contenu du fichier ../index.php : $pass= "serdesfsefhijosefjtfgyuhjiosefdfthgyjh";
The same traversal also reads /etc/passwd, which exposes a non-standard entry: webadmin with a $1$ MD5crypt hash embedded directly in the passwd file.
webadmin:$1$webadmin$3sXBxGUtDGIFAcnNTNhi6/:1001:1001:webadmin,,,:/home/webadmin:/bin/bash
Extract the hash and crack it with hashcat mode 500 (md5crypt):
$1$webadmin$3sXBxGUtDGIFAcnNTNhi6/:$WEBADMIN_PASSWORD Status: Cracked Hash.Mode: 500 (md5crypt)
Initial Access
[email protected]'s password: webadmin@serv:~$
Privilege Escalation
Check sudo permissions:
User webadmin may run the following commands on serv:
(ALL : ALL) /bin/nice /notes/*
The rule allows running /bin/nice with any path matching /notes/* as root. The wildcard only validates the prefix — it doesn't prevent path traversal. Passing /notes/../bin/bash satisfies the glob match while actually executing /bin/bash as root:
root@serv:/home/webadmin#
Root shell obtained.
References
-
PHP — strcmp() type juggling behaviourwww.php.net/manual/en/function.strcmp.php (opens in new tab)
strcmp() returns NULL when comparing against an array — evaluates as 0 in loose comparison
-
GTFOBins — nicegtfobins.github.io/gtfobins/nice (opens in new tab)
nice sudo abuse via argument path traversal to execute arbitrary binaries