decentralized-identity / decentralized-web-node

Decentralized data storage and message relay for decentralized identity and apps.
https://identity.foundation/decentralized-web-node/spec/
Apache License 2.0
402 stars 79 forks source link

Requiring fine-grained capabilities #142

Open alanhkarp opened 2 years ago

alanhkarp commented 2 years ago

The current specification allows the capability for a collection to be used when accessing an individual member of that collection, which is a violation of the Principle of Least Privilege. Of course, the holder of a capability for a collection can always create a new capability for the individual item, but that requires extra work that many people won't do. The result will be that a successful attack will be able to do substantially more harm than had the system required fine-grained capabilities.

It should be possible for the software invoked when submitting a request to construct the fine-grained capability from the one provided by the invoker.

andorsk commented 1 year ago

Discussed on DIF call.

Designate solely on the capability. Give permission to the specific record. The problem comes in with an API call that promotes more than one object. Example: Copy and paste multiple objects.

alanhkarp commented 1 year ago

Think of Alice calling a function that will read a specified file. One way to do that is

readfn("/u/alice/data.txt")

The problem is that readfn() needs permission to read any file that Alice has permission to read. A better approach is for Alice to do

handle = open("/u/alice/data.txt", r) readfn(handle)

Now readfn() doesn't need any of Alice's permissions because "handle" is a capability.

Now consider a DWN capability that specifies a collection, analogous to "/u/alice/*"; call it cap1. It makes perfect sense for Alice to hold such a capability. One way for Alice to do an invocation is

readfn(cap1, "data.txt")

There are two problems. The first is a violation of Least Privilege. Invoking in this way means Alice is giving readfn() permission to read everything in "/u/alice".

The correct approach is for Alice to do

cap2 = delegate(cap1, "data.txt") readfn(cap2)

Note the way the capability is used as the argument to the function.

The second problem is that you've separated designation of the specific object, data.txt, from the authorization to use it, cap1. In more complex scenarios that can lead to a confused deputy vulnerability. Although it was stated in the call that DWN has no APIs that involve more than one argument, @andorsk asks about calls involving multiple arguments. In that situation Alice would do

cap2 = delegate(cap1, r, "input.txt") cap3 = delegate(cap1, w, "output.txt") copypaste(cap2, cap3)

She could also invoke an operation on a collection, e.g.,

cap2 = delegate(cap1, r, "/u/alice") cap3 = delegate(cap1, w, "/u/alice/backup) backup(cap2, cap3)

In this case the operation is being performed on the collection, so it makes sense to designate the collection. The point is that the capability designates what is to be operated on, not some other piece of information.

LiranCohen commented 1 year ago

@alanhkarp

There are two problems. The first is a violation of Least Privilege. Invoking in this way means Alice is giving readfn() permission to read everything in "/u/alice".

I'm not sure I quite follow this logic wrt DWNs. I'd like to try to describe this in the sense of collections and DIDs to better understand who is giving capabilities to who.

So we have did:alice, she has a collection "example.org/AliceStuff/", since she is the owner of the collection, she has implicit capabilities.

Now say she wants to give access to did:bob, she could either:

a) grant a Read&Write capability to did:bob over the entire collection (this would imply she completely trusts bob) b) grant a Read&Write capability to did:bob for a specific record (identified by a recordId) c) as a part of a protocol definition & a grant, allow bob to add new records into "example.org/AliceStuff/" and only allow him to modify/delete the records that he added.

Does this still fit the problem case you presented? We can discuss on the call today or async within the issue.

andorsk commented 1 year ago

TODO: Let's wait until the spec aligns and then revisit this after it is updated.

alanhkarp commented 1 year ago

@LiranCohen

I'm not sure I quite follow this logic wrt DWNs. I'd like to try to describe this in the sense of collections and DIDs to better understand who is giving capabilities to who.

Sorry for the confusion. I haven't gotten the terminology straight for the different communities I'm talking to.😞

So we have did:alice, she has a collection "example.org/AliceStuff/", since she is the owner of the collection, she has implicit capabilities.

Now say she wants to give access to did:bob, she could either:

a) grant a Read&Write capability to did:bob over the entire collection (this would imply she completely trusts bob) b) grant a Read&Write capability to did:bob for a specific record (identified by a recordId) c) as a part of a protocol definition & a grant, allow bob to add new records into "example.org/AliceStuff/" and only allow him to modify/delete the records that he added.

c) is a separate issue that needs to be discussed.

Does this still fit the problem case you presented? We can discuss on the call today or async within the issue.

That's not the issue that concerns me.

When did:alice gives did:bob access to the collection, the certificate will have something that looks like "example.org/AliceStuff/*" with a "Read" and a "Write" permission. (The details depend on the certificate format.)

The question that concerns me is the invocation. Clearly, the certificate with "example.org/AliceStuff/*" does not specify which record did:bob wants to read. In several proposed systems, the specific record is designated somewhere else. That's the issue, which the analogy with readfn("example.org/AliceStuff/Vegas.gif") was meant to illustrate (but I think confused the issue).

Let's call the certificate that that gives did:bob read and write permission to everything in AliceStuff A2B. Then did:bob can create an invocation that would have fields

operation: "Read", permission: A2B, record: "Vegas.gif

I'm proposing instead that did:bob MUST delegate to a key he controls a new certificate denoting a specific record. Call that certificate A2B-Vegas.gif. Now Bob's invocation is

operation: "Read", permission: A2B-Vegas.gif

In other word, did:bob creates a capability that both designates the specific record AND authorizes his use of it.

There's no essential difference in this simple case of a single argument, but there is when there are two or more. That's what the confused deputy vulnerability is all about.

LiranCohen commented 12 months ago

Resurfacing this to the top given @alanhkarp's recent comments within the implementation repo.

When we originally discussed this we did not have roles specified within protocols.

https://github.com/TBD54566975/dwn-sdk-js/pull/512#issuecomment-1743795300

andorsk commented 9 months ago

Discussed at DIF (December 13):

Discussed that the confused deputy problem, similar with Unix based systems, is out of scope for the work on DWN currently, but acknowledged that it is possible that given a permission overlay written against a DWN, there are ways to bypass the proper capabilities if a custom permission layer is written on top of the DWN. Direct, directed delegated capability could be roadmap. If more use cases show up, we will refocus this problem. Delegation is on the spec, but we will need to focus on this to effectively solve the confused deputy problem.

graph TD
     a[Third Party] --> PermissionOverlay[Custom Permission Layer] --> PermissionParty[Permissioned Party] --> DWN
andorsk commented 5 months ago

Possibly add a non-normative section. TODO: Reject a request if the authorization is much broader than the request.

andorsk commented 5 months ago

Probably add in 7.1.

LiranCohen commented 4 months ago

Add language around message authorization and how decide if an authorization matches the request. Applies to protocol-authorization as well as flat-space authorization.