# Server-Side Request Forgery

A **server-side request forgery** (SSRF) attack is when an attacker crafts a malicious HTTP request that triggers a further request from your server to a domain of their choosing. SSRF vulnerabilities can be used to probe your network or to disguise denial-of-service attacks against third parties.

## Common Causes of SSRF

There are many reasons your web-server might make outgoing HTTP requests, including:

* Calling a third-party API in response to a user action.
* Communicating with a *Single Sign-On* (SSO) provider.
* Implementing an image upload functions that accept URLs instead of files.
* Checking validation URLs – for example, hosted schema files referenced in XML documents.
* Accessing open-graph meta-data used in generating link previews.

In some of these scenarios, the domain of the URL will be taken from the HTTP request. This allows an attacker to trigger HTTP requests to arbitrary domains. Malicious users will try to use this in denial-of-service attacks against other targets (for which you will get blamed), and to probe internal IP addresses on your network that are not intended to be public.

## Mitigation

The easiest way to mitigate SSRF vulnerabilities is to never make outgoing HTTP requests to domain names drawn from an incoming HTTP request. If you call the Google Maps API from your web-server, for instance, the domain of the API should be defined in server-side code, rather than pulled from the client. An easy way to do this is to use the Google Maps SDK:

import googlemaps
from datetime import datetimegmaps = googlemaps.Client(key=GOOGLE_MAPS_API_KEY)

directions = gmaps.directions(“Sydney Town Hall”,
“Parramatta, NSW”,
mode = “transit”,
departure_time = datetime.now())

## Validation URLs

XML documents often reference schema files hosted on remote URLs. Generally speaking, however, you should know how to validate an uploaded XML file ahead of time. If you perform validation of XML documents on your server, make sure it is against a schema file stored locally, rather than drawn from an uploaded XML file that could be controlled by an attacker:

from lxml import etreedef is_validate(xml_file, xsd_file):
“””Validate an XML file at the supplied path against an XSD schema file,
disabling external network access.”””
parser = etree.XMLParser(resolve_entities=False, no_network=True)
xml = etree.parse(xml_file, parser)
xsd = etree.parse(xsd_file, parser)
schema = etree.XMLSchema(xsd.getroot())

return schema.validate(xml)

## Making Outbound HTTP Requests to Arbitrary URLs

Some websites do need to make requests to arbitrary third-party URLs. Social media sites, for example, allow sharing of web links, and will often pull down the open graph meta-data from those URLs to generate link previews. In these cases, you need to protect yourself against SSRF attacks. This means you should:

* Only make outgoing HTTP requests from your server in response to actions by *authenticated* users.
* Limit the number of links a user can share in a given time-frame, to avoid abuse.
* Consider making the user pass a CAPTCHA test with each link they share.
* Keep a configurable “blocklist” of domains you will never contact.
* Talk to your networking team about limiting which internal servers are reachable from your web-servers.
* Validate that the URLs contain web domains rather than IP addresses.

Note that a competent attacker will be able to set up DNS records pointing to private IPs, so simply validating a URL contains a domain name (rather than an IP address) generally isn’t sufficient.

Below is an illustration of some of these techniques:

import re
import validatorsfrom flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from IPy import IP
from opengraph import OpenGraph
from urllib.parse import urlparse

app = Flask()

limiter = Limiter(
key_func = get_remote_address,
default_limits = [ “200 per day”, “50 per hour” ]

def share(link):
“””Return the meta-data for a web-link shared by a user, throttling
access by the remote IP address, and validating the link before
accessing it.”””

# Add a protocol if not supplied.
link = link.lower()
link = link if re.match(“^[a-z]+://.*”, link) else f”https://{link}”

# Reject invalid URLs or those containing private IP addresses.
if validators.url(link, public=True):
raise Exception(“Invalid or private URL”)

components = urlparse(link)

# Reject URLs with non-standard protocols.
if components.scheme not in (‘http’, ‘https’):
raise Exception(“Invalid protocol”)

# Reject URLs with non-standard ports.
if ‘:’ in components.netloc:
raise Exception(“Please do not specify a port”)

# Reject URLs containing IP addresses rather than domains.
raise Exception(“Please specify domains rather than IP addresses”)
except ValueError:

# Reject URLs where the domain is in our blocklist.
if components.netloc in BLOCKLIST:
raise Exception(“Please do not share links to this domain”)

# Everything looks good, go grab the meta-data.
return OpenGraph(url=link).to_json()

## CWEs

* [CWE-918](https://cwe.mitre.org/data/definitions/918.html)

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit: www.shiftleft.io.


See for yourself – run a scan on your code right now