[OpenAFS] RFC: Altering the processing of IPv4 (aka Host) ACLs
to enforce negative rights
Dave Botsch
botsch@cnf.cornell.edu
Thu, 23 Mar 2023 10:05:03 -0400
I'm generally in favor of considering this a bug and fixing it.
Thanks!
On Mon, Mar 20, 2023 at 04:21:12PM -0400, Jeffrey E Altman wrote:
> On 7 March Andrew Deason submitted a patch to OpenAFS documenting the
> existing behavior of the OpenAFS fileserver when computing Anonymous an=
d
> Caller Access Rights if the IPv4 address from which the RXAFS RPC was
> received matches a PTS host entry and that PTS entry matches an Access
> Control Entry (ACE).
>=20
> https://gerrit.openafs.org/#/c/15340/
>=20
> Quoting Andrew's submission to the fs_setacl man page:
>=20
> "Combining _Negative rights_ granted from machine entries (IP
> addresses) and _Normal rights_ granted from non-machine entries (or
> vice versa) will generally not work as expected. Permissions granted
> by machine entries and by non-machine entries are calculated
> separately, and both sets of permissions are given to an accessing
> user. For example, if permissions are granted to an authenticated
> user or group (or _system:anyuser_), you cannot remove those
> permissions from specific hosts by adding machine entries to a group
> in an ACL in the _Negative rights_> section."
>=20
> The IBM AFS Administrator's Guide "Protecting Data in AFS" section stat=
es:
>=20
> "When determining what type of access to grant to a user, theFile
> Server first compiles a set of permissions by examiningall of the
> entries in the Normal rights section of the ACL. Itthen subtracts
> any permissions associated with the user (orwith groups to which the
> user belongs) on the Negative rightssection of the ACL. Therefore,
> negative permissions alwayscancel out normal permissions."
>=20
> IBM/Transarc AFS 3.2 introduced the granting of permissions based upon =
the
> host's IPv4 address in addition to those granted to the caller. The
> implementation evaluates the caller's rights independently of the host'=
s
> rights and then ORs the results. This approach violates the statement t=
hat
> negative permissions always cancel out normal (aka positive) permission=
s. If
> a caller is granted "read" but there is a matching negative "read" ACE =
(aka
> permission) for the host, the negative "read" ACE is ignored. Likewise =
if
> "lookup" is granted to the host but the caller matches a negative "look=
up"
> ACE, then the caller's negative "lookup" ACE is ignored.
>=20
> The problem can be demonstrated with a couple of examples.=A0=A0 First,=
lets
> define some PTS entities and membership relations:
>=20
> * user: jane =3D 1000
> o member: system:authusers
> o member: system:anyuser
> o member: no-admin
> * user: 128.66.0.130 =3D 2000
> o member: local-hosts
> * group: no-admin =3D -100
> o member: jane
> * group: local-hosts =3D -500
> o member: 128.66.0.130
>=20
> Example 1:=A0 RXAFS RPC received from a host that is not a member of
> local-hosts
>=20
> ACL
>=20
> * system:anyuser: l; -none
> * system:authuser: lrk; -none
> * jane: none; -r
> * local-hosts: r; -none
>=20
> Rights:
>=20
> * system:anyuser: lookup
> * system:authuser: lookup, read, lock
> * jane: lookup, lock
>=20
> When "jane" accesses a file with this ACL the granted rights will be "l=
k"
> because the negative read permission cancels the positive read permissi=
on
> granted by the membership in the system:authuser group.
>=20
>=20
> Example 2: RXAFS RPC received from a host that is a member of local-hos=
ts
>=20
> ACL
>=20
> * system:anyuser: l; -none
> * system:authuser: lrk; -none
> * jane: none; -r
> * local-hosts: r; -none
>=20
> Rights:
>=20
> * system:anyuser: lookup, read
> * system:authuser: lookup, read, lock
> * jane: lookup, read, lock
>=20
> In this case, even though "jane" is denied the "read" permission grante=
d to
> members of "system:authuser" because of the negative "read" in the "jan=
e"
> ACE she is granted the permission because of the positive read permissi=
on
> granted to "local-hosts" members. The granting of "read" permission to
> "jane" is an unexpected result!
>=20
>=20
> Example 3: RXAFS RPC received from a host that is not a member of
> local-hosts
>=20
> ACL
>=20
> * system:anyuser: l; -none
> * system:authuser: lrk; -none
> * jane: lrkwid; -none
> * local-hosts: none; -wida
>=20
> Rights:
>=20
> * system:anyuser: lookup
> * system:authuser: lookup, read, lock
> * jane: lookup, read, lock, write, insert, delete
>=20
> In this case, "jane" is granted all of the permissions other than "admi=
n".
>=20
>=20
> Example 4: RXAFS RPC received from a host that is a member of local-hos=
ts
>=20
> ACL
>=20
> * system:anyuser: l; -none
> * system:authuser: lrk; -none
> * jane: lrkwid; -none
> * local-hosts: none; -wida
>=20
> Rights:
>=20
> * system:anyuser: lookup
> * system:authuser: lookup, read, lock
> * jane: lookup, read, lock, write, insert, delete
>=20
> In this case, "jane" is granted all of the permissions other than "admi=
n".=A0=A0
> However, because the RPC was issued from a host that is a member of
> "local-hosts" the expected result would be "jane" receiving only the
> "lookup, read, lock" rights.=A0=A0=A0 The granting of "write, insert an=
d delete"
> permission is an unexpected outcome!
>=20
>=20
> In examples 2 and 4 rights are granted to the caller that would appear =
to be
> contrary to the explicit use of negative rights in the access control
> entries.=A0 The example 4 use case might represent client systems which=
are
> intended to be read-only consumers of the /afs content but which might =
be
> vulnerable to exploitation.=A0=A0 Example 2 is intended to always deny =
read
> privileges to "jane" but if she can gain access to the host with IPv4
> address 128.66.0.130 she can bypass those restrictions.
>=20
> This behavior feels like a bug to me. A bug that has been present since=
the
> release of AFS 3.2 more than thirty years ago but a bug nevertheless.=A0=
I
> propose that OpenAFS fix the broken behavior so that ACL interpretation=
is
> consistent with the documentation inherited from IBM.
>=20
> Two commits submitted to Gerrit will enforce negative access rights.
>=20
> https://gerrit.openafs.org/#/c/15344/
> https://gerrit.openafs.org/#/c/15345/
>=20
>=20
> History:
>=20
> AFS 3.1 and earlier did not have a concept of IP or Host ACLs.=A0=A0 Th=
at
> functionality was introduced in AFS 3.2.=A0 However, the implementation=
that
> is present in the release version of AFS 3.2 and in use to this day mig=
ht
> not have been the original implementation.=A0=A0=A0 Today's fileserver =
issues
> separate calls to the protection service to obtain the caller's Current
> Protection Set (CPS) and the host's CPS.=A0=A0 The fileserver then comp=
utes the
> caller rights by comparing the caller's CPS to the object's ACL; and it
> computes the host's rights by comparing the host's CPS to the object's
> ACL.=A0=A0 The fileserver then grants the caller all rights granted to =
both the
> caller and the host.
>=20
> The host's CPS is obtained by the fileserver by issuing the PR_GetHostC=
PS
> RPC.=A0 PR_GetHostCPS differs from PR_GetCPS in that it matches the hos=
t's
> IPv4 address using wildcard pattern matching when searching for a match=
ing
> PTS ID.=A0 It also does not treat the PTS entity as a member of the
> system:anyuser group.
>=20
> Before PR_GetHostCPS was added to the protection service another RPC wa=
s
> introduced, PR_GetCPS2 which obtained the CPS for the combination of a
> caller and a host. An implementation of IP ACLs that used PR_GetCPS2 wo=
uld
> have behaved as expected because the all of the positive rights would h=
ave
> been computed and from those all of the negative rights would have been
> removed.=A0 I do not have access to the source code for a version of th=
e
> fileserver that used the PR_GetCPS2 RPC but I can imagine that a likely
> implementation would have issued a PR_GetCPS2 call for (anonymous, host=
) and
> (caller, host).=A0=A0 The additional load these RPCs placed on the prot=
ection
> service might have been deemed too expensive.=A0 As a result, the alter=
native
> approach using the PR_GetHostCPS was introduced.
>=20
> Whatever the motivation for PR_GetHostCPS in preference to PR_GetCPS2, =
the
> existing implementation does not interpret ACLs in a manner that permit=
s
> negative rights to be superior to positive rights.=A0=A0 Perhaps it did=
n't occur
> to the implementer that there was a problem; and it didn't occur to any=
one
> that a simple change to acl_checkRights() and the fileserver GetRights(=
)
> function would permit computing the expected results.
>=20
>=20
> Proposal:
>=20
> I propose that OpenAFS treat the current behavior as a bug.=A0 The use =
of
> negative rights is discouraged because they are hard to analyze.=A0 It =
is
> hoped that their use is rare.=A0 If negative rights are not in use, the=
n
> changing the behavior when IP ACLs exist will not alter the computed
> outcome.=A0 However, if negative rights are in use, they are likely bei=
ng used
> because it wasn't easy to limit the access any other way.=A0 In which c=
ase,
> granting more access then was specified is problematic.=A0=A0 A CVE can=
be
> published to document the existing behavior and the behavior as it will
> appear beginning with a specific version of the fileserver.
>=20
> If required, a configuration option can be provided to enable the AFS 3=
.2
> behavior until all of the fileservers within a cell have been updated.=A0=
=A0 I
> discourage using a configuration option to enable the stricter
> interpretation of ACLs as that will result in some sites being vulnerab=
le
> when they did not intend to be.
>=20
>=20
> Jeffrey Altman
>=20
> P.S. I am writing this letter publicly as opposed to sending it to the
> openafs-security queue because the behavior in question is public and
> Andrew's proposed patch to the OpenAFS man pages is public.
>=20
--=20
********************************
David William Botsch
Programmer/Analyst
@CornellCNF
botsch@cnf.cornell.edu
********************************