mushorg / glastopf

Web Application Honeypot
http://glastopf.org
551 stars 172 forks source link

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

Closed loveraven42 closed 6 years ago

loveraven42 commented 6 years ago

My English isn't fluent

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 commented 6 years ago

You made a correct observation of an intended behavior.

loveraven42 commented 6 years ago

Maybe we can remove this function? shall we?

glaslos commented 6 years ago

This function is intentionally, we want this behavior.

loveraven42 commented 6 years ago

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 commented 6 years ago

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

loveraven42 commented 6 years ago

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 commented 6 years ago

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

glaslos commented 6 years ago

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

loveraven42 commented 6 years ago

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 commented 6 years ago

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

xandfury commented 6 years ago

This issue has been cited as the source. More info

creolis commented 6 years ago

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 commented 6 years ago

@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.