Module: HTTPX::Plugins::SsrfFilter

Defined in:
lib/httpx/plugins/ssrf_filter.rb

Overview

This plugin adds support for preventing Server-Side Request Forgery attacks.

gitlab.com/os85/httpx/wikis/Server-Side-Request-Forgery-Filter

Defined Under Namespace

Modules: ConnectionMethods, IPAddrExtensions, InstanceMethods, OptionsMethods

Constant Summary collapse

IPV4_BLACKLIST =
[
  IPAddr.new("0.0.0.0/8"), # Current network (only valid as source address)
  IPAddr.new("10.0.0.0/8"), # Private network
  IPAddr.new("100.64.0.0/10"), # Shared Address Space
  IPAddr.new("127.0.0.0/8"), # Loopback
  IPAddr.new("169.254.0.0/16"), # Link-local
  IPAddr.new("172.16.0.0/12"), # Private network
  IPAddr.new("192.0.0.0/24"), # IETF Protocol Assignments
  IPAddr.new("192.0.2.0/24"), # TEST-NET-1, documentation and examples
  IPAddr.new("192.88.99.0/24"), # IPv6 to IPv4 relay (includes 2002::/16)
  IPAddr.new("192.168.0.0/16"), # Private network
  IPAddr.new("198.18.0.0/15"), # Network benchmark tests
  IPAddr.new("198.51.100.0/24"), # TEST-NET-2, documentation and examples
  IPAddr.new("203.0.113.0/24"), # TEST-NET-3, documentation and examples
  IPAddr.new("224.0.0.0/4"), # IP multicast (former Class D network)
  IPAddr.new("240.0.0.0/4"), # Reserved (former Class E network)
  IPAddr.new("255.255.255.255"), # Broadcast
].freeze
IPV6_BLACKLIST =
([
  IPAddr.new("::1/128"), # Loopback
  IPAddr.new("64:ff9b::/96"), # IPv4/IPv6 translation (RFC 6052)
  IPAddr.new("100::/64"), # Discard prefix (RFC 6666)
  IPAddr.new("2001::/32"), # Teredo tunneling
  IPAddr.new("2001:10::/28"), # Deprecated (previously ORCHID)
  IPAddr.new("2001:20::/28"), # ORCHIDv2
  IPAddr.new("2001:db8::/32"), # Addresses used in documentation and example source code
  IPAddr.new("2002::/16"), # 6to4
  IPAddr.new("fc00::/7"), # Unique local address
  IPAddr.new("fe80::/10"), # Link-local address
  IPAddr.new("ff00::/8"), # Multicast
] + IPV4_BLACKLIST.flat_map do |ipaddr|
  prefixlen = ipaddr.prefixlen

  ipv4_compatible = ipaddr.ipv4_compat.mask(96 + prefixlen)
  ipv4_mapped = ipaddr.ipv4_mapped.mask(80 + prefixlen)

  [ipv4_compatible, ipv4_mapped]
end).freeze

Class Method Summary collapse

Class Method Details

.extra_options(options) ⇒ Object



76
77
78
# File 'lib/httpx/plugins/ssrf_filter.rb', line 76

def extra_options(options)
  options.merge(allowed_schemes: %w[https http])
end

.unsafe_ip_address?(ipaddr) ⇒ Boolean

Returns:

  • (Boolean)


80
81
82
83
84
85
86
87
# File 'lib/httpx/plugins/ssrf_filter.rb', line 80

def unsafe_ip_address?(ipaddr)
  range = ipaddr.to_range
  return true if range.first != range.last

  return IPV6_BLACKLIST.any? { |r| r.include?(ipaddr) } if ipaddr.ipv6?

  IPV4_BLACKLIST.any? { |r| r.include?(ipaddr) } # then it's IPv4
end