ruby / ruby/net-http

Make it easier to prevent Server side request forgery (SSRF) attacks

Offen
#141 7 Kommentare 1 Reaktion 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Vorherrschende Sprache
Ruby
Sterne
148
Forks
95
Ø Merge
10 Std. 54 Min.
Gemergte PRs (30 T.)
4

Beschreibung

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:

  1. Performing a DNS lookup first for the IP address.
  2. If the IP address maps to internal or local networks, reject the request.
  3. 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-http to use the original hostname by overriding the hostname= 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?

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne damit, den #connect-Pfad von net-http und die bestehende Behandlung von hostname= zu lesen, und vergleiche dann die im Issue beschriebene SSRF-Abwehr mit dem Resolv-Workaround in ssrf_filter. Das Issue schlägt einen Callback für die Hostnamenauflösung und die Genehmigung von Verbindungen vor, definiert jedoch keine festgelegte API oder Tests; abgeschlossen wäre die Aufgabe erst mit einem abgestimmten Design und einer Abdeckung für abgelehnte interne Adressen und erlaubte HTTPS-Verbindungen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
ruby
Bereich
networking, security
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Ruhig
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.