Issue 9052 - ACL protections get lost if same identity uses different SSF levels
Summary: ACL protections get lost if same identity uses different SSF levels
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: 2.4.47
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-07-09 21:23 UTC by Quanah Gibson-Mount
Modified: 2019-07-24 22:12 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Quanah Gibson-Mount 2019-07-09 21:23:42 UTC
Full_Name: Quanah Gibson-Mount
Version: 2.4.47
OS: N/A
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (47.208.128.44)


It is common set a security factor level in ACL statements to ensure that that
strength level must be met for an operation to proceed.  A common example of
this would be sasl_ssf=56 (require SASL/GSSAPI) or tls_ssf=256 (require TLS).

However, these protections fail if an operation does *not* meet the security
specifications is executed AFTER an operation that does meet the required
security specifications.

I have a slapd.conf file that has the following access restrictions:

access to *
    by self write
    by sockurl.exact="ldapi:///" write
    by users sasl_ssf=56 read
    by anonymous auth

After starting slapd, we can see that this ACL is correctly honored when I
search via a cleartext connection (no TLS, no SASL, etc):

# /etc/init.d/slapd restart
slapd stopping....  done.
slapd starting...  done.
# ldapsearch -LLL -x -H ldap:/// -D
krb5PrincipalName=bob@RB.SYMAS.NET,ou=KerberosPrincipals,dc=example,dc=com -w
secret -b dc=example,dc=com krb5PrincipalName=bob@RB.SYMAS.NET
No such object (32)
# ldapsearch -LLL -x -H ldap:/// -D
krb5PrincipalName=bob@RB.SYMAS.NET,ou=KerberosPrincipals,dc=example,dc=com -w
secret -b dc=example,dc=com krb5PrincipalName=bob@RB.SYMAS.NET
No such object (32)

(I ran it twice just to ensure the result)

Next, I do a SASL/GSSAPI bind (which maps to the same user entry), and we
(correctly) get a result:

# ldapsearch -LLL -Q -Y GSSAPI -H ldap:// -X u:bob -b dc=example,dc=com
krb5PrincipalName=bob@RB.SYMAS.NET                                              
 dn: krb5PrincipalName=bob@RB.SYMAS.NET,ou=KerberosPrincipals,dc=example,dc=com
objectClass: top
objectClass: account
objectClass: krb5Principal
objectClass: krb5KDCEntry
objectClass: simpleSecurityObject
krb5PrincipalName: bob@RB.SYMAS.NET
uid: bob
krb5KeyVersionNumber: 1
krb5ExtendedAttributes:: MBqgAwEBAKETpxEYDzIwMTkwNzA5MjEwNDAzWg==
krb5MaxLife: 86400
krb5MaxRenew: 604800
krb5KDCFlags: 126
krb5Key:: MEmhKzApoAMCARKhIgQgCua45ttcKFQ+ZUJfapWldQ9wLqGBvHgg9hQLjc2faYyiGjAY
 oAMCAQOhEQQPUkIuU1lNQVMuTkVUYm9i
krb5Key:: MEGhIzAhoAMCARChGgQYMcRG2uw0ATh89Fc4pG2Ag5h8OOb+eo8mohowGKADAgEDoREE
 D1JCLlNZTUFTLk5FVGJvYg==
krb5Key:: MDmhGzAZoAMCARehEgQQt8iZFUGX6KKjMSHXaiQKtaIaMBigAwIBA6ERBA9SQi5TWU1B
 Uy5ORVRib2I=
userPassword:: c2VjcmV0


Finally, I re-run my original search, and this time it INCORRECTLY returns
results:

# ldapsearch -LLL -x -H ldap:/// -D
krb5PrincipalName=bob@RB.SYMAS.NET,ou=KerberosPrincipals,dc=example,dc=com -w
secret -b dc=example,dc=com krb5PrincipalName=bob@RB.SYMAS.NET
dn: krb5PrincipalName=bob@RB.SYMAS.NET,ou=KerberosPrincipals,dc=example,dc=com
objectClass: top
objectClass: account
objectClass: krb5Principal
objectClass: krb5KDCEntry
objectClass: simpleSecurityObject
krb5PrincipalName: bob@RB.SYMAS.NET
uid: bob
krb5KeyVersionNumber: 1
krb5ExtendedAttributes:: MBqgAwEBAKETpxEYDzIwMTkwNzA5MjEwNDAzWg==
krb5MaxLife: 86400
krb5MaxRenew: 604800
krb5KDCFlags: 126
krb5Key:: MEmhKzApoAMCARKhIgQgCua45ttcKFQ+ZUJfapWldQ9wLqGBvHgg9hQLjc2faYyiGjAY
 oAMCAQOhEQQPUkIuU1lNQVMuTkVUYm9i
krb5Key:: MEGhIzAhoAMCARChGgQYMcRG2uw0ATh89Fc4pG2Ag5h8OOb+eo8mohowGKADAgEDoREE
 D1JCLlNZTUFTLk5FVGJvYg==
krb5Key:: MDmhGzAZoAMCARehEgQQt8iZFUGX6KKjMSHXaiQKtaIaMBigAwIBA6ERBA9SQi5TWU1B
 Uy5ORVRib2I=
userPassword:: c2VjcmV0



This is a significant problem, as it means any protections to ensure encryption
is required for results to be returned for a given identity are utterly lost.
Comment 1 Howard Chu 2019-07-10 20:31:24 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 2 Quanah Gibson-Mount 2019-07-11 17:22:17 UTC
changed notes
Comment 3 Quanah Gibson-Mount 2019-07-15 16:03:31 UTC
changed notes
changed state Test to Release
Comment 4 Quanah Gibson-Mount 2019-07-24 19:06:56 UTC
changed notes
Comment 5 Quanah Gibson-Mount 2019-07-24 19:06:57 UTC
published 9052
marked public
Comment 6 OpenLDAP project 2019-07-24 19:07:12 UTC
fixed in master
fixed in RE24 (2.4.48)
CVE-2019-13565
Comment 7 Quanah Gibson-Mount 2019-07-24 19:07:12 UTC
changed notes
changed state Release to Closed
Comment 8 Quanah Gibson-Mount 2019-07-24 21:40:24 UTC
--On Wednesday, July 24, 2019 8:06 PM +0000 openldap-its@OpenLDAP.org wrote:


For informational purposes, here's additional detail as the subject and 
original problem description do not fully capture the extend of the 
problem.  In all 2.x releases prior to 2.4.48 (I.e., 2.0.x, 2.1.x, 2.2.x, 
2.3.x, and 2.4.x up to 2.4.47), the SASL security factor layer was set 
globally rather than per connection.  So once a connection had been made 
that sets a SASL SSF, any and all non SASL connections would inherit that 
value.

If ACLs are used to limit access via setting restrictions with the sasl_ssf 
parameter, connections with no sasl_ssf could match those ACLs incorrectly.

For example,

access to *
 by users sasl_ssf=56 read
 by users tls_ssf=128 read
 by * none

Would allow a user who bound without any encryption full access to the 
database as long as one SASL connection had been made that had a minimum 
sasl_ssf value of 56.

Another contrived example:

access to attrs=userPassword
 by self sasl_ssf=56 =xw
 by * auth

Would allow a user to change their own password whether or not they had 
performed a SASL bind with a sasl_ssf of 56.


--Quanah

--

Quanah Gibson-Mount
Product Architect
Symas Corporation
Packaged, certified, and supported LDAP solutions powered by OpenLDAP:
<http://www.symas.com>


Comment 9 Quanah Gibson-Mount 2019-07-24 21:45:41 UTC
For informational purposes, here's additional detail as the subject and 
original problem description do not fully capture the extend of the 
problem.  In all 2.x releases prior to 2.4.48 (I.e., 2.0.x, 2.1.x, 2.2.x, 
2.3.x, and 2.4.x up to 2.4.47), the SASL security factor layer was set 
globally rather than per connection.  So once a connection had been made 
that sets a SASL SSF, any and all non SASL connections would inherit that 
value.

If ACLs are used to limit access via setting restrictions with the sasl_ssf 
parameter, connections with no sasl_ssf could match those ACLs incorrectly.

For example,

access to *
 by users sasl_ssf=56 read
 by users tls_ssf=128 read
 by * none

Would allow a user who bound without any encryption full access to the 
database as long as one SASL connection had been made that had a minimum 
sasl_ssf value of 56.

Another contrived example:

access to attrs=userPassword
 by self sasl_ssf=56 =xw
 by * auth

Would allow a user to change their own password whether or not they had 
performed a SASL bind with a sasl_ssf of 56.


--Quanah


--

Quanah Gibson-Mount
Product Architect
Symas Corporation
Packaged, certified, and supported LDAP solutions powered by OpenLDAP:
<http://www.symas.com>


Comment 10 Quanah Gibson-Mount 2019-07-24 22:12:08 UTC
--On Wednesday, July 24, 2019 3:45 PM -0700 Quanah Gibson-Mount 
<quanah@symas.com> wrote:

> For informational purposes, here's additional detail as the subject and
> original problem description do not fully capture the extend of the
> problem.  In all 2.x releases prior to 2.4.48 (I.e., 2.0.x, 2.1.x, 2.2.x,
> 2.3.x, and 2.4.x up to 2.4.47), the SASL security factor layer was set
> globally rather than per connection.  So once a connection had been made
> that sets a SASL SSF, any and all non SASL connections would inherit that
> value.

Correction -- sasl SSF was set per connection structure.  Any new client 
connection that used the same connection structure as a previous connection 
would inherit the sasl_ssf value of the prior connection.  In slapd, one 
can generally tell which connection structure is being used by looking at 
the file descriptor in use by a given connection (stats level logging will 
display this information, for example).  On a busy server where connection 
structures are routinly being re-used then there is a high probability that 
this would apply to most connections as long as the majority of connections 
are setting SASL SSF values.

--Quanah


--

Quanah Gibson-Mount
Product Architect
Symas Corporation
Packaged, certified, and supported LDAP solutions powered by OpenLDAP:
<http://www.symas.com>