ssrf_filter 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ssrf_filter/ssrf_filter.rb +28 -11
- data/lib/ssrf_filter/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 855ec5e3486aa13ddfebb55690b3e7d30f6148d2
|
4
|
+
data.tar.gz: 6df3da50c9087158e4cb2911a290ba694406e111
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac67704b7c90ba7c2b7a43b94e1d2a7f9230776f5754e195cc74076abe1a0e90c2cfa05b43fe5d8d7da40359729e7df056f15f6c00b16763e37c8f8e5e6d30a9
|
7
|
+
data.tar.gz: 0f0f93dc6016603c49d151006c70564f9eb9dfc60ddbe4cd28b537f091ae4ba0b4830739987e70d9deaff307a18a2c0f5f89a19c5cb6ca10188c1b1002728b5a
|
@@ -4,6 +4,22 @@ require 'resolv'
|
|
4
4
|
require 'uri'
|
5
5
|
|
6
6
|
class SsrfFilter
|
7
|
+
def self.prefixlen_from_ipaddr(ipaddr)
|
8
|
+
mask_addr = ipaddr.instance_variable_get('@mask_addr')
|
9
|
+
raise ArgumentError, 'Invalid mask' if mask_addr.zero?
|
10
|
+
|
11
|
+
mask_addr >>= 1 while (mask_addr & 0x1).zero?
|
12
|
+
|
13
|
+
length = 0
|
14
|
+
while mask_addr & 0x1 == 0x1
|
15
|
+
length += 1
|
16
|
+
mask_addr >>= 1
|
17
|
+
end
|
18
|
+
|
19
|
+
length
|
20
|
+
end
|
21
|
+
private_class_method :prefixlen_from_ipaddr
|
22
|
+
|
7
23
|
# https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
8
24
|
IPV4_BLACKLIST = [
|
9
25
|
::IPAddr.new('0.0.0.0/8'), # Current network (only valid as source address)
|
@@ -24,7 +40,7 @@ class SsrfFilter
|
|
24
40
|
::IPAddr.new('255.255.255.255') # Broadcast
|
25
41
|
].freeze
|
26
42
|
|
27
|
-
IPV6_BLACKLIST = [
|
43
|
+
IPV6_BLACKLIST = ([
|
28
44
|
::IPAddr.new('::1/128'), # Loopback
|
29
45
|
::IPAddr.new('64:ff9b::/96'), # IPv4/IPv6 translation (RFC 6052)
|
30
46
|
::IPAddr.new('100::/64'), # Discard prefix (RFC 6666)
|
@@ -36,7 +52,14 @@ class SsrfFilter
|
|
36
52
|
::IPAddr.new('fc00::/7'), # Unique local address
|
37
53
|
::IPAddr.new('fe80::/10'), # Link-local address
|
38
54
|
::IPAddr.new('ff00::/8'), # Multicast
|
39
|
-
].
|
55
|
+
] + IPV4_BLACKLIST.flat_map do |ipaddr|
|
56
|
+
prefixlen = prefixlen_from_ipaddr(ipaddr)
|
57
|
+
|
58
|
+
ipv4_compatible = ipaddr.ipv4_compat.mask(96 + prefixlen)
|
59
|
+
ipv4_mapped = ipaddr.ipv4_mapped.mask(80 + prefixlen)
|
60
|
+
|
61
|
+
[ipv4_compatible, ipv4_mapped]
|
62
|
+
end).freeze
|
40
63
|
|
41
64
|
DEFAULT_SCHEME_WHITELIST = %w[http https].freeze
|
42
65
|
|
@@ -110,14 +133,7 @@ class SsrfFilter
|
|
110
133
|
return true if ipaddr_has_mask?(ip_address)
|
111
134
|
|
112
135
|
return IPV4_BLACKLIST.any? { |range| range.include?(ip_address) } if ip_address.ipv4?
|
113
|
-
|
114
|
-
if ip_address.ipv6?
|
115
|
-
result = IPV6_BLACKLIST.any? { |range| range.include?(ip_address) }
|
116
|
-
# TODO: convert these to be members of IPV6_BLACKLIST
|
117
|
-
result ||= ip_address.ipv4_compat? && IPV4_BLACKLIST.any? { |range| range.include?(ip_address.ipv4_compat) }
|
118
|
-
result ||= ip_address.ipv4_mapped? && IPV4_BLACKLIST.any? { |range| range.include?(ip_address.ipv4_mapped) }
|
119
|
-
return result
|
120
|
-
end
|
136
|
+
return IPV6_BLACKLIST.any? { |range| range.include?(ip_address) } if ip_address.ipv6?
|
121
137
|
|
122
138
|
true
|
123
139
|
end
|
@@ -140,7 +156,8 @@ class SsrfFilter
|
|
140
156
|
uri.hostname = ip
|
141
157
|
|
142
158
|
request = VERB_MAP[verb].new(uri)
|
143
|
-
|
159
|
+
# Attach port for non-80 as per RFC2616
|
160
|
+
request['host'] = uri.port == 80 ? hostname : "#{hostname}:#{uri.port}"
|
144
161
|
|
145
162
|
Array(options[:headers]).each do |header, value|
|
146
163
|
request[header] = value
|
data/lib/ssrf_filter/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssrf_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkadiy Tetelman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler-audit
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.4'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
124
|
version: '0'
|
111
125
|
requirements: []
|
112
126
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.
|
127
|
+
rubygems_version: 2.6.12
|
114
128
|
signing_key:
|
115
129
|
specification_version: 4
|
116
130
|
summary: A gem that makes it easy to prevent server side request forgery (SSRF) attacks
|