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

safe_requests feature request #13

Open
tjs-intel opened this issue Feb 21, 2024 · 5 comments
Open

safe_requests feature request #13

tjs-intel opened this issue Feb 21, 2024 · 5 comments
Assignees
Labels
enhancement New feature or request

Comments

@tjs-intel
Copy link

tjs-intel commented Feb 21, 2024

The current implementation of safe_requests parses the hostname from the request URL and checks it against a fairly limited set of IP addresses (namely 198.168.1.1 and the AWS instance metadata URL). This should be fairly easy to bypass by registering a domain name (or finding one that already exists) either with an A record that resolves to one of these restricted addresses, or by hosting a web server that returns a redirect to the restricted address.

I propose the following procedure for sandboxing requests.

  1. Resolve the host to an IP address, ex. socket.gethostbyname()
  2. Check that the IP address falls within a set of public IP address ranges
  3. Swap the hostname of the URL with the resolved IP address
  4. Hand the request off to requests

There are many edge cases to handle here, ex. tls hostname verification, proxies, redirects, and it may ultimately be easiest to add functionality to requests and/or urllib to support IP address allow/block lists.

@tjs-intel
Copy link
Author

@drdavella

@drdavella drdavella self-assigned this Feb 22, 2024
@drdavella drdavella added the enhancement New feature or request label Feb 22, 2024
@drdavella
Copy link
Member

Hi @tjs-intel thanks so much for opening this issue! I agree that ultimately upstreaming this to requests itself might be a good idea. However one of the main motivations for the security project is the fact that many commonly used libraries don't currently enable that kind of hardening.

You've identified an interesting gap here and I think it's worth working through a potential solution. I'm going to ask @matt- to chime in since I think he has a few ideas about how we could accomplish what you're suggesting. One such option might be to hook into a lower-level layer of the requests library and perform validation there.

@tjs-intel
Copy link
Author

I tried a quick POC of this concept yesterday by adding an IP address check here in http.client:

https://github.com/python/cpython/blob/b254de71d0d1eb0232ff4abd403a4977ca3f2fe7/Lib/http/client.py#L1010

@matt-
Copy link

matt- commented Feb 22, 2024

If we just swap out the host name with the resolved IP I think we may run into some issues with servers that check hostname header, or parse raw URL for some reason.

However I think we could hook into this by making the safe methods use a custom "Transport Adapter"

s = requests.Session()
s.mount('https://github.com/', MyAdapter())

I will have to dig more, but it looks like we could grab access to the "connection" before the request is made which would give us the resolved IP

@tjs-intel
Copy link
Author

A relevant post on SO, showing how to resolve a hostname before making the connection: https://stackoverflow.com/a/22614367

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants