Class: SsrfFilter

Inherits:
Object
  • Object
show all
Defined in:
lib/ssrf_filter/version.rb,
lib/ssrf_filter/ssrf_filter.rb

Defined Under Namespace

Classes: CRLFInjection, CredentialLeakage, Error, InvalidUriScheme, PrivateIPAddress, TooManyRedirects, UnresolvedHostname

Constant Summary collapse

VERSION =
'1.6.0'
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.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
NAT64_LOCAL_PREFIX =

NAT64 local-use prefix (RFC 8215), uses RFC 6052 /48 encoding (checked at runtime).

::IPAddr.new('64:ff9b:1::/48').freeze
IPV6_BLACKLIST =
([
  ::IPAddr.new('::/128'), # Unspecified address
  ::IPAddr.new('::1/128'), # Loopback
  ::IPAddr.new('100::/64'), # Discard prefix (RFC 6666)
  ::IPAddr.new('100:0:0:1::/64'), # Dummy IPv6 prefix (RFC 9780)
  ::IPAddr.new('2001::/32'), # Teredo tunneling
  ::IPAddr.new('2001:2::/48'), # Benchmarking (RFC 5180)
  ::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('3fff::/20'), # Documentation (RFC 9637)
  ::IPAddr.new('5f00::/16'), # Segment Routing (SRv6) SIDs (RFC 9602)
  ::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 = prefixlen_from_ipaddr(ipaddr)

  # Don't call ipaddr.ipv4_compat because it prints out a deprecation warning on ruby 2.5+
  ipv4_compatible  = IPAddr.new(ipaddr.to_i, Socket::AF_INET6).mask(96 + prefixlen)
  ipv4_mapped      = ipaddr.ipv4_mapped.mask(80 + prefixlen)
  # IPv4-translated (RFC 2765): ::ffff:0:x.x.x.x/96+n
  ipv4_translated  = IPAddr.new("::ffff:0:#{ipaddr}").mask(96 + prefixlen)
  # NAT64 well-known prefix (RFC 6052): 64:ff9b::x.x.x.x/96+n
  nat64_well_known = IPAddr.new("64:ff9b::#{ipaddr}").mask(96 + prefixlen)

  [ipv4_compatible, ipv4_mapped, ipv4_translated, nat64_well_known]
end).freeze
DEFAULT_SCHEME_WHITELIST =
%w[http https].freeze
DEFAULT_RESOLVER =
proc do |hostname|
  ::Resolv.getaddresses(hostname).map { |ip| ::IPAddr.new(ip) }
end
DEFAULT_ALLOW_UNFOLLOWED_REDIRECTS =
false
DEFAULT_MAX_REDIRECTS =
10
DEFAULT_SENSITIVE_HEADERS =
%w[authorization cookie].freeze
DEFAULT_ON_CROSS_ORIGIN_REDIRECT =
:strip
CONNECTION_ERRORS =
[
  ::Errno::EHOSTUNREACH,
  ::Errno::ENETUNREACH,
  ::Errno::EADDRNOTAVAIL,
  ::Errno::ECONNREFUSED,
  ::Errno::ETIMEDOUT,
  ::Net::OpenTimeout
].freeze
VERB_MAP =
{
  get: ::Net::HTTP::Get,
  put: ::Net::HTTP::Put,
  post: ::Net::HTTP::Post,
  delete: ::Net::HTTP::Delete,
  head: ::Net::HTTP::Head,
  patch: ::Net::HTTP::Patch
}.freeze