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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68db49bb250c05d11655c0afe1913b34247d783c
4
- data.tar.gz: f1d11ee2913e121b3c996a1af745926a3da953e2
3
+ metadata.gz: 855ec5e3486aa13ddfebb55690b3e7d30f6148d2
4
+ data.tar.gz: 6df3da50c9087158e4cb2911a290ba694406e111
5
5
  SHA512:
6
- metadata.gz: 201bf113012c32ddb97e79df1fe9428d9dff43be894d340789a6b937f819e4538e680f8ec66e0d458a396ed7e082d1d20374d4b8c0fc0833970fb6b1d9a81bad
7
- data.tar.gz: 769532a2d3f68fe97a20a001d73fc930855dbdd7c1dbe4ac115c29e2f7661f509c3d89cbe21480a7630e503af7bb3bea7b4fedbb625fb2e51e5a08aa4a1a1dc4
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
- ].freeze
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
- request['host'] = hostname
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
@@ -1,3 +1,3 @@
1
1
  class SsrfFilter
2
- VERSION = '1.0.0'.freeze
2
+ VERSION = '1.0.1'.freeze
3
3
  end
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.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-25 00:00:00.000000000 Z
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.4.6
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