Make it easier to prevent Server side request forgery (SSRF) attacks
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
- Issue type
- Feature
- Clarity
- Needs clarification
- Activity status
- Quiet
- Tech stack
- ruby
- Domain
- networking, security
Research direction
Start by reading net-http's #connect path and the existing hostname= handling, then compare the SSRF mitigation described in the issue with the Resolv workaround in ssrf_filter. The issue suggests a callback for hostname resolution and connection approval, but does not define a settled API or tests; done would require an agreed design and coverage for rejected internal addresses and allowed HTTPS connections.
Written by the indexing model from the issue text.
Description
Over the years, we've received many bug bounty reports relating to Server side request forgery (SSRF) attacks. In a nutshell, these attacks use short-lived DNS entries to direct Web hooks and other URLs to internal IP addresses, such as AWS's instance metadata endpoint.
To a large extent, the problem is mitigated by using HTTPS, since a SSL certificate Common Name (CN) must match the hostname. However, there are a number of edge cases where HTTPS doesn't solve the issue. For example:
- DNS rebinding might still enable reconnaissance on the local network, since errors show the difference between "10.1.2.3:4567 unreachable" and "10.1.2.3:4567 reachable but TLS error".
- Some clients or Web hooks may disable SSL certificate verification.
In the past, we've mitigated the problem by:
- Performing a DNS lookup first for the IP address.
- If the IP address maps to internal or local networks, reject the request.
- If the IP address is allowed, make the HTTPS request with the IP address instead of the hostname. To ensure SNI works, we patched
net-httpto use the original hostname by overriding thehostname=method.
A similar approach is taken by ssrf_filter.
However, with https://github.com/ruby/net-http/pull/36, our net-http patch no longer works because hostname= isn't called when an IP address is used. To handle that, https://github.com/arkadiyt/ssrf_filter/pull/54 introduced an even uglier patch that overrides the Resolv equality methods.
Both hostname= and Resolv patches are a bit ugly, but short of patching the #connect method there's no alternative at the moment.
A better approach might be to invoke some callback in #connect that will allow the caller to resolve the hostname and decide whether the connection should still proceed.
I realize that others might argue that a proxying all external calls via a proxy server is ultimately the right approach, but that's another moving part that requires more setup.
@jeremyevans What do you think about this?
- Dominant language
- Ruby
- Stars
- 148
- Forks
- 95
- Avg merge
- 10h 54m
- Merged PRs (30d)
- 4
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ruby/net-http
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
-
Difficulty 5/5 Over a week Newbie friendliness 38/100
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
Similar issues
-
user-reported
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Kong/developer.konghq.com#7316 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
TheOdinProject/curriculum#31408 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
bensheldon/good_job#1816 · 5 comments ·