Authenticated SSRF vulnerability in the heat dashboard (horizon dashboard)

Bug #1765402 reported by b
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
heat-dashboard
New
Undecided
Unassigned

Bug Description

Hello,
I found a SSRF vulnerability in the "Stack Preview" functionality. This functionality can be reached like this :

- on the left hand size menu (of the horizon dashboard) click

      "Orchestration"

- then from the submenu select

          "Stacks"

- then on the right of the screen the button

               "Preview Stack"

  is present.

- then in the

    "Template Source"

- it is possible to select "URL" and choose an arbitrary address including internal IP addresses. The result can be retrieved from "alert-danger" div tag class on the server response.

This makes it possible to perform GET request on arbitrary ports and IP (external or internal). The code that is being executed during the URL request is located here :

    heat/common/urlfetch.py

def get(url, allowed_schemes=('http', 'https')):
    """Get the data at the specified URL.

    The URL must use the http: or https: schemes.
    The file: scheme is also supported if you override
    the allowed_schemes argument.
    Raise an IOError if getting the data fails.
    """
    LOG.info('Fetching data from %s', url)

    components = urllib.parse.urlparse(url)

    if components.scheme not in allowed_schemes:
        raise URLFetchError(_('Invalid URL scheme %s') % components.scheme)

    if components.scheme == 'file':
        try:
            return urllib.request.urlopen(url).read()
        except urllib.error.URLError as uex:
            raise URLFetchError(_('Failed to retrieve template: %s') % uex)

available on the https://github.com/openstack/heat as seen in the recent commit commit "7271252add45e600e9af2e68fe4700151367fec7" (date : April 12 13:28:57 2018).

Possible results include :

    http://127.0.0.1:8080 <urlopen error [Errno 113] No route to host>
    http://127.0.0.1:8080 <urlopen error [Errno 111] Connection refused>
    http://127.0.0.1:22 <urlopen error [Errno 111] Connection refused>
    http://127.0.0.1:80 <urlopen error [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)>

Which gives the attacker a good idea of which ports are open and what IP addresses are reachable.

In the attachement you can find a simple exploitation script.

Best regards,

Revision history for this message
b (blogresponder) wrote :
Revision history for this message
Jeremy Stanley (fungi) wrote :

While reports of suspected vulnerabilities for heat-dashboard are not normally coordinated by the OpenStack VMT, the reporter reached out to and subscribed us requesting some assistance as this has been sitting untriaged for over a month. I have in turn subscribed the Heat team's core security reviewers since I'm unsure who has initial visibility into private security bugs for heat-dashboard.

Given the probable low risk/impact from the described issue I'm inclined to recommend continuing discussion in public, but it's up to the Heat team and reporter to decide that.

Revision history for this message
Zane Bitter (zaneb) wrote :

Both heat and heat-dashboard have moved their bugs to storyboard.openstack.org (possibly since this issue was opened, otherwise I don't see how you managed to create a new bug report on Launchpad).

IIUC this is not an issue with heat-dashboard, but with Heat itself (as you point out it's the code in heat/common/urlfetch.py that is doing the fetching, meaning it's called from heat-api). Arguably being able to access it through the dashboard makes it easier to exploit, but having to interact directly with the API is not really an obstacle to anybody malicious.

In any event, this vulnerability has been known practically since the feature of fetching a template from a URL was implemented. I don't see any point continuing to keep the bug private. We'd like to get rid of the feature altogether, and have discussed it many, many times, but it would involve breaking backwards compatibility. For example, here's a discussion from 2013:

http://lists.openstack.org/pipermail/openstack-dev/2013-December/021318.html

Heat bugs have moved to storyboard.openstack.org from Launchpad, so I'm not going to reassign the project. I guess if we do end up closing this loophole in Heat then we'll want to make sure the dashboard doesn't reimplement the same thing. (Probably we'll want to make use of the new feature to allow retrieving templates from Swift when that lands - see bug 1755453.) That might be worth creating a story or task in Launchpad for.

Jeremy Stanley (fungi)
information type: Private Security → Public
Revision history for this message
Jeremy Stanley (fungi) wrote :

Thanks, Zane. Since this sounds like a known issue and you suggested switching it to public, I went ahead and did that.

As you indicated, Heat deliverables are using https://storyboard.openstack.org/#!/project_group/82 for bug tracking (as of May 6 according to my notes), but private bugs were not imported as they were not visible to the importer tool so it may make sense for Jan (or somebody) to open a story there about deprecation of URL-based template fetching with a task for the openstack/heat project.

b (blogresponder)
description: updated
description: updated
description: updated
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.