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

Implement more comprehensive SSRF mitigation #6362

Merged
merged 2 commits into from
Jun 29, 2023

Conversation

SpecLad
Copy link
Contributor

@SpecLad SpecLad commented Jun 22, 2023

Motivation and context

The current mitigation approach (resolving the IP address and checking if it's in the private range) is insufficient for a few reasons:

  • It is susceptible to DNS rebinding (an attacker-controlled DNS name resolving to a public IP address when queried during the check, and to a private IP address afterwards).

  • It is susceptible to redirect-based attacks (a server with a public address redirecting to a server with a private address).

  • It is only applied when downloading remote files of tasks (and is not easily reusable).

Replace it with an approach based on smokescreen, a proxy that blocks connections to private IP addresses. In addition, use this proxy for webhooks, since they also make requests to untrusted URLs.

The benefits of smokescreen are as follows:

  • It's not susceptible to the problems listed above.

  • It's configurable, so system administrators can allow certain private IP ranges if necessary. This configurability is exposed via the SMOKESCREEN_OPTS environment variable.

  • It doesn't require much code to use.

The drawbacks of smokescreen are:

  • It's not as clear when the request fails due to smokescreen (compared to manual IP validation). To compensate, make the error message in _download_data more verbose.

  • The smokescreen project seems to be in early development (judging by the 0.0.x version numbers). Still, Stripe itself uses it, so it should be good enough. It's also not very convenient to set up (on account of not providing binaries), so disable it in development environments.

Keep the scheme check from _validate_url. I don't think this check prevents any attacks (as requests only supports http/https to begin with), but it provides a friendly error message in case the user tries to use an unsupported scheme.

How has this been tested?

Manual testing.

Checklist

  • I submit my changes into the develop branch
  • I have added a description of my changes into the CHANGELOG file
  • [ ] I have updated the documentation accordingly
  • [ ] I have added tests to cover my changes
  • [ ] I have linked related issues (see GitHub docs)
  • [ ] I have increased versions of npm packages if it is necessary
    (cvat-canvas,
    cvat-core,
    cvat-data and
    cvat-ui)

License

  • I submit my code changes under the same MIT License that covers the project.
    Feel free to contact the maintainers if that's a concern.

@SpecLad
Copy link
Contributor Author

SpecLad commented Jun 22, 2023

/check

@github-actions
Copy link
Contributor

github-actions bot commented Jun 22, 2023

✔️ All checks completed successfully
📄 See logs here

@SpecLad SpecLad marked this pull request as ready for review June 23, 2023 09:58
@SpecLad SpecLad force-pushed the comprehensive-ssrf branch 3 times, most recently from e40991a to 7e29781 Compare June 23, 2023 17:28
@codecov
Copy link

codecov bot commented Jun 23, 2023

Codecov Report

Merging #6362 (8725383) into develop (1f6c63b) will decrease coverage by 0.27%.
The diff coverage is 61.53%.

@@             Coverage Diff             @@
##           develop    #6362      +/-   ##
===========================================
- Coverage    81.20%   80.93%   -0.27%     
===========================================
  Files          322      331       +9     
  Lines        37782    42827    +5045     
  Branches      6821     8368    +1547     
===========================================
+ Hits         30680    34662    +3982     
- Misses        6793     7854    +1061     
- Partials       309      311       +2     
Components Coverage Δ
cvat-ui 77.05% <ø> (+0.29%) ⬆️
cvat-server 85.32% <61.53%> (+0.14%) ⬆️

@SpecLad SpecLad force-pushed the comprehensive-ssrf branch 3 times, most recently from a3ef9cd to 5cff3c5 Compare June 25, 2023 12:32
The current mitigation approach (resolving the IP address and checking if it's
in the private range) is insufficient for a few reasons:

* It is susceptible to DNS rebinding (an attacker-controlled DNS name resolving
  to a public IP address when queried during the check, and to a private IP
  address afterwards).

* It is susceptible to redirect-based attacks (a server with a public address
  redirecting to a server with a private address).

* It is only applied when downloading remote files of tasks (and is not easily
  reusable).

Replace it with an approach based on smokescreen, a proxy that blocks connections
to private IP addresses. In addition, use this proxy for webhooks, since they also
make requests to untrusted URLs.

The benefits of smokescreen are as follows:

* It's not susceptible to the problems listed above.

* It's configurable, so system administrators can allow certain private IP ranges
  if necessary. This configurability is exposed via the `SMOKESCREEN_OPTS`
  environment variable.

* It doesn't require much code to use.

The drawbacks of smokescreen are:

* It's not as clear when the request fails due to smokescreen (compared to
  manual IP validation). To compensate, make the error message in
  `_download_data` more verbose.

* The smokescreen project seems to be in early development (judging by the
  0.0.x version numbers). Still, Stripe itself uses it, so it should be good
  enough. It's also not very convenient to set up (on account of not providing
  binaries), so disable it in development environments.

Keep the scheme check from `_validate_url`. I don't think this check
prevents any attacks (as requests only supports http/https to begin with),
but it provides a friendly error message in case the user tries to use an
unsupported scheme.
@azhavoro
Copy link
Contributor

LGTM

@SpecLad SpecLad merged commit 16d03aa into cvat-ai:develop Jun 29, 2023
54 of 56 checks passed
@SpecLad SpecLad deleted the comprehensive-ssrf branch June 29, 2023 11:41
@azhavoro azhavoro mentioned this pull request Jul 5, 2023
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.

None yet

2 participants