rack-protection 2.0.0.beta2 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

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: