Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

there is a vulnerability of Server-Side Request Forgery #286

Closed
loveraven42 opened this issue Apr 16, 2018 · 13 comments
Closed

there is a vulnerability of Server-Side Request Forgery #286

loveraven42 opened this issue Apr 16, 2018 · 13 comments

Comments

@loveraven42
Copy link

My English isn't fluent

  • when I let this program run in my nginx web site, I find it has Server-Side Request Forgery vulnerability
  • for example , the url is
 http://192.168.8.123/abc.php?a=http://****.***.com(the other abnormal web server)

and I can get the log from the other web server which this ip(192.168.8.123)visit it.

I know you have do something that prevent it, though I can see Internal Server Error from this request http://192.168.8.123/abc.php?a=http://***.**.com(a normal webserver)
Maybe the other hackers could use it to attack the other website as a proxy
My English really is not fluent
I hope you can understand my means, thanks, bro.

@glaslos
Copy link
Member

glaslos commented Apr 16, 2018

You made a correct observation of an intended behavior.

@loveraven42
Copy link
Author

Maybe we can remove this function? shall we?

@glaslos
Copy link
Member

glaslos commented Apr 16, 2018

This function is intentionally, we want this behavior.

@loveraven42
Copy link
Author

well, bro. But I change the handlers/emulators/rfi.py, and let the function of download_file disable, though I still think this function is vulnerable, thanks

@glaslos
Copy link
Member

glaslos commented Apr 17, 2018

Do you have any other ideas on how to avoid the abuse without completely removing support for RFI?

@loveraven42
Copy link
Author

well, we could filter the url , this is the demo, I hope it can help you
you can just use the function of safe_request_url

import socket
import re
import requests
from urlparse import urlparse
from socket import inet_aton
from struct import unpack
from requests.utils import requote_uri

def check_ssrf(url):
    hostname = urlparse(url).hostname

    def ip2long(ip_addr):
        return unpack("!L", inet_aton(ip_addr))[0]

    def is_inner_ipaddress(ip):
        ip = ip2long(ip)
        return ip2long('127.0.0.0') >> 24 == ip >> 24 or \
                ip2long('10.0.0.0') >> 24 == ip >> 24 or \
                ip2long('172.16.0.0') >> 20 == ip >> 20 or \
                ip2long('192.168.0.0') >> 16 == ip >> 16

    try:
    	# print re.match(r"^http(s)?://(.*?)$", url)
        # if not re.match(r"^https?://.*/.*$", url):
        if not re.match(r"^http(s)?://(.*?)$", url):
            raise BaseException("url format error")
        # print socket.getaddrinfo(hostname, 'http')
        ip_address = socket.getaddrinfo(hostname, 'http')[0][4][0]
        if is_inner_ipaddress(ip_address):
            raise BaseException("inner ip address attack")
        return True, "success"
    except BaseException as e:
        return False, str(e)
    except:
        return False, "unknow error"

def safe_request_url(url, **kwargs):
    def _request_check_location(r, *args, **kwargs):
        if not r.is_redirect:
            return
        url = r.headers['location']

        # The scheme should be lower case...
        parsed = urlparse(url)
        url = parsed.geturl()

        # Facilitate relative 'location' headers, as allowed by RFC 7231.
        # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
        # Compliant with RFC3986, we percent encode the url.
        if not parsed.netloc:
            url = urljoin(r.url, requote_uri(url))
        else:
            url = requote_uri(url)

        succ, errstr = check_ssrf(url)
        if not succ:
            raise requests.exceptions.InvalidURL("SSRF Attack: %s" % (errstr, ))

    success, errstr = check_ssrf(url)
    if not success:
        raise requests.exceptions.InvalidURL("SSRF Attack: %s" % (errstr,))

    all_hooks = kwargs.get('hooks', dict())
    if 'response' in all_hooks:
        if hasattr(all_hooks['response'], '__call__'):
            r_hooks = [all_hooks['response']]
        else:
            r_hooks = all_hooks['response']

        r_hooks.append(_request_check_location)
    else:
        r_hooks = [_request_check_location]

    all_hooks['response'] = r_hooks
    kwargs['hooks'] = all_hooks
    return requests.get(url, **kwargs)

print safe_request_url("http://10.10.10.10")

@loveraven42
Copy link
Author

Can I apply for a cve? I want to try it. :)

@glaslos
Copy link
Member

glaslos commented Apr 18, 2018

Why a CVE? This is not a vulnerability in Glastopf, it is intended behavior.
Please send a pull request with your changes...

@loveraven42
Copy link
Author

em... so embarrassed, ok, I will send a pull request. But this pull request just filter the url in some ips, and others still can use the web server as a proxy. does the program really need this funcion?
I know it is a intended behavior, But you don't filter the url. if some companies deploy your program in the internet, it is possible to be attacked by others. And the day before yesterday I deployed this program, the logs of nginx show that someone use my website as a proxy to attack other.

@attritionorg
Copy link

@glaslos looks like CVE-2018-10220 was assigned to this despite your comments

@xandfury
Copy link
Member

This issue has been cited as the source. More info

@creolis
Copy link
Member

creolis commented Apr 20, 2018

And the day before yesterday I deployed this program, the logs of nginx show that someone use my website as a proxy to attack other

@akamei, ... what do you think Glastopf is? To be more specific - what is your use case (what do you want to do with the software in general)?

@loveraven42
Copy link
Author

@creolis Sorry, I was too busy before I see your comments. I use your program to gather the web attack log, and I don't want it to influence my web server. This vulnerability may let others attack the inner network of my web server, so I just filter the url and don't let the others attack it. I think If you want the function of rfi, you must filter the url. I think I explain it clearly, if you have ant questions, please tell me, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants