It is possible to trigger a POST-Request to any address via Horizon

Bug #1980349 reported by Sven Anders
258
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Dashboard (Horizon)
New
Undecided
Unassigned
OpenStack Security Advisory
Incomplete
Undecided
Unassigned

Bug Description

# Description of the bug

We use horizon in the following version: `git+https://opendev.org/openstack/horizon@9d1bb3626bc1dbcf29a55aeb094f4350067317cd#egg=horizon`

In Horizon there is the following code in Xena:
openstack_auth/views.py

```
def websso(request):
    """Logs a user in using a token from Keystone's POST."""
    referer = request.META.get('HTTP_REFERER', settings.OPENSTACK_KEYSTONE_URL)
    auth_url = utils.clean_up_auth_url(referer)
    token = request.POST.get('token')
    try:
        request.user = auth.authenticate(request, auth_url=auth_url,
                                         token=token)
   ...
```

This call is usually called during SAML-Auth, but you can call it on the command line like this:

``
curl -v 'http://horizon-name:8080/auth/websso/' -X POST -H 'Referer: https://referer:5001/' -H 'Content-Type: application/x-www-form-urlencoded' --data-raw 'token=mytoken'
``

So an attacker can control the content of the HTTP_REFERER and then an auth POST request will be sent to this address.

I have changed the referer to a web server https://webserver/su-huhu/ and you can find inside the logfile:

```
access.log: <ip-address-of-horizon> - - [28/Jun/2022:08:15:06 +0200] "POST /su-huhu/v3/auth/tokens HTTP/1.1" 404 6529 "-" "openstack_auth keystoneauth1/4.5.0 python-requests/2.27.1 CPython/3.8.10"
```

# Impact

* An attacker can hide his ip and do a brute force attack to any other ip via all public available horizon dashboards.
* An attacker can setup a machine, set the referer to this machine and then send some ugly results (e.g. very long, never ending, wrong json code, ssl protocol issues) to the horizon service.
* An attacker can analyze which services are available on the horizon host (if it is behind a firewall, use DNS Servers with private zones). Note that you are able to change the port number to any number. I have not tested, but perhaps it is also possible to change the protocol to another value, let's say: imap://user:passwort@ip/.

# Is this only relevant for xena

The code has changed on master branch, but the bug is still there:
```
# TODO(stephenfin): Migrate to CBV
@sensitive_post_parameters()
@csrf_exempt
@never_cache
def websso(request):
    """Logs a user in using a token from Keystone's POST."""
    if settings.WEBSSO_USE_HTTP_REFERER:
        referer = request.META.get('HTTP_REFERER',
                                   settings.OPENSTACK_KEYSTONE_URL)
        auth_url = utils.clean_up_auth_url(referer)
    else:
        auth_url = settings.OPENSTACK_KEYSTONE_URL
    token = request.POST.get('token')
    try:
        request.user = auth.authenticate(request, auth_url=auth_url,
                                         token=token)
    except exceptions.KeystoneAuthException as exc:
        if settings.WEBSSO_DEFAULT_REDIRECT:
            res = django_http.HttpResponseRedirect(settings.LOGIN_ERROR)
        else:
            msg = 'Login failed: %s' % exc
            res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
            set_logout_reason(res, msg)
        return res
```

only changing the WEBSSO_USE_HTTP_REFERER to false (Default true) will forbid to call this.

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

Since this report concerns a possible security risk, an incomplete
security advisory task has been added while the core security
reviewers for the affected project or projects confirm the bug and
discuss the scope of any vulnerability along with potential
solutions.

description: updated
Changed in ossa:
status: New → Incomplete
Revision history for this message
Jeremy Stanley (fungi) wrote :

Just to follow up, Sven Anders (the reporter) reached out to the OpenStack vulnerability coordinators today via E-mail to inquire on the status of this report.

Horizon core security reviewers: please take a look at the details above and, at a minimum, leave a comment letting us know the following...

1. Can you confirm the reported bug is a defect in maintained stable branches of Horizon, not merely a misunderstanding nor misconfiguration?

2. If #1 is yes, can you give your opinion on whether the severity of the defect is sufficient to warrant developing and testing a fix it in private before making the details public?

3. If #1 and #2 are yes, can you indicate whether potential fixes are likely to be backportable to supported stable branches (not violating stable backport policies, e.g. due to requiring additional configuration or changing config defaults)?

Thanks in advance for your prompt attention!

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

We're well past the scheduled expiration for this embargo, so I'm switching the report to public. Hopefully with more eyes on it we can come up with more answers to the questions posed above.

description: updated
information type: Private Security → Public Security
Revision history for this message
Nick Tait (nickthetait) wrote :

Sven, in your associated post [1] you mention "there is now CVE". But I don't find any reference (here or on the blog) of what the CVE identifier is. Could you confirm if there has been one reserved yet?

[1] https://packetstormsecurity.com/files/169464/openstack-missingvalidation.txt

Revision history for this message
Sven Anders (tabacha) wrote :

Sorry it was a typo, there is no CVE. I have no idea how to get one.

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

If there's consensus from the Horizon maintainers on a fix which is safely backportable to stable branches, and that the risk of exploitation for this defect is sufficiently severe to warrant broad distribution of a security advisory, then I can file a request with MITRE to have a CVE assigned for inclusion in that advisory.

Revision history for this message
Mohammed Naser (mnaser) wrote :

Sven, what do you recommend as a fix in this scenario?

Revision history for this message
Sven Anders (tabacha) wrote :

Hi Mohammed,
I am unsure, I am not a OpenStack Developer. I am only reporting an issue. I do not know how Keystone and SAML works in detail.

But I would suggest that the incomming call is only acceepted when it comes from an Ip Range which the Admin has configured form SAML / OpenID Auth.

I think every Company who wants to make federation, is knowing the servers which will federate.

Revision history for this message
Brian Rosmaita (brian-rosmaita) wrote :

Just want to note that the WEBSSO_USE_HTTP_REFERER option was introduced by change I9c5c8d59c5f5a8570dbb5 and is present in all stable branches. Unfortunately, its default value is True. Plus, it only works for a single Keystone URL. But it's there.

Since the source of the exploit seems to be this:

curl -v 'http://horizon-name:8080/auth/websso/' -X POST -H 'Referer: https://referer:5001/' -H 'Content-Type: application/x-www-form-urlencoded' --data-raw 'token=mytoken'

I agree with Swen's suggestion that the quickest way to fix this would be to configure the webserver hosting horizon to only accept requests to /auth/sso from known IP ranges from which the external federated horizons will be making requests. Whether this will be effective depends on how tightly the IPs are controlled in the federated clouds ... if it's the entire IP range of Cloud X, then it's only going to be of limited use.

Another option would be a Horizon change to add an allowlist of keystone URLs, and then the horizon sso code will only use a HTTP_REFERER value that's in the list. I'm not sure where this would fit in the priorities of horizon developers, though.

To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

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