rack-protection 2.0.0.beta2 → 2.0.0.rc1

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.

Potentially problematic release.


This version of rack-protection might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8577a28a79d48600a61b507f03677aab4a00e21
4
- data.tar.gz: e6db383a9598a41a22725c522e78e319a0236189
3
+ metadata.gz: 7866e19271188b3c5668af566e5d61f305d7ebfd
4
+ data.tar.gz: 3cbee3fe323d7dbf531741731cda60dfe76b451e
5
5
  SHA512:
6
- metadata.gz: 16061dd9bbf90d1dd9ccc30f0bfbb97df23c2abdcd6fbc02403579fd68ac369e35aff61ed789a2b780f4ee308409aa45f7a9c545e95f89da8daccd81b984b243
7
- data.tar.gz: 3a838ee68a0613f39fc4e524644eb1a5283a340b05604ad603b41086b293d3864389b97f534f4383f306f65cabd3024527eb0fe4c4df39a78e58a09ee37e8329
6
+ metadata.gz: d740e0613f51e92b942e33611f29f317dd197be142818724c67a06be9536dbdba2d1e7b890d0f7444db6c804e4e77d9f156ab392ab503481985bd7481e6d3beb
7
+ data.tar.gz: ca24a69a0ef6b19bb3087d6c60f70ff51043e3e8ab7da691ab2311d2d7da73129e24c5adacbd37ce9b9436ee8541f29b2c96d98b6276e8373f00d0754860ed08
@@ -12,65 +12,28 @@ module Rack
12
12
  # Only accepts unsafe HTTP requests if a given access token matches the token
13
13
  # included in the session.
14
14
  #
15
- # Compatible with Rails and rack-csrf.
15
+ # Compatible with rack-csrf.
16
16
  #
17
17
  # Options:
18
18
  #
19
19
  # authenticity_param: Defines the param's name that should contain the token on a request.
20
- #
21
20
  class AuthenticityToken < Base
21
+ TOKEN_LENGTH = 32
22
+
22
23
  default_options :authenticity_param => 'authenticity_token',
23
- :authenticity_token_length => 32,
24
24
  :allow_if => nil
25
25
 
26
- class << self
27
- def token(session)
28
- mask_token(session[:csrf])
29
- end
30
-
31
- def random_token(length = 32)
32
- SecureRandom.base64(length)
33
- end
34
-
35
- # Creates a masked version of the authenticity token that varies
36
- # on each request. The masking is used to mitigate SSL attacks
37
- # like BREACH.
38
- def mask_token(token)
39
- token = decode_token(token)
40
- one_time_pad = SecureRandom.random_bytes(token.length)
41
- encrypted_token = xor_byte_strings(one_time_pad, token)
42
- masked_token = one_time_pad + encrypted_token
43
- encode_token masked_token
44
- end
45
-
46
- # Essentially the inverse of +mask_token+.
47
- def unmask_decoded_token(masked_token)
48
- # Split the token into the one-time pad and the encrypted
49
- # value and decrypt it
50
- token_length = masked_token.length / 2
51
- one_time_pad = masked_token[0...token_length]
52
- encrypted_token = masked_token[token_length..-1]
53
- xor_byte_strings(one_time_pad, encrypted_token)
54
- end
55
-
56
- def encode_token(token)
57
- Base64.strict_encode64(token)
58
- end
59
-
60
- def decode_token(token)
61
- Base64.strict_decode64(token)
62
- end
63
-
64
- private
26
+ def self.token(session)
27
+ self.new(nil).mask_authenticity_token(session)
28
+ end
65
29
 
66
- def xor_byte_strings(s1, s2)
67
- s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
68
- end
30
+ def self.random_token
31
+ SecureRandom.base64(TOKEN_LENGTH)
69
32
  end
70
33
 
71
34
  def accepts?(env)
72
35
  session = session env
73
- session[:csrf] ||= self.class.random_token(token_length)
36
+ set_token(session)
74
37
 
75
38
  safe?(env) ||
76
39
  valid_token?(session, env['HTTP_X_CSRF_TOKEN']) ||
@@ -78,10 +41,15 @@ module Rack
78
41
  ( options[:allow_if] && options[:allow_if].call(env) )
79
42
  end
80
43
 
44
+ def mask_authenticity_token(session)
45
+ token = set_token(session)
46
+ mask_token(token)
47
+ end
48
+
81
49
  private
82
50
 
83
- def token_length
84
- options[:authenticity_token_length]
51
+ def set_token(session)
52
+ session[:csrf] ||= self.class.random_token
85
53
  end
86
54
 
87
55
  # Checks the client's masked token to see if it matches the
@@ -90,7 +58,7 @@ module Rack
90
58
  return false if token.nil? || token.empty?
91
59
 
92
60
  begin
93
- token = self.class.decode_token(token)
61
+ token = decode_token(token)
94
62
  rescue ArgumentError # encoded_masked_token is invalid Base64
95
63
  return false
96
64
  end
@@ -102,7 +70,7 @@ module Rack
102
70
  compare_with_real_token token, session
103
71
 
104
72
  elsif masked_token?(token)
105
- token = self.class.unmask_decoded_token(token)
73
+ token = unmask_token(token)
106
74
 
107
75
  compare_with_real_token token, session
108
76
 
@@ -111,12 +79,33 @@ module Rack
111
79
  end
112
80
  end
113
81
 
82
+ # Creates a masked version of the authenticity token that varies
83
+ # on each request. The masking is used to mitigate SSL attacks
84
+ # like BREACH.
85
+ def mask_token(token)
86
+ token = decode_token(token)
87
+ one_time_pad = SecureRandom.random_bytes(token.length)
88
+ encrypted_token = xor_byte_strings(one_time_pad, token)
89
+ masked_token = one_time_pad + encrypted_token
90
+ encode_token(masked_token)
91
+ end
92
+
93
+ # Essentially the inverse of +mask_token+.
94
+ def unmask_token(masked_token)
95
+ # Split the token into the one-time pad and the encrypted
96
+ # value and decrypt it
97
+ token_length = masked_token.length / 2
98
+ one_time_pad = masked_token[0...token_length]
99
+ encrypted_token = masked_token[token_length..-1]
100
+ xor_byte_strings(one_time_pad, encrypted_token)
101
+ end
102
+
114
103
  def unmasked_token?(token)
115
- token.length == token_length
104
+ token.length == TOKEN_LENGTH
116
105
  end
117
106
 
118
107
  def masked_token?(token)
119
- token.length == token_length * 2
108
+ token.length == TOKEN_LENGTH * 2
120
109
  end
121
110
 
122
111
  def compare_with_real_token(token, session)
@@ -124,7 +113,19 @@ module Rack
124
113
  end
125
114
 
126
115
  def real_token(session)
127
- self.class.decode_token(session[:csrf])
116
+ decode_token(session[:csrf])
117
+ end
118
+
119
+ def encode_token(token)
120
+ Base64.strict_encode64(token)
121
+ end
122
+
123
+ def decode_token(token)
124
+ Base64.strict_decode64(token)
125
+ end
126
+
127
+ def xor_byte_strings(s1, s2)
128
+ s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
128
129
  end
129
130
  end
130
131
  end
@@ -13,7 +13,7 @@ module Rack
13
13
  # This middleware is not used when using the Rack::Protection collection,
14
14
  # since it might be a security issue, depending on your application
15
15
  #
16
- # Compatible with Rails and rack-csrf.
16
+ # Compatible with rack-csrf.
17
17
  class FormToken < AuthenticityToken
18
18
  def accepts?(env)
19
19
  env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" or super
@@ -10,7 +10,7 @@ module Rack
10
10
  # Only accepts unsafe HTTP requests if a given access token matches the token
11
11
  # included in the session *or* the request comes from the same origin.
12
12
  #
13
- # Compatible with Rails and rack-csrf.
13
+ # Compatible with rack-csrf.
14
14
  class RemoteToken < AuthenticityToken
15
15
  default_reaction :deny
16
16
 
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Protection
3
- VERSION = "2.0.0.beta2"
3
+ VERSION = "2.0.0.rc1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-protection
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta2
4
+ version: 2.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Haase
@@ -41,7 +41,7 @@ authors:
41
41
  autorequire:
42
42
  bindir: bin
43
43
  cert_chain: []
44
- date: 2016-08-22 00:00:00.000000000 Z
44
+ date: 2017-03-04 00:00:00.000000000 Z
45
45
  dependencies:
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rack
@@ -141,4 +141,3 @@ specification_version: 4
141
141
  summary: Protect against typical web attacks, works with all Rack apps, including
142
142
  Rails.
143
143
  test_files: []
144
- has_rdoc: