external.Default authentication plugin only considers leftmost part of the REMOTE_USER split by "@"

Bug #1254619 reported by Alvaro Lopez
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Fix Released
High
Dolph Mathews
OpenStack Security Advisory
Invalid
Undecided
Unassigned
OpenStack Security Notes
Fix Released
Undecided
Nathan Kinder

Bug Description

Hi there.

Keystone allows the usage of external authentication. This external
authentication makes possible for the deployers to integrate external
euth methods in Keystone. When it is executed as a WSGI application
(for example when executed behind apache using mod_wsgi) the
authentication can be made by the web server and the user will be
passed down using the REMOTE_USER environment variable. It is also
possible to use external authn by creating a custom WSGI filter that
will be pipelined. More details of this behaviour can be seen in [0].

[0] http://docs.openstack.org/developer/keystone/external-auth.html

Since the Havana release, this code has been refactored and moved to a
pluggable mechanism under keystone/auth/plugins/external.py. If I am
not wrong, this was introduced in commit
88c319e6bce98082f9a90b8b27726793d5366326 [1]. This code is in
stable/havana since that commit, and is currently in the trunk.

[1] https://github.com/openstack/keystone/commit/88c319e6bce98082f9a90b8b27726793d5366326

During the review of [2] the ExternalDefault plugin I've realized that
the way the plugin extracts the username can lead to impersonation.
The excerpt of code that extracts the username is this one [3]:

    names = remote_user.split('@')
    username = names.pop(0)
    domain_id = CONF.identity.default_domain_id
    user_ref = auth_info.identity_api.get_user_by_name(username,
                                                       domain_id)

When Keystone is configured to use the defualt domain, the REMOTE_USER
variable is splited by all the "@" and then only the leftfmost part is
considered, while the leftovers are discarded. Since a username can
contain "@" inside (for example when emails are used as usernames)
"john" "<email address hidden>" and "<email address hidden>" will all get a token
belonging to the "john" user.

[2] https://review.openstack.org/#/c/50362
[3] https://github.com/openstack/keystone/blob/stable/havana/keystone/auth/plugins/external.py#L39

External authentication opens the door for any deployer to use any
authentication mechanism. OpenStack does not ship any external
authentication mechanism, but it is perfectly possible to use emails
as the usernames (or usernames containing "@", as X509 certificate
DNs). For example, a LDAP directory could be configured in Apache to
let the users in, and set the REMOTE_USER as the username, instead of
the user DN.

It is possible to easily reproduce this using devstack as follows:

    ubuntu@test-ks-vuln:~/devstack$ cat > localrc << EOF
    > ENABLED_SERVICES=key,mysql
    > APACHE_ENABLED_SERVICES+=keystone
    > EOF
    ubuntu@test-ks-vuln:~/devstack$ ./stack.sh
    (...)
    ubuntu@test-ks-vuln:~/devstack$ source openrc admin admin
    ubuntu@test-ks-vuln:~/devstack$ keystone user-list
    +----------------------------------+-------+---------+-------------------+
    | id | name | enabled | email |
    +----------------------------------+-------+---------+-------------------+
    | dc90b499a1c0499997bd35ba19a2436c | admin | True | <email address hidden> |
    | 685cd73e645243c2ba81314cbc5ac89a | demo | True | <email address hidden> |
    +----------------------------------+-------+---------+-------------------+
    ubuntu@test-ks-vuln:~/devstack$ keystone tenant-list
    +----------------------------------+--------------------+---------+
    | id | name | enabled |
    +----------------------------------+--------------------+---------+
    | d5319bc5b7054e0589ad32048813ee1a | admin | True |
    | badfa689e32a4d9fb7d102a7d92ad3b7 | demo | True |
    | 110627ae8c534b548d70a5a159ff65ee | invisible_to_admin | True |
    | 92484643deb246e680ee3d716a7dfeea | service | True |
    +----------------------------------+--------------------+---------+
    ubuntu@test-ks-vuln:~/devstack$ keystone tenant-create --name external_users
    +-------------+----------------------------------+
    | Property | Value |
    +-------------+----------------------------------+
    | description | |
    Listen 5000
    | enabled | True |
    Listen 5000
    | id | 3ac4e3f06a3548378eb26e3be8dc3952 |
    | name | external_users |
    +-------------+----------------------------------+
    ubuntu@test-ks-vuln:~/devstack$ keystone user-create --name john --tenant d5319bc5b7054e0589ad32048813ee1a --pass secret
    +----------+----------------------------------+
    | Property | Value |
    +----------+----------------------------------+
    | email | |
    Listen 5000
    | enabled | True |
    | id | a8fe063e8a124f89ada9526d401aad98 |
    | name | john |
    | tenantId | d5319bc5b7054e0589ad32048813ee1a |
    +----------+----------------------------------+
    ubuntu@test-ks-vuln:~/devstack$ keystone user-create --name john@external_user.com --tenant 3ac4e3f06a3548378eb26e3be8dc3952 --pass secret
    +----------+----------------------------------+
    | Property | Value |
    +----------+----------------------------------+
    | email | |
    | enabled | True |
    | id | 6af78b4bdca646a68069d74cdf8e5334 |
    | name | john@external_user.com |
    | tenantId | 3ac4e3f06a3548378eb26e3be8dc3952 |
    +----------+----------------------------------+

So far I've two different users. For the shake of simplicity I will
use Apache's basic authentication, so it is needed to add the
following excerpt to /etc/apache2/sites-enabled/keystone:

    Listen 5001
    <VirtualHost *:5001>
        WSGIDaemonProcess keystone-public2 processes=5 threads=1 user=ubuntu
        WSGIProcessGroup keystone-public2
        WSGIScriptAlias / /var/www/keystone/main
        WSGIApplicationGroup %{GLOBAL}
        ErrorLog /var/log/apache2/keystone
        LogLevel debug
        CustomLog /var/log/apache2/access.log combined
        <Location />
            AuthType Basic
            AuthName "Restricted Files"
            AuthBasicProvider file
            AuthUserFile /opt/stack/htpasswd
            Require valid-user
        </Location>
    </VirtualHost>

And then, create the external user, and authenticate with it:

    ubuntu@test-ks-vuln:~/devstack$ sudo htpasswd -c /opt/stack/htpasswd john@external_user.com
    New password:
    Re-type new password:
    Adding password for user john@external_user.com
    ubuntu@test-ks-vuln:~/devstack$ sudo /etc/init.d/apache2 restart
    * Restarting web server apache2
    * ... waiting
    ubuntu@test-ks-vuln:~/devstack$
    ubuntu@test-ks-vuln:~$ curl --user john@external_user.com:secret -d '{"auth": {"identity":{ "methods": []}}}' -H "Content-type: application/json" http://172.16.0.63:5001/v3/auth/tokens |python -mjson.tool
      % Total % Received % Xferd Average Speed Time Time Time Current
                                     Dload Upload Total Spent Left Speed
    100 1134 100 1095 100 39 2301 81 --:--:-- --:--:-- --:--:-- 2300
    {
        "token": {
            "catalog": [
                {
                    "endpoints": [
                        {
                            "id": "d0b2b692496a4d2c8a70e63543782aed",
                            "interface": "internal",
                            "legacy_endpoint_id": "59eddafa29194ef5a1d221aad17f2f2e",
                            "region": "RegionOne",
                            "url": "http://172.16.0.63:5000/v2.0"
                        },
                        {
                            "id": "da7fe597a1b84529910e890807b47bdb",
                            "interface": "admin",
                            "legacy_endpoint_id": "59eddafa29194ef5a1d221aad17f2f2e",
                            "region": "RegionOne",
                            "url": "http://172.16.0.63:35357/v2.0"
                        },
                        {
                            "id": "eeda9fbcffe94588ad15689d33f2c1e9",
                            "interface": "public",
                            "legacy_endpoint_id": "59eddafa29194ef5a1d221aad17f2f2e",
                            "region": "RegionOne",
                            "url": "http://172.16.0.63:5000/v2.0"
                        }
                    ],
                    "id": "14a4bd4966b74503ab2fb47836101824",
                    "type": "identity"
                }
            ],
            "expires_at": "2013-11-26T23:04:55.341085Z",
            "extras": {},
            "issued_at": "2013-11-25T23:04:55.341121Z",
            "methods": [],
            "project": {
                "domain": {
                    "id": "default",
                    "name": "Default"
                },
                "id": "d5319bc5b7054e0589ad32048813ee1a",
                "name": "admin"
            },
            "roles": [
                {
                    "id": "9fe2ff9ee4384b1894a90878d3e92bab",
                    "name": "_member_"
                }
            ],
            "user": {
                "domain": {
                    "id": "default",
                    "name": "Default"
                },
                "id": "a8fe063e8a124f89ada9526d401aad98",
                "name": "john"
            }
        }
    }

As you can see, I am getting the id for the user "john"
(a8fe063e8a124f89ada9526d401aad98) instead of the user
"john@example_user.com" (6af78b4bdca646a68069d74cdf8e5334). The patch
in [2] should fix this issue (although it was initially unrelated)
since it does not split the username when using the ExternalDefault
plugin.

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

Trying to determine whether this merits an advisory... can you expand on your scenario above? When you suggest "an external
plugin that uses the email as the username" is this common/recommended practice? Also, what releases contain code vulnerable to this?

Changed in ossa:
status: New → Incomplete
Revision history for this message
Alvaro Lopez (aloga) wrote :

Hi Jeremy.

I will update the description of the patch with more information right now.

Revision history for this message
Alvaro Lopez (aloga) wrote :

Updated. If you need further information, please do not hesitate to ask.

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

It sounds like this is probably a surprising enough result that fixing it merits a security advisory, and potentially exploitable so should remain embargoed until then (the security impact of https://review.openstack.org/50362 seems sufficiently opaque such that I don't think it gives away this issue). Does anyone disagree?

Revision history for this message
Grant Murphy (gmurphy) wrote :

@fungi -

Will the fact that a core contributor -1'd this patch for compatibility issues make this difficult to get through without publicly disclosing the reasons why the fix is needed?

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

It's entirely possible that a more targeted security fix could be
needed to address this, independent of (or in place of)
https://review.openstack.org/50362 but hopefully Dolph and other
Keystone developers will be able to make that determination.

Revision history for this message
Thierry Carrez (ttx) wrote :

Not totally convinced about this one. If I understand correctly, this is about username mapping -- if Keystone is configured to rely on REMOTE_USER to give it usernames, it will consider REMOTE_USERs john and john@* to all point to the same Keystone user "john".

If properly documented, that could be seen as a feature. If not, that could be seen as a bug (you have no way to access Keystone user john@* in a REMOTE_USER-enabled setup). If it's a bug, it has some potential security impact that we should document, but I could go with OSSN + fix in next, especially if the fix ends up breaking existing setups actually *relying* on the mapping.

Revision history for this message
Alvaro Lopez (aloga) wrote :

@ttx -

Hi Tierry. Thanks for your comments, but I have to disagree with you.

First of all, the only documented behavior is for the V2 API [1], where the
REMOTE_USER variable contains the username of the authenticated user. A site
administrator with a working configuration for the V2 would assume for sure
that this is the behavior for the V3 as well, but this is not true. If
somebody has configured an external authentication mechanism that relies in
the user emails as the usernames in V2, and has moved this to V3 he will be
affected by this.

[1] http://docs.openstack.org/developer/keystone/external-auth.html#using-httpd-authentication

Secondly, this behavior goes against the semantics of the REMOTE_USER env
variable in WSGI: "REMOTE_USER: This should be the string username of the
user, nothing more." [2]. A site admin reading the documentation [1] and with
the semantics of the REMOTE_USER in mind would configure its installation so
that the usernames are passed down in the REMOTE_USER env variable, and those
userames are then created in Keystone. This way, "<email address hidden>",
"<email address hidden>" and "john" are three different users. The two former will
be authenticated externally, and the later locally, but this is not the case.

[2] http://wsgi.readthedocs.org/en/latest/specifications/simple_authentication.html#specification

In third place, this renders unusable the external authentication for
usernames containing an "@". For example, X.509 certificates can contain the
email address of the user (or even of the CA) in the subject. Therefore this
certificate DN:

    /DC=org/DC=example/O=whatever/CN=alvaro <email address hidden>

Will break into:

    /DC=org/DC=example/O=whatever/CN=alvaro alvaro

I agree that the second and third aspects are only a bug, but from my
perspective of a resource provider that has been using external authentication
since V2, the first one has a clear security impact.

> If it's a bug, it has some potential security impact that we should document,
> but I could go with OSSN + fix in next, especially if the fix ends up breaking
> existing setups actually *relying* on the mapping.

The external authentication behavior for the V3 has been already broken
between the releases. The support shipped with Grizzly behaves completely
different than the Havana one (therefore the compatibility was broken between
releases). If somebody is using an "@" inside their REMOTE_USERs, it is already
broken (it's not only emails, but LDAP dns, X509 subject names, etc).

Revision history for this message
Alvaro Lopez (aloga) wrote :

BTW, should I add the Closes-Bug in the commit message of the patchset that fixes this?

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

For embargoed security vulnerabilities, a vulnerability management team member will end up submitting the patches to fix it in all affected branches at the time we release an accompanying advisory. When we do that, we generally set the Closes-Bug header in each commit message accordingly.

But that's jumping ahead a bit... first we need Keystone security reviewers to confirm the reported vulnerability and look at any proposed patches to address it (which should only be distributed by attaching them to this bug, if they agree that it should remain embargoed).

Dolph Mathews (dolph)
summary: - ExternalDefault authentication plugin only considers leftmost part of
+ external.Default authentication plugin only considers leftmost part of
the REMOTE_USER splited by "@"
summary: external.Default authentication plugin only considers leftmost part of
- the REMOTE_USER splited by "@"
+ the REMOTE_USER split by "@"
Revision history for this message
Dolph Mathews (dolph) wrote :

Splitting REMOTE_USER by '@' and discarding anything strikes me as a non-existent use case to begin with (this just looks broken). If there is no use case for this behavior, this bug is effectively embargoed from a non-existent set of users. I'm working to corroborate or contradict this suspicion if possible.

Revision history for this message
Thierry Carrez (ttx) wrote :

Yeah, I'm still not convinced this is actually exploitable, even by accident. It looks like the buggy user mapping would always end up in accidental access denying rather than accidental access allowance...

Alvaro: could you describe a scenario where this bug can be exploited for profit by an attacker ?

Revision history for this message
Alvaro Lopez (aloga) wrote :

@ttx:

The buggy mapping will finish in an access denial if there is no other user with that username in the local backend. If by chance you have in your local backend a user "john" and an external user "<email address hidden>" (as shown above) this is exploitable (this is a corner case, but it is still possible).

In V2 you could have "john", "<email address hidden>" (authenticated externally), "<email address hidden> "(also externally) and so on, and all of them were different users. If you were using this in V2 and you switch to using V3, the two later John's would get the former's credentials.

The security impact is low (too many variables are involved), but it exists (maybe a OSSN is enough, but I let it to the experts).

On the other hand (this is regarding the bug), the REMOTE_USER should not be splited at all and it should be considered as the username for the user that authenticated upstream, without further modifications (as V2 external did).

Revision history for this message
Thierry Carrez (ttx) wrote :

Alvaro: thx, that sounds like a valid case to me...
Dolph: do you agree we should cover this as a security vulnerability ?

Revision history for this message
Dolph Mathews (dolph) wrote :

After talking to Adam Young, I still don't see any utility in splitting REMOTE_USER and discarding half the value. We do agree that it should be fixed in master & havana to match grizzly's behavior of using the entire REMOTE_USER value as a username in the default domain.

So, I'd like to fix this bug in the open but I do think it makes sense to issue an OSSN regarding the potential risk in attempting to use Havana's broken behavior. I'd also like to piggyback the OSSN email asking for deployer feedback on the fix itself, before it merges.

Changed in keystone:
status: New → Triaged
importance: Undecided → High
Revision history for this message
Jeremy Stanley (fungi) wrote :

Alvaro: Is it okay with you if we make this public and fix it as a security hardening bug?

Revision history for this message
Alvaro Lopez (aloga) wrote :

@fungi: Yes, it is ok for me.

@Dolhp: This is what https://review.openstack.org/#/c/50362/ did in patchset 24 that was -2ed for breaking backwards compatibility.

Revision history for this message
Alvaro Lopez (aloga) wrote :

@dolph: Regarding the feedback, with my deployer hat on I find it important to get it coherent between V2 and V3: i.e. not touching REMOTE_USER at all and use it entirely as the username, regardless of using the default domain or not (as it was done for V2). There are other means of passing down the domain to Keystone (for example in another env variable).

The reasons are various: it is difficult to maintain both V2 and V3 at the same time (even if V2 is going to be deprecated); it is harder to configure when using just an http server for authentication (and not using a WSGI filter) and it is not the expected behavior when comparing against other applications (not to say that this was not the behavior with V2)

Assuming that backwards compatibility will be broken for this fix: why is it needed to append domain information to the REMOTE_USER? Why not just using an additional variable to pass down this value?

Jeremy Stanley (fungi)
Changed in ossa:
status: Incomplete → Invalid
information type: Private Security → Public
tags: added: security
Revision history for this message
Thierry Carrez (ttx) wrote :

Adding ossn team as they might want to address this in a security note...

Revision history for this message
Nathan Kinder (nkinder) wrote :

I think it makes sense to release an OSSN for this. I'll work on writing it up.

Changed in ossn:
assignee: nobody → Nathan Kinder (nkinder)
status: New → In Progress
Changed in keystone:
assignee: nobody → Alvaro Lopez (aloga)
status: Triaged → In Progress
Revision history for this message
Dolph Mathews (dolph) wrote :

(replying mostly for posterity as I think this conversation took place in other venues)

@Alvaro: agree completely. Adam Young has lifted his -2 to make exactly that happen. Regarding backwards compatibility, we should actually be restoring it vs grizzly, not breaking it in this bug fix. The bug fix itself will restore the behavior of master and stable/havana to be compatible with that of stable/grizzly... which should provide an easy migration path from stable/grizzly forward, eliminating the ops pain.

Revision history for this message
Alvaro Lopez (aloga) wrote :

So I assume that I should remove the LegacyDomain and LegacyDefaultDomain from the patchest, don't I?

Revision history for this message
Dolph Mathews (dolph) wrote :

Alvaro- refer to the code review

Changed in keystone:
assignee: Alvaro Lopez (aloga) → Adam Young (ayoung)
Changed in keystone:
assignee: Adam Young (ayoung) → Dolph Mathews (dolph)
Revision history for this message
Nathan Kinder (nkinder) wrote :
Download full text (3.5 KiB)

I've finished a draft of the OSSN for this issue. It's still unclear exactly what the fix (if any) is going to be for a Havana update, so the OSSN doesn't mention anything about potential future changes. The OSSN draft follows below.

-------------------------------------------------------------------------------------------------------------------------

Keystone can allow user impersonation when using REMOTE_USER for external authentication.
---

### Summary ###
When external authentication is used with Keystone using the "ExternalDefault" plug-in, external usernames containing "@" characters are truncated at the "@" character before being mapped to a local Keystone user. This can result in separate external users mapping to the same local Keystone user, which could lead to user impersonation.

### Affected Services / Software ###
Keystone, Havana

### Discussion ###
When Keystone is run in Apache HTTP Server, the webserver can handle authentication and pass the authenticated username to Keystone using the REMOTE_USER environment variable. External authentication behavior is handled by authentication plugins in Keystone. In the Havana release of OpenStack, if the external username provided in the REMOTE_USER environment variable contains an "@" character Keystone will only use the portion preceding the "@" character as the username when using the "ExternalDefault" authentication plugin. This results in the ability for multiple unique external usernames to map to the same single username in Keystone. For example, the external usernames "<email address hidden>" and "<email address hidden>" would both map to the Keystone user "jdoe". This behavior could potentially be abused to allow one to impersonate another similarly named external user.

Keystone in OpenStack releases prior to Havana uses the entire value contained in the REMOTE_USER environment variable, so those versions are not vulnerable to this impersonation issue.

### Recommended Actions ###
If the "ExternalDefault" plugin is being used for external authentication in the Havana release, you should ensure that external usernames do not contain "@" characters unless you want to collapse similarly named external users into a single user on the Keystone side.

If your external usernames do contain "@" characters and you do not want to collapse similarly named external users into a single user on the Keystone side, you might be able to use the "ExternalDomain" plug-in. This plugin considers the portion of the external username that follows an "@" character to be the domain that the user belongs to in Keystone. This allows similarly named external users to map to separate Keystone users if the portion of the external username that follows an "@" character maps to a Keystone domain name. To configure the "ExternalDomain" authentication plugin, set the "external" parameter in the "[auth]" section of Keystone's keystone.conf as follows:

---- begin example keystone.conf snippet ----
[auth]
methods = external,password,token,oauth1
external = keystone.auth.plugins.external.ExternalDomain
---- end example keystone.conf snippet ----

If neither of the above recommendations work for your deploy...

Read more...

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to keystone (master)

Reviewed: https://review.openstack.org/50362
Committed: https://git.openstack.org/cgit/openstack/keystone/commit/?id=1889ff207561c57587384063d61ef0b6f78457c4
Submitter: Jenkins
Branch: master

commit 1889ff207561c57587384063d61ef0b6f78457c4
Author: Alvaro Lopez Garcia <email address hidden>
Date: Tue Oct 8 11:08:42 2013 +0200

    Fix external auth (REMOTE_USER) plugin support

    According to the WSGI specification "REMOTE_USER should be the string
    username of the user, nothing more" [1], therefore no modifications
    should be made to the REMOTE_USER variable and it should be fully
    considered as the username. Otherwise the expected semantics of the
    REMOTE_USER variable change, and an site administrator could get
    undesirable side-effects.

    [1] http://wsgi.readthedocs.org/en/latest/specifications/simple_authentication.html#specification

    Moreover, it is important to have a consistent behaviour regarding
    external authentication in V2 (not domain aware), V3 with default
    domain and V3 with domain (see Bug #1253484) so that we produce similar
    results with the three methods.

    This change aims to solve this issues by removing the split of the
    REMOTE_USER variable by "@" at all:

    - In external.DefaultDomain, we cannot split REMOTE_USER by "@". This split
      will cause errors for remote users containing an "@" (not only
      emails, but also X.509 subjects, etc). The external.DefaultDomain plugin
      considers the REMOTE_USER variable as the username, and the configured
      default domain as the domain

    - In external.Domain we should not split also the REMOTE_USER by "@". A
      new environment variable (REMOTE_DOMAIN) is introduced, so that any
      external plugin can pass down the right domain for the user. The
      external.Domain plugin considers the REMOTE_USER as the username, the
      REMOTE_DOMAIN as the domain if it is present, otherwise it takes the
      configured default domain.

    - Two legacy plugins are also provided with the same behaviour as the
      Havana shipped ones. This plugins should not be used and are provided
      for compatibility reasons (see Bug #1254619)

    Closes-Bug: #1254619
    Closes-Bug: #1211233
    Closes-Bug: #1253484

    DocImpact: This change breaks backwards compatibility in favour of
    security (see bug #1254619), therefore an upgrade not is needed. It is
    needed to document the new plugins and state clearly the semantics of
    the REMOTE_USER and REMOTE_DOMAIN variable for the WSGI filters. The
    default external authentication plugin has been changed from
    exernal.ExternalDefault to external.Default.

    Change-Id: I1b2521a526fa976146dfe2fcf4d4c1851416d8ae

Changed in keystone:
status: In Progress → Fix Committed
Revision history for this message
Dolph Mathews (dolph) wrote :

+1 for OSSN in comment #24

Revision history for this message
Robert Clark (robert-clark) wrote :

Two thoughts on the OSSN:

"When Keystone is run in Apache HTTP Server" isn't this normally described as running Keystone "behind" apache?

We probably shouldn't use Oauthv1 in our configuration snippet as it's not without it's own security considerations.

Otherwise looks good to me :)

Revision history for this message
Nathan Kinder (nkinder) wrote :

> "When Keystone is run in Apache HTTP Server" isn't this normally described as running Keystone "behind" apache?

Keystone is actually run as a child of the httpd process by using mod_wsgi, so I think "in Apache HTTP Server" is appropriate here.

> We probably shouldn't use Oauthv1 in our configuration snippet as it's not without it's own security considerations.

I can pull this out. It was in the default config on my Havana RDO install, so I was simply using the default config in the example.

Revision history for this message
Nathan Kinder (nkinder) wrote :
Download full text (3.3 KiB)

Published the following OSSN to the openstack and openstack-dev mailing lists:

-----------------------------------------------------------------

Keystone can allow user impersonation when using REMOTE_USER for
external authentication
---

### Summary ###
When external authentication is used with Keystone using the
"ExternalDefault" plug-in, external usernames containing "@"
characters are truncated at the "@" character before being mapped to a
local Keystone user. This can result in separate external users
mapping to the same local Keystone user, which could lead to user
impersonation.

### Affected Services / Software ###
Keystone, Havana

### Discussion ###
When Keystone is run in the Apache HTTP Server, the webserver can
handle authentication and pass the authenticated username to Keystone
using the REMOTE_USER environment variable. External authentication
behavior is handled by authentication plugins in Keystone. In the
Havana release of OpenStack, if the external username provided in the
REMOTE_USER environment variable contains an "@" character Keystone
will only use the portion preceding the "@" character as the username
when using the "ExternalDefault" authentication plugin. This results
in the ability for multiple unique external usernames to map to the
same single username in Keystone. For example, the external usernames
"<email address hidden>" and "<email address hidden>" would both map to the
Keystone user "jdoe". This behavior could potentially be abused to
allow one to impersonate another similarly named external user.

Keystone in OpenStack releases prior to Havana uses the entire value
contained in the REMOTE_USER environment variable, so those versions
are not vulnerable to this impersonation issue.

### Recommended Actions ###
If the "ExternalDefault" plugin is being used for external
authentication in the Havana release, you should ensure that external
usernames do not contain "@" characters unless you want to collapse
similarly named external users into a single user on the Keystone side.

If your external usernames do contain "@" characters and you do not
want to collapse similarly named external users into a single user on
the Keystone side, you might be able to use the "ExternalDomain"
plug-in. This plugin considers the portion of the external username
that follows an "@" character to be the domain that the user belongs
to in Keystone. This allows similarly named external users to map to
separate Keystone users if the portion of the external username that
follows an "@" character maps to a Keystone domain name. To configure
the "ExternalDomain" authentication plugin, set the "external"
parameter in the "[auth]" section of Keystone's keystone.conf as follows:

---- begin example keystone.conf snippet ----
[auth]
methods = external,password,token
external = keystone.auth.plugins.external.ExternalDomain
---- end example keystone.conf snippet ----

If neither of the above recommendations work for your deployment, a
custom authentication plugin can be created that uses the external
username that contains an "@" character as-is.

### Contacts / References ###
This OSSN : https://bugs.launchpad.net/ossn/+bug/1254619
Original LaunchPa...

Read more...

Changed in ossn:
status: In Progress → Fix Released
Thierry Carrez (ttx)
Changed in keystone:
milestone: none → icehouse-2
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in keystone:
milestone: icehouse-2 → 2014.1
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.