ssrf_filter 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|