Description
Server-Side Request Forgery (SSRF) is a vulnerability that allows an attacker to make the server perform unauthorized requests to internal or external systems. The attacker can leverage this to bypass network restrictions, access internal systems, or exfiltrate sensitive data.
How SSRF Works
SSRF occurs when an application takes user input and uses it to form a request to another server, without sufficient validation. This can be exploited in various ways:
Internal Network Scanning: The attacker can use the server to scan and map the internal network.
Accessing Internal Services: The attacker can interact with internal services that are not exposed to the external network.
Exfiltrating Data: The attacker can use the server to send data to an external system.
Real-World Scenarios
Cloud Metadata Service Access:
Many cloud providers offer a metadata service that provides information about the instance. This service is usually accessible at a well-known IP address. An attacker can exploit SSRF to access this service and retrieve sensitive information, such as access tokens.
Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```ruby http://example.com/vulnerable.php?url=http://169.254.169.254/latest/meta-data/ ``` The attacker can access the cloud instance metadata and potentially retrieve sensitive data like IAM roles and temporary credentials. Interacting with Internal APIs: Many applications have internal APIs that are not exposed to the public internet but are accessible internally. An attacker can use SSRF to interact with these APIs. Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```bash http://example.com/vulnerable.php?url=http://localhost/admin/api ``` The attacker can potentially perform administrative actions by interacting with the internal API. Port Scanning: SSRF can be used to scan for open ports on the internal network. By crafting requests to different ports, an attacker can identify open services. Example: ```php <?php if (isset($_GET['url'])) {
$url = $_GET['url'];
$content = file_get_contents($url);
echo $content; } else {
echo "No URL provided."; } ?> ``` Attack: ```bash
http://example.com/vulnerable.php?url=http://localhost:8080 ```
The attacker can determine if a service is running on port 8080.
Case Study: Capital One Breach
One of the most notable examples of SSRF exploitation was the Capital One breach in 2019. The attacker exploited an SSRF vulnerability in a web application firewall (WAF) hosted on AWS. By leveraging SSRF, the attacker accessed the AWS metadata service to obtain temporary credentials, which were then used to access sensitive data stored in S3 buckets.
Key Points of the Attack:
Initial Exploit: The attacker sent a request that exploited the SSRF vulnerability, targeting the AWS metadata service.
Credential Theft: By accessing the metadata service, the attacker retrieved AWS IAM credentials.
Data Exfiltration: Using the stolen credentials, the attacker accessed and exfiltrated data from S3 buckets. Exploitation Path
SSRF Exploit: ```ruby http://vulnerable-app.com/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ Credential Access: ```ruby http://vulnerable-app.com/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name ``` S3 Data Access: ```bash aws s3 ls s3://sensitive-data-bucket --profile stolen-credentials ```
Mitigation
- Whitelist Valid URLs
Only allow requests to a predefined set of trusted domains. This ensures that any request made by the application is to a safe and known destination.
```php
<?php
$whitelisted_domains = [‘example.com’, ‘api.example.com’];
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
$parsed_url = parse_url($url);
if (in_array($parsed_url['host'], $whitelisted_domains)) {
$content = file_get_contents($url);
echo $content;
} else {
echo "Invalid URL.";
} } else {
echo "No URL provided."; } ?> ``` 2. Validate and Sanitize Input Ensure that the URL provided by the user is valid and adheres to your expectations. This involves checking the URL's scheme, host, and structure. ```php <?php function validate_url($url) {
$parsed_url = parse_url($url);
if ($parsed_url === false) {
return false;
}
$allowed_schemes = ['http', 'https'];
if (!in_array($parsed_url['scheme'], $allowed_schemes)) {
return false;
}
return true; }
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
if (validate_url($url)) {
$content = file_get_contents($url);
echo $content;
} else {
echo "Invalid URL.";
} } else {
echo "No URL provided."; } ?> ``` 3. Block Private IP Ranges Prevent the server from making requests to internal IP addresses. This helps to stop the server from accessing internal services and sensitive resources. ```php <?php function is_private_ip($ip) {
$private_ips = [
'10.0.0.0|10.255.255.255',
'172.16.0.0|172.31.255.255',
'192.168.0.0|192.168.255.255',
'127.0.0.0|127.255.255.255'
];
$ip_long = ip2long($ip);
if ($ip_long != -1) {
foreach ($private_ips as $private_ip) {
list($start, $end) = explode('|', $private_ip);
if ($ip_long >= ip2long($start) && $ip_long <= ip2long($end)) {
return true;
}
}
}
return false; }
if (isset($_GET[‘url’])) {
$url = $_GET[‘url’];
$parsed_url = parse_url($url);
$host = $parsed_url[‘host’];
$ip = gethostbyname($host);
if (is_private_ip($ip)) {
echo "Invalid URL.";
} else {
$content = file_get_contents($url);
echo $content;
} } else {
echo "No URL provided."; } ?> ``` By implementing these three strategies—whitelisting valid URLs, validating and sanitizing input, and blocking private IP ranges—you can significantly reduce the risk of SSRF vulnerabilities in your application ---