PenTest Playbook
  • Welcome!
  • Web App Pentesting
    • SQL Injection
    • NoSQL Injection
    • XSS
    • CSRF
    • SSRF
    • XXE
    • IDOR
    • SSTI
    • Broken Access Control/Privilege Escalation
    • Open Redirect
    • File Inclusion
    • File Upload
    • Insecure Deserialization
      • XMLDecoder
    • LDAP Injection
    • XPath Injection
    • JWT
    • Parameter Pollution
    • Prototype Pollution
    • Race Conditions
    • CRLF Injection
    • LaTeX Injection
    • CORS Misconfiguration
    • Handy Commands & Payloads
  • Active Directory Pentest
    • Domain Enumeration
      • User Enumeration
      • Group Enumeration
      • GPO & OU Enumeration
      • ACLs
      • Trusts
      • User Hunting
    • Domain Privilege Escalation
      • Kerberoast
        • AS-REP Roast (Kerberoasting)
        • CRTP Lab 14
      • Targeted Kerberoasting
        • AS-REP Roast
        • Set SPN
      • Kerberos Delegation
        • Unconstrained Delegation
          • CRTP Lab 15
        • Constrained Delegation
          • CRTP Lab 16
        • Resource Based Constrained Delegation (RBCD)
          • CRTP Lab 17
      • Across Trusts
        • Child to Parent (Cross Domain)
          • Using Trust Tickets
            • CRTP Lab 18
          • Using KRBTGT Hash
            • CRTP Lab 19
        • Cross Forest
          • Lab 20
        • AD CS (Across Domain Trusts)
          • ESC1
            • CRTP Lab 21
        • Trust Abuse - MSSQL Servers
          • CRTP Lab 22
    • Lateral Movement
      • PowerShell Remoting
      • Extracting Creds, Hashes, Tickets
      • Over-PassTheHash
      • DCSync
    • Evasion
      • Evasion Cheetsheet
    • Persistence
      • Golden Ticket
        • CRTP Lab 8
      • Silver Ticket
        • CRTP Lab 9
      • Diamond Ticket
        • CRTP Lab 10
      • Skeleton Key
      • DSRM
        • CRTP Lab 11
      • Custom SSP
      • Using ACLs
        • AdminSDHolder
        • Rights Abuse
          • CRTP Lab 12
        • Security Descriptors
          • CRTP Lab 13
    • Tools
    • PowerShell
  • AI Security
    • LLM Security Checklist
    • GenAI Vision Security Checklist
    • Questionnaire for AI/ML/GenAI Engineering Teams
  • Network Pentesting
    • Information Gathering
    • Scanning
    • Port/Service Enumeration
      • 21 FTP
      • 22 SSH
      • 25, 465, 587 SMTP
      • 53 DNS
      • 80, 443 HTTP/s
      • 88 Kerberos
      • 135, 593 MSRPC
      • 137, 138, 139 NetBios
      • 139, 445 SMB
      • 161, 162, 10161, 10162/udp SNMP
      • 389, 636, 3268, 3269 LDAP
      • Untitled
      • Page 14
      • Page 15
      • Page 16
      • Page 17
      • Page 18
      • Page 19
      • Page 20
    • Nessus
    • Checklist
  • Mobile Pentesting
    • Android
      • Android PenTest Setup
      • Tools
    • iOS
  • DevSecOps
    • Building CI Pipeline
    • Threat Modeling
    • Secure Coding
      • Code Review Examples
        • Broken Access Control
        • Broken Authentication
        • Command Injection
        • SQLi
        • XSS
        • XXE
        • SSRF
        • SSTI
        • CSRF
        • Insecure Deserialization
        • XPath Injection
        • LDAP Injection
        • Insecure File Uploads
        • Path Traversal
        • LFI
        • RFI
        • Prototype Pollution
        • Connection String Injection
        • Sensitive Data Exposure
        • Security Misconfigurations
        • Buffer Overflow
        • Integer Overflow
        • Symlink Attack
        • Use After Free
        • Out of Bounds
      • C/C++ Secure Coding
      • Java/JS Secure Coding
      • Python Secure Coding
  • Malware Dev
    • Basics - Get detected!
    • Not so easy to stage!
    • Base64 Encode Shellcode
    • Caesar Cipher (ROT 13) Encrypt Shellcode
    • XOR Encrypt Shellcode
    • AES Encrypt Shellcode
  • Handy
    • Reverse Shells
    • Pivoting
    • File Transfers
    • Tmux
  • Wifi Pentesting
    • Monitoring
    • Cracking
  • Buffer Overflows
  • Cloud Security
    • AWS
    • GCP
    • Azure
  • Container Security
  • Todo
Powered by GitBook
On this page
  • Example 1 (Java)
  • Example 2 (Java)
  • Example 3 (Python)
  1. DevSecOps
  2. Secure Coding
  3. Code Review Examples

SSRF

Example 1 (Java)

Vulnerable Code:

import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class SSRFVulnerable {
    public static String fetchUrl(String urlString) throws Exception {
        URL url = new URL(urlString);
        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
        StringBuilder content = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            content.append(line);
        }
        reader.close();
        return content.toString();
    }
}

Reason for Vulnerability:

This code allows an attacker to specify any URL, potentially accessing internal resources or making requests to unintended destinations.

Fixed Code:

javaCopyimport java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;

public class SSRFFixed {
    private static final String[] ALLOWED_HOSTS = {"api.example.com", "data.example.com"};

    public static String fetchUrl(String urlString) throws Exception {
        URL url = new URL(urlString);
        if (!isAllowedHost(url.getHost())) {
            throw new SecurityException("Access to the specified host is not allowed");
        }
        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
        StringBuilder content = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            content.append(line);
        }
        reader.close();
        return content.toString();
    }

    private static boolean isAllowedHost(String host) throws Exception {
        InetAddress address = InetAddress.getByName(host);
        if (address.isLoopbackAddress() || address.isAnyLocalAddress()) {
            return false;
        }
        for (String allowedHost : ALLOWED_HOSTS) {
            if (host.equalsIgnoreCase(allowedHost)) {
                return true;
            }
        }
        return false;
    }
}

Reason for Fix:

The fixed code implements a whitelist of allowed hosts and checks if the provided URL's host is in this list. It also prevents access to loopback and local addresses, mitigating the risk of SSRF attacks.

Example 2 (Java)

Vulnerable Code:

javaCopyimport org.springframework.web.client.RestTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
public class ImageFetcher {
    @GetMapping("/fetch-image")
    public String fetchImage(@RequestParam String imageUrl) {
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(imageUrl, String.class);
    }
}

Reason for Vulnerability:

This endpoint allows an attacker to specify any URL, potentially accessing internal resources or making requests to unintended destinations.

Fixed Code:

javaCopyimport org.springframework.web.client.RestTemplate;
import org.springframework.web.bind.annotation.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.regex.Pattern;

@RestController
public class ImageFetcher {
    private static final Pattern URL_PATTERN = Pattern.compile("^https?://[\\w.-]+(:\\d+)?(/[\\w./\\-?=&%]*)?$");
    private static final String ALLOWED_DOMAIN = "images.example.com";

    @GetMapping("/fetch-image")
    public String fetchImage(@RequestParam String imageUrl) throws MalformedURLException {
        if (!isValidAndAllowedUrl(imageUrl)) {
            throw new SecurityException("Invalid or disallowed URL");
        }
        RestTemplate restTemplate = new RestTemplate();
        return restTemplate.getForObject(imageUrl, String.class);
    }

    private boolean isValidAndAllowedUrl(String urlString) throws MalformedURLException {
        if (!URL_PATTERN.matcher(urlString).matches()) {
            return false;
        }
        URL url = new URL(urlString);
        return url.getHost().equalsIgnoreCase(ALLOWED_DOMAIN);
    }
}

Reason for Fix:

The fixed code implements URL validation using a regex pattern and restricts requests to a specific allowed domain. This prevents attackers from accessing internal resources or making requests to unintended destinations.

Example 3 (Python)

Vulnerable Code:

pythonCopyimport requests
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/proxy')
def proxy():
    url = request.args.get('url')
    try:
        response = requests.get(url)
        return jsonify({
            'status': response.status_code,
            'content': response.text
        })
    except requests.RequestException as e:
        return jsonify({'error': str(e)}), 400

if __name__ == '__main__':
    app.run(debug=True)

Reason for Vulnerability:

This Flask application creates a proxy endpoint that makes requests to any URL provided as a query parameter, allowing potential SSRF attacks.

Fixed Code:

pythonCopyimport requests
from flask import Flask, request, jsonify
from urllib.parse import urlparse
import ipaddress

app = Flask(__name__)

ALLOWED_DOMAINS = ['api.example.com', 'data.example.com']

def is_valid_public_ip(ip_str):
    try:
        ip = ipaddress.ip_address(ip_str)
        return not (ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_multicast)
    except ValueError:
        return False

def is_allowed_url(url):
    parsed_url = urlparse(url)
    if not parsed_url.scheme in ['http', 'https']:
        return False
    if parsed_url.hostname in ALLOWED_DOMAINS:
        return True
    try:
        ip = ipaddress.ip_address(parsed_url.hostname)
        return is_valid_public_ip(ip)
    except ValueError:
        return False

@app.route('/proxy')
def proxy():
    url = request.args.get('url')
    if not url or not is_allowed_url(url):
        return jsonify({'error': 'Invalid or disallowed URL'}), 403
    try:
        response = requests.get(url, allow_redirects=False)
        return jsonify({
            'status': response.status_code,
            'content': response.text
        })
    except requests.RequestException as e:
        return jsonify({'error': str(e)}), 400

if __name__ == '__main__':
    app.run(debug=True)

Reason for Fix:

The fixed code implements several security measures:

  1. It checks if the URL's domain is in the allowed list.

  2. It validates that the URL uses either HTTP or HTTPS protocols.

  3. If the hostname is an IP address, it ensures it's a valid public IP address.

  4. It disables redirects to prevent potential bypass techniques. These measures significantly reduce the risk of SSRF attacks while still allowing the proxy functionality for legitimate use cases.


Example 1: Java

Vulnerable Code:

javaCopy codeString url = request.getParameter("url");
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Reason for vulnerability: User-controlled URL can lead to SSRF attacks.

Fixed Code:

javaCopy codeString url = request.getParameter("url");
if (!isValidUrl(url)) {
    throw new IllegalArgumentException("Invalid URL");
}
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Reason for fix: Validate the URL to prevent SSRF attacks.

Example 2: Python

Vulnerable Code:

pythonCopy codeurl = request.args.get('url')
response = requests.get(url)

Reason for vulnerability: User-controlled URL can lead to SSRF attacks.

Fixed Code:

pythonCopy codeurl = request.args.get('url')
if not is_valid_url(url):
    abort(400)
response = requests.get(url)

Reason for fix: Validate the URL to prevent SSRF attacks.

PreviousXXENextSSTI

Last updated 9 months ago