flawopen.com/ssrf/Php
How curl_exec in PHP exposes internal networks, and how to filter IPs using FILTER_VALIDATE_IP and CURLOPT_FOLLOWLOCATION.
कल्पना करें कि आप एक सहायक को सार्वजनिक दुकान से पार्सल लाने के लिए भेजते हैं, लेकिन उसे प्रबंधक के कार्यालय में रखी बंद तिजोरी का पता देते हैं। चूंकि सहायक के पास आंतरिक सुरक्षा बैज है, वह तिजोरी खोलकर कंपनी के रहस्य आपको सौंप देता है।
Web Application SecurityCWE-918.CWE-918CWE-918): Standard Common Weakness Enumeration classification for ssrf-php.Defense-in-Depthएप्लिकेशन इमेज फ़ेचिंग, वेबहुक या पीडीएफ़ जनरेशन के लिए उपयोगकर्ता द्वारा दिया गया URL स्वीकार करता है।
हमलावर क्लाउड मेटाडेटा सेवा (उदा. http://169.254.169.254/latest/meta-data/) या लूपबैक एड्रेस इनपुट करता है।
सर्वर बिना आईपी सत्यापन के आंतरिक वीपीसी नेटवर्क से अनुरोध भेज देता है।
आंतरिक मेटाडेटा सेवा सर्वर के अनुरोध पर विश्वास करके अस्थायी आईएएम टोकन और गुप्त कुंजियाँ लौटा देती है।
<?php
// VULNERABLE: file_get_contents on user-controlled URL
$url = $_GET['url'];
// Attacker input: http://169.254.169.254/latest/meta-data/
$content = file_get_contents($url);
echo $content;
?>
<?php
// HARDENED: Parse URL, resolve DNS, filter private IPs, and disable redirects
$url = $_GET['url'] ?? '';
$parsed = parse_url($url);
if (!$parsed || !in_array(strtolower($parsed['scheme'] ?? ''), ['http', 'https'], true)) {
http_response_code(400);
exit('Invalid URL scheme');
}
$host = $parsed['host'] ?? '';
$ips = gethostbynamel($host);
if (!$ips) {
http_response_code(400);
exit('Unable to resolve host');
}
// Check every resolved IP address
foreach ($ips as $ip) {
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
http_response_code(403);
exit('Access to private/internal address denied');
}
}
// Fetch using cURL with redirects disabled
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false, // Prevent redirect bypasses
CURLOPT_TIMEOUT => 3,
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>