Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Federation: sanitize paths to avoid path traversal attacks #1646

Merged
merged 5 commits into from
Jul 8, 2021

Conversation

jschaul
Copy link
Member

@jschaul jschaul commented Jul 6, 2021

At the moment we use the convention that all RPCs between federator -> brig/galley/etc use the "federation" path prefix. This PR adds validation to ensure other paths cannot be called, as that would expose non-federation APIs (including internal, non-authenticated ones) to the world.

See also the discussion in https://wearezeta.atlassian.net/wiki/spaces/CORE/pages/224166764/Limiting+access+to+federation+endpoints

Checklist

  • Title of this PR explains the impact of the change.
  • The description provides context as to why the change should occur and what the code contributes to that effect. This could also be a link to a JIRA ticket or a Github issue, if there is one.
  • rebase to develop after Federation: Types for InwardErrors and federator refactoring #1637 has landed.
  • The CHANGELOG.md file in the Unreleased section has been updated to explain the change which will be included in the release notes.

@jschaul jschaul changed the title Federation: sanitize paths to avoid path traversal attacks [WIP] [skip ci] Federation: sanitize paths to avoid path traversal attacks Jul 6, 2021
@jschaul jschaul force-pushed the federation-sanitize-paths branch from e9905c5 to e8fc0c3 Compare July 6, 2021 17:34
@jschaul jschaul changed the title [WIP] [skip ci] Federation: sanitize paths to avoid path traversal attacks Federation: sanitize paths to avoid path traversal attacks Jul 6, 2021
runTestFederator env $ do
let o = object ["name" .= ("fakeNewUser" :: Text)]
err <- asInwardErrorUnsafe <$> inwardBrigCall "federation/../i/users" (encode o)
expectErr IForbiddenEndpoint err
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dear reviewers, I'd love ideas on what other things to test. Would any property tests make sense here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having property tests for sanitizePath would be useful, but of course only insofar as the generator produces realistic URL inputs. As for ad-hoc test cases, you could maybe add some with non-ascii character (both percent-encoded and not), query string and/or fragments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, some (unit) tests for sanitizePath would be good to have, including one that has "federation" as the only path segment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a bunch of unit tests, take a look.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 👍

Copy link
Contributor

@kkohbrok kkohbrok left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks solid already! Another common vector for attacks would be encoding. I assume that URIB.parseRelativeRef handles the decoding of the byte string, so we could test the normalization function for its handling of percent encoding. I don't have a lot of experience in webapp security, but it seems to be a common enough attack vector to have some tests for it, i.e. to make sure that the normalizer properly handles percent decoding before sanitization.

Copy link
Contributor

@pcapriotti pcapriotti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

services/federator/src/Federator/Validation.hs Outdated Show resolved Hide resolved
runTestFederator env $ do
let o = object ["name" .= ("fakeNewUser" :: Text)]
err <- asInwardErrorUnsafe <$> inwardBrigCall "federation/../i/users" (encode o)
expectErr IForbiddenEndpoint err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having property tests for sanitizePath would be useful, but of course only insofar as the generator produces realistic URL inputs. As for ad-hoc test cases, you could maybe add some with non-ascii character (both percent-encoded and not), query string and/or fragments.

Copy link
Contributor

@mdimjasevic mdimjasevic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good. I haven't checked, but I suppose sanitizePath is already used for all federator paths?

runTestFederator env $ do
let o = object ["name" .= ("fakeNewUser" :: Text)]
err <- asInwardErrorUnsafe <$> inwardBrigCall "federation/../i/users" (encode o)
expectErr IForbiddenEndpoint err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, some (unit) tests for sanitizePath would be good to have, including one that has "federation" as the only path segment.

Base automatically changed from federator-resrict-paths to develop July 7, 2021 15:20
jschaul added a commit that referenced this pull request Jul 7, 2021
* Introduce a few error types in `InwardResponse`
* Improve readability of ExternalServer in Federator by use of Polysemy.Error also in callLocal
* This also solves an existing TODO whereby federator integration tests didn't work due to InwardResponses, whether an error or an expected return value, were parsed always as InwardResponseBody. This may have been an issue with mu-haskell when parsing (only needed in tests), since the behaviour when using `grpccurl` was correct. This is now sidestepped by using more than a simple string on errors.

This PR is in preparation to sanitize request paths against path traversal attacks (separate PR #1646)
At the moment we use the convention that all RPCs between federator -> brig/galley/etc use the "federation" path prefix. This PR adds validation to ensure other paths cannot be called, as that would expose non-federation APIs (including internal, non-authenticated ones) to the world.

See also the discussion in https://wearezeta.atlassian.net/wiki/spaces/CORE/pages/224166764/Limiting+access+to+federation+endpoints
@jschaul jschaul force-pushed the federation-sanitize-paths branch from 87a871e to c858462 Compare July 7, 2021 15:25
@jschaul
Copy link
Member Author

jschaul commented Jul 8, 2021

I added a range of tests, and also changed the implementation to guard against more cases. Merging this PR now, but in case someone still has other ideas, feel free to comment.

@jschaul jschaul merged commit 2437b62 into develop Jul 8, 2021
@jschaul jschaul deleted the federation-sanitize-paths branch July 8, 2021 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants