Skip to main content
Hehe total refactorring :)
Source Link

You"Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing." https://portswigger.net/web-security/ssrf

This is an example of an app which is vulnerable to SSRF:

from flask import Flask, escape, request
import requests 
app = Flask(__name__)

@app.route('/')
def hello():
    url = request.args['url']
    return request.get(url).text

It takes parameter "url" and makes a http request to user entered URL. The impact of this vulnerability depends ~. For an example if this web app had an elasticsearch installed with it an attacker could run some bad commands on it, but if an app had some fetch client which can get files from local filesystem like requests.get("file://etc/passwd") that takes us to another level of vulnerability solidy!

To understand the impact you can seek into some SSRF reports on H1 https://www.google.com/search?q=site%3Ahackerone.com+ssrf

As a developer you need to make internal network unavailable for the user entered requests. Some guys advise you to make a blacklist of hosts which you should NEVER use curldisallow make requests to send reuests anywhere without, but I pretend you from doing blacklisting. Because:

  • there are so many ways to bypass such as stupid thing as blacklist! For an example in the work there are so many WAFs but they can be bypassed by humans via some tricks! In SSRF there are also so many tricks to bypass blacklist which are listed here: https://twitter.com/search?q=ssrf I like this one http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ lol :)
  • And also this is not a good practice to solve problem via just "sealing" a security hole! If you have got a security hole you should think, and change your design!

So in my opinion the right solution for this is using proxy! Please note I'm talking about local instance of proxy, to pretend internal requests and allow only external not to pretend IP leaking (please note that this is also a problem you can fix by buying proxy list or making own proxy network based filteringwhich can not be one point of failure DDOSed via L3, L4)! You should use

There are many ways to set up your own squid proxy instance but please note that your http proxy must be accesible only by your application, not to the internet :) So close it using iptables to only your own network infrastructure using it.

So in short you need to disallow local network for your squid http proxy and sendmake your app send http requests usingthrough it! There so mny ways

 proxies = {
  'http': 'http://my_local_squid_instance:3128',
}
request.get(url, proxies=proxies, timeout=10).text

(I also recommend you using queues or coroutines while you do stuff like fetching because we do not know if external server will respond in few minutes or few minutes :) (so you should add timeout for external requests to bypass blacklisting filteringalso pretend DOS))

P.S I was also making a pet project which had user's URL fetching functionality and I wanted to understand how to properly fix that stuff! Some guys wornder why I recomend Squid proxy. The answer is that I know a big real world app that uses it: VK.com uses squid proxy to fetch external data, you can ensure in it by using https://webhook.site, you will see the User-Agent is squid proxy :)

You should NEVER use curl to send reuests anywhere without network based filtering! You should use squid proxy and send your requests using it! There so mny ways to bypass blacklisting filtering!

"Server-side request forgery (also known as SSRF) is a web security vulnerability that allows an attacker to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker's choosing." https://portswigger.net/web-security/ssrf

This is an example of an app which is vulnerable to SSRF:

from flask import Flask, escape, request
import requests 
app = Flask(__name__)

@app.route('/')
def hello():
    url = request.args['url']
    return request.get(url).text

It takes parameter "url" and makes a http request to user entered URL. The impact of this vulnerability depends ~. For an example if this web app had an elasticsearch installed with it an attacker could run some bad commands on it, but if an app had some fetch client which can get files from local filesystem like requests.get("file://etc/passwd") that takes us to another level of vulnerability solidy!

To understand the impact you can seek into some SSRF reports on H1 https://www.google.com/search?q=site%3Ahackerone.com+ssrf

As a developer you need to make internal network unavailable for the user entered requests. Some guys advise you to make a blacklist of hosts which you should disallow make requests to, but I pretend you from doing blacklisting. Because:

  • there are so many ways to bypass such as stupid thing as blacklist! For an example in the work there are so many WAFs but they can be bypassed by humans via some tricks! In SSRF there are also so many tricks to bypass blacklist which are listed here: https://twitter.com/search?q=ssrf I like this one http://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ lol :)
  • And also this is not a good practice to solve problem via just "sealing" a security hole! If you have got a security hole you should think, and change your design!

So in my opinion the right solution for this is using proxy! Please note I'm talking about local instance of proxy, to pretend internal requests and allow only external not to pretend IP leaking (please note that this is also a problem you can fix by buying proxy list or making own proxy network which can not be one point of failure DDOSed via L3, L4)!

There are many ways to set up your own squid proxy instance but please note that your http proxy must be accesible only by your application, not to the internet :) So close it using iptables to only your own network infrastructure using it.

So in short you need to disallow local network for your squid http proxy and make your app send http requests through it!

 proxies = {
  'http': 'http://my_local_squid_instance:3128',
}
request.get(url, proxies=proxies, timeout=10).text

(I also recommend you using queues or coroutines while you do stuff like fetching because we do not know if external server will respond in few minutes or few minutes :) (so you should add timeout for external requests to also pretend DOS))

P.S I was also making a pet project which had user's URL fetching functionality and I wanted to understand how to properly fix that stuff! Some guys wornder why I recomend Squid proxy. The answer is that I know a big real world app that uses it: VK.com uses squid proxy to fetch external data, you can ensure in it by using https://webhook.site, you will see the User-Agent is squid proxy :)

Source Link

You should NEVER use curl to send reuests anywhere without network based filtering! You should use squid proxy and send your requests using it! There so mny ways to bypass blacklisting filtering!