indieweb / indieauth

IndieAuth.net website code and IndieAuth Specification
52 stars 7 forks source link

Improve validation rules for the verification response 'me' #35

Closed fluffy-critter closed 4 years ago

fluffy-critter commented 4 years ago

The spec as currently written says:

Clients MUST use the resulting me value from the authorization code verification or access token response rather than assume the initially-entered URL is correct, with the following condition:

The resulting profile URL MUST have a matching domain of the initially-entered profile URL.

This ensures that an authorization endpoint is not able to issue valid responses for arbitrary profile URLs.

However this has a security concern in the case of a website with multiple users on a single domain; for example, given sites https://example.com/alice/ and https://example.com/bob/, the bob user could provide an IndieAuth authorization_endpoint that maliciously verifies all codes with a me of https://example.com/alice.

The specification should instead only allow augmentations to the path; for example:

however,

Possible phrasing:

"The response URL's normalized path is strictly the same as or within a subdirectory of the provided identity URL's path"

dmitshur commented 4 years ago

In your suggestion to only allow augmentations to the path, it's worth considering that the following user profile canonicalization may be worth supporting:

I've considered this concern, but understood it to be okay as long as you treat the entire domain as a unit of trust. For https://example.com/alice/ to use IndieAuth safely, she must trust that example.com will not be malicious and will not allow another URL on the same domain to impersonate her.

Such an assumption makes IndieAuth very suitable for single user per website, but it does not have good properties if it is to be used for multiple users per website. A change such as the one you're proposing can improve that aspect.

fluffy-critter commented 4 years ago

Hmm, yeah, I can see an argument being made for leaving off the terminal /. I doubt it would come up in practice but it's good to be unambiguous.

I guess this goes down the rabbit hole of defining what's meant by a normalized path, or phrasing the concern in terms of path components or something.

And yeah the whole reason I proposed this change is because as it stands, IndieAuth is only suitable for one-user-per-domain situations, but there's definitely interest in getting IndieAuth support for multi-user systems like Mastodon, or old-school shared-domain sites like tilde.club/tilde.town et al.

dmitshur commented 4 years ago

And yeah the whole reason I proposed this change is because as it stands, IndieAuth is only suitable for one-user-per-domain situations, but there's definitely interest in getting IndieAuth support for multi-user systems

That makes sense.

To be thorough, I'll mention that since a subdomain is a part of the domain, IndieAuth is currently also suitable for one-user-per-subdomain situations. For example, https://alice.example.com/ can be safe knowing that https://bob.example.com/ could not impersonate her in the manner described in the original issue.

fluffy-critter commented 4 years ago

Oh, sure, but subdomains aren't the concern behind this proposal. :)

fluffy-critter commented 4 years ago

(Which is to say that in the context of IndieAuth -- or anything else, for that matter -- there's no difference between a domain and a subdomain. Strictly speaking, foo.com and bar.com are both subdomains of com.)

dmitshur commented 4 years ago

The original issue talks only about differences in the URL path. Another case to consider is URLs that differ only in the query component. E.g.:

fluffy-critter commented 4 years ago

And that opens up a whole slew of things to wonder about, like given https://example.com/user/bob?foo=bar what about https://example.com/user/bob/profile

That said, the path specificity already implies authoritative control over the path itself; it doesn't seem likely to have a situation where different users would have different control over the identity response given the same path but different query paremeters. Any situation where that is the case is not, IMO, worth caring too much about. To that end I think that the query component should be ignored in the comparison.

Now, to clarify the situation I'm worried about here, let's say you have a shared domain with old-fashioned https://example.com/~username URLs that map to a public_html directory, or generally anywhere that people have some control over the HTML <head> and/or response headers. You want to prevent people from being able to authenticate themselves as other users on the same domain. For example, Alice has a webpage at https://example.com/~alice/ with:

<link rel="authorization_endpoint" href="https://example.com/cgi-bin/indieauth.cgi">

where indieauth.cgi, say, uses PAM credentials to verify the profile URL. Meanwhile, Bob has a webpage at https://example.com/~bob/ with this HTML:

<link rel="authorization_endpoint" href="https://bogus-indieauth.example.com/">

where bogus-indieauth.example.com is a rogue endpoint that allows people to specify any final me URL they want (for example, https://github.com/fluffy-critter/AnyAuth/).

This isn't just theoretical. I have a proof of concept at https://tilde.club/~fluffy which points to an AnyAuth instance as the authorization endpoint. Sign into any IndieAuth site using that URL, and most clients will let you identify as any tilde.club user, under the current validation rules.

I've actually had this up and running for quite some time now (which is to say, since roughly last October). This is a serious flaw in the specification.

jalcine commented 4 years ago

That URL (https://tilde.club/~fluffy/) broke with https://publish.koype.net. That's because I grab the token endpoint that's used in the returned profile to verify the token (which fails).

fluffy-critter commented 4 years ago

Yeah, that page doesn't declare a token endpoint. But anything which only does indieauth for identity verification, for example webmention.io, lets me log in appearing as any tilde.club user.

It does limit the scope of the issue somewhat but it's still a problem for anything that uses just IndieAuth without tokens, and this is why in Authl I opted to implement the profile URL validation per the suggestion in the original issue.

That said, I suppose that one possible alternative to codifying stricter URL validation would be to verify that the target profile has the same authorization_endpoint. I can't readily think of any issues with that, but I also don't have a very good imagination when it comes to security stuff.

fluffy-critter commented 4 years ago

So okay maybe the solution is adding the following to the end of s7.1 (differing profile URLs):

If the resulting profile URL differs from the initially-entered profile URL, the client SHOULD verify that the resulting profile URL declares the same authorization_endpoint. This prevents users on a shared domain from forging their identity as being another user of that domain.