rack-protection-monkey 1.5.3

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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/License +20 -0
  3. data/README.md +90 -0
  4. data/Rakefile +48 -0
  5. data/lib/rack-protection.rb +1 -0
  6. data/lib/rack/protection.rb +40 -0
  7. data/lib/rack/protection/authenticity_token.rb +31 -0
  8. data/lib/rack/protection/base.rb +121 -0
  9. data/lib/rack/protection/escaped_params.rb +87 -0
  10. data/lib/rack/protection/form_token.rb +23 -0
  11. data/lib/rack/protection/frame_options.rb +37 -0
  12. data/lib/rack/protection/http_origin.rb +34 -0
  13. data/lib/rack/protection/ip_spoofing.rb +23 -0
  14. data/lib/rack/protection/json_csrf.rb +35 -0
  15. data/lib/rack/protection/path_traversal.rb +47 -0
  16. data/lib/rack/protection/remote_referrer.rb +20 -0
  17. data/lib/rack/protection/remote_token.rb +22 -0
  18. data/lib/rack/protection/session_hijacking.rb +36 -0
  19. data/lib/rack/protection/version.rb +16 -0
  20. data/lib/rack/protection/xss_header.rb +25 -0
  21. data/rack-protection.gemspec +123 -0
  22. data/spec/lib/rack/protection/authenticity_token_spec.rb +46 -0
  23. data/spec/lib/rack/protection/base_spec.rb +38 -0
  24. data/spec/lib/rack/protection/escaped_params_spec.rb +41 -0
  25. data/spec/lib/rack/protection/form_token_spec.rb +31 -0
  26. data/spec/lib/rack/protection/frame_options_spec.rb +37 -0
  27. data/spec/lib/rack/protection/http_origin_spec.rb +40 -0
  28. data/spec/lib/rack/protection/ip_spoofing_spec.rb +33 -0
  29. data/spec/lib/rack/protection/json_csrf_spec.rb +56 -0
  30. data/spec/lib/rack/protection/path_traversal_spec.rb +39 -0
  31. data/spec/lib/rack/protection/protection_spec.rb +103 -0
  32. data/spec/lib/rack/protection/remote_referrer_spec.rb +29 -0
  33. data/spec/lib/rack/protection/remote_token_spec.rb +40 -0
  34. data/spec/lib/rack/protection/session_hijacking_spec.rb +53 -0
  35. data/spec/lib/rack/protection/xss_header_spec.rb +54 -0
  36. data/spec/spec_helper.rb +86 -0
  37. data/spec/support/dummy_app.rb +7 -0
  38. data/spec/support/not_implemented_as_pending.rb +23 -0
  39. data/spec/support/rack_monkey_patches.rb +21 -0
  40. data/spec/support/shared_examples.rb +65 -0
  41. data/spec/support/spec_helpers.rb +36 -0
  42. metadata +180 -0
@@ -0,0 +1,23 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: CSRF
7
+ # Supported browsers:: all
8
+ # More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
9
+ #
10
+ # Only accepts submitted forms if a given access token matches the token
11
+ # included in the session. Does not expect such a token from Ajax request.
12
+ #
13
+ # This middleware is not used when using the Rack::Protection collection,
14
+ # since it might be a security issue, depending on your application
15
+ #
16
+ # Compatible with Rails and rack-csrf.
17
+ class FormToken < AuthenticityToken
18
+ def accepts?(env)
19
+ env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" or super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: Clickjacking
7
+ # Supported browsers:: Internet Explorer 8, Firefox 3.6.9, Opera 10.50,
8
+ # Safari 4.0, Chrome 4.1.249.1042 and later
9
+ # More infos:: https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header
10
+ #
11
+ # Sets X-Frame-Options header to tell the browser avoid embedding the page
12
+ # in a frame.
13
+ #
14
+ # Options:
15
+ #
16
+ # frame_options:: Defines who should be allowed to embed the page in a
17
+ # frame. Use :deny to forbid any embedding, :sameorigin
18
+ # to allow embedding from the same origin (default).
19
+ class FrameOptions < Base
20
+ default_options :frame_options => :sameorigin
21
+
22
+ def frame_options
23
+ @frame_options ||= begin
24
+ frame_options = options[:frame_options]
25
+ frame_options = options[:frame_options].to_s.upcase unless frame_options.respond_to? :to_str
26
+ frame_options.to_str
27
+ end
28
+ end
29
+
30
+ def call(env)
31
+ status, headers, body = @app.call(env)
32
+ headers['X-Frame-Options'] ||= frame_options if html? headers
33
+ [status, headers, body]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,34 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: CSRF
7
+ # Supported browsers:: Google Chrome 2, Safari 4 and later
8
+ # More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
9
+ # http://tools.ietf.org/html/draft-abarth-origin
10
+ #
11
+ # Does not accept unsafe HTTP requests when value of Origin HTTP request header
12
+ # does not match default or whitelisted URIs.
13
+ class HttpOrigin < Base
14
+ DEFAULT_PORTS = { 'http' => 80, 'https' => 443, 'coffee' => 80 }
15
+ default_reaction :deny
16
+
17
+ def base_url(env)
18
+ request = Rack::Request.new(env)
19
+ port = ":#{request.port}" unless request.port == DEFAULT_PORTS[request.scheme]
20
+ "#{request.scheme}://#{request.host}#{port}"
21
+ end
22
+
23
+ def accepts?(env)
24
+ origin = env['HTTP_ORIGIN']
25
+
26
+ return true if safe? env
27
+ return true unless origin && origin != 'null'
28
+ return true if base_url(env) == origin
29
+ Array(options[:origin_whitelist]).include? origin
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: IP spoofing
7
+ # Supported browsers:: all
8
+ # More infos:: http://blog.c22.cc/2011/04/22/surveymonkey-ip-spoofing/
9
+ #
10
+ # Detect (some) IP spoofing attacks.
11
+ class IPSpoofing < Base
12
+ default_reaction :deny
13
+
14
+ def accepts?(env)
15
+ return true unless env.include? 'HTTP_X_FORWARDED_FOR'
16
+ ips = env['HTTP_X_FORWARDED_FOR'].split(/\s*,\s*/)
17
+ return false if env.include? 'HTTP_CLIENT_IP' and not ips.include? env['HTTP_CLIENT_IP']
18
+ return false if env.include? 'HTTP_X_REAL_IP' and not ips.include? env['HTTP_X_REAL_IP']
19
+ true
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: CSRF
7
+ # Supported browsers:: all
8
+ # More infos:: http://flask.pocoo.org/docs/security/#json-security
9
+ #
10
+ # JSON GET APIs are vulnerable to being embedded as JavaScript while the
11
+ # Array prototype has been patched to track data. Checks the referrer
12
+ # even on GET requests if the content type is JSON.
13
+ class JsonCsrf < Base
14
+ alias react deny
15
+
16
+ def call(env)
17
+ request = Request.new(env)
18
+ status, headers, body = app.call(env)
19
+
20
+ if has_vector? request, headers
21
+ warn env, "attack prevented by #{self.class}"
22
+ react(env) or [status, headers, body]
23
+ else
24
+ [status, headers, body]
25
+ end
26
+ end
27
+
28
+ def has_vector?(request, headers)
29
+ return false if request.xhr?
30
+ return false unless headers['Content-Type'].to_s.split(';', 2).first =~ /^\s*application\/json\s*$/
31
+ origin(request.env).nil? and referrer(request.env) != request.host
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,47 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: Directory traversal
7
+ # Supported browsers:: all
8
+ # More infos:: http://en.wikipedia.org/wiki/Directory_traversal
9
+ #
10
+ # Unescapes '/' and '.', expands +path_info+.
11
+ # Thus <tt>GET /foo/%2e%2e%2fbar</tt> becomes <tt>GET /bar</tt>.
12
+ class PathTraversal < Base
13
+ def call(env)
14
+ path_was = env["PATH_INFO"]
15
+ env["PATH_INFO"] = cleanup path_was if path_was && !path_was.empty?
16
+ app.call env
17
+ ensure
18
+ env["PATH_INFO"] = path_was
19
+ end
20
+
21
+ def cleanup(path)
22
+ if path.respond_to?(:encoding)
23
+ # Ruby 1.9+ M17N
24
+ encoding = path.encoding
25
+ dot = '.'.encode(encoding)
26
+ slash = '/'.encode(encoding)
27
+ else
28
+ # Ruby 1.8
29
+ dot = '.'
30
+ slash = '/'
31
+ end
32
+
33
+ parts = []
34
+ unescaped = path.gsub(/%2e/i, dot).gsub(/%2f/i, slash)
35
+
36
+ unescaped.split(slash).each do |part|
37
+ next if part.empty? or part == dot
38
+ part == '..' ? parts.pop : parts << part
39
+ end
40
+
41
+ cleaned = slash + parts.join(slash)
42
+ cleaned << slash if parts.any? and unescaped =~ %r{/\.{0,2}$}
43
+ cleaned
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: CSRF
7
+ # Supported browsers:: all
8
+ # More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
9
+ #
10
+ # Does not accept unsafe HTTP requests if the Referer [sic] header is set to
11
+ # a different host.
12
+ class RemoteReferrer < Base
13
+ default_reaction :deny
14
+
15
+ def accepts?(env)
16
+ safe?(env) or referrer(env) == Request.new(env).host
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: CSRF
7
+ # Supported browsers:: all
8
+ # More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
9
+ #
10
+ # Only accepts unsafe HTTP requests if a given access token matches the token
11
+ # included in the session *or* the request comes from the same origin.
12
+ #
13
+ # Compatible with Rails and rack-csrf.
14
+ class RemoteToken < AuthenticityToken
15
+ default_reaction :deny
16
+
17
+ def accepts?(env)
18
+ super or referrer(env) == Request.new(env).host
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: Session Hijacking
7
+ # Supported browsers:: all
8
+ # More infos:: http://en.wikipedia.org/wiki/Session_hijacking
9
+ #
10
+ # Tracks request properties like the user agent in the session and empties
11
+ # the session if those properties change. This essentially prevents attacks
12
+ # from Firesheep. Since all headers taken into consideration can be
13
+ # spoofed, too, this will not prevent determined hijacking attempts.
14
+ class SessionHijacking < Base
15
+ default_reaction :drop_session
16
+ default_options :tracking_key => :tracking, :encrypt_tracking => true,
17
+ :track => %w[HTTP_USER_AGENT HTTP_ACCEPT_LANGUAGE]
18
+
19
+ def accepts?(env)
20
+ session = session env
21
+ key = options[:tracking_key]
22
+ if session.include? key
23
+ session[key].all? { |k,v| v == encrypt(env[k]) }
24
+ else
25
+ session[key] = {}
26
+ options[:track].each { |k| session[key][k] = encrypt(env[k]) }
27
+ end
28
+ end
29
+
30
+ def encrypt(value)
31
+ value = value.to_s.downcase
32
+ options[:encrypt_tracking] ? super(value) : value
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ module Rack
2
+ module Protection
3
+ def self.version
4
+ VERSION
5
+ end
6
+
7
+ SIGNATURE = [1, 5, 3]
8
+ VERSION = SIGNATURE.join('.')
9
+
10
+ VERSION.extend Comparable
11
+ def VERSION.<=>(other)
12
+ other = other.split('.').map { |i| i.to_i } if other.respond_to? :split
13
+ SIGNATURE <=> Array(other)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: Non-permanent XSS
7
+ # Supported browsers:: Internet Explorer 8 and later
8
+ # More infos:: http://blogs.msdn.com/b/ie/archive/2008/07/01/ie8-security-part-iv-the-xss-filter.aspx
9
+ #
10
+ # Sets X-XSS-Protection header to tell the browser to block attacks.
11
+ #
12
+ # Options:
13
+ # xss_mode:: How the browser should prevent the attack (default: :block)
14
+ class XSSHeader < Base
15
+ default_options :xss_mode => :block, :nosniff => true
16
+
17
+ def call(env)
18
+ status, headers, body = @app.call(env)
19
+ headers['X-XSS-Protection'] ||= "1; mode=#{options[:xss_mode]}" if html? headers
20
+ headers['X-Content-Type-Options'] ||= 'nosniff' if options[:nosniff]
21
+ [status, headers, body]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,123 @@
1
+ # Run `rake rack-protection.gemspec` to update the gemspec.
2
+ Gem::Specification.new do |s|
3
+ # general infos
4
+ s.name = "rack-protection-monkey"
5
+ s.version = "1.5.3"
6
+ s.description = "You should use protection! - Monkey Version"
7
+ s.homepage = "http://github.com/sinatra/rack-protection"
8
+ s.summary = s.description
9
+ s.license = 'MIT'
10
+
11
+ # generated from git shortlog -sn
12
+ s.authors = [
13
+ "Konstantin Haase",
14
+ "Alex Rodionov",
15
+ "Patrick Ellis",
16
+ "Jason Staten",
17
+ "ITO Nobuaki",
18
+ "Jeff Welling",
19
+ "Matteo Centenaro",
20
+ "Egor Homakov",
21
+ "Florian Gilcher",
22
+ "Fojas",
23
+ "Igor Bochkariov",
24
+ "Mael Clerambault",
25
+ "Martin Mauch",
26
+ "Renne Nissinen",
27
+ "SAKAI, Kazuaki",
28
+ "Stanislav Savulchik",
29
+ "Steve Agalloco",
30
+ "TOBY",
31
+ "Thais Camilo and Konstantin Haase",
32
+ "Vipul A M",
33
+ "Akzhan Abdulin",
34
+ "brookemckim",
35
+ "Bj\u{f8}rge N\u{e6}ss",
36
+ "Chris Heald",
37
+ "Chris Mytton",
38
+ "Corey Ward",
39
+ "Dario Cravero",
40
+ "David Kellum"
41
+ ]
42
+
43
+ # generated from git shortlog -sne
44
+ s.email = [
45
+ "konstantin.mailinglists@googlemail.com",
46
+ "p0deje@gmail.com",
47
+ "jstaten07@gmail.com",
48
+ "patrick@soundcloud.com",
49
+ "jeff.welling@gmail.com",
50
+ "bugant@gmail.com",
51
+ "daydream.trippers@gmail.com",
52
+ "florian.gilcher@asquera.de",
53
+ "developer@fojasaur.us",
54
+ "ujifgc@gmail.com",
55
+ "mael@clerambault.fr",
56
+ "martin.mauch@gmail.com",
57
+ "rennex@iki.fi",
58
+ "kaz.july.7@gmail.com",
59
+ "s.savulchik@gmail.com",
60
+ "steve.agalloco@gmail.com",
61
+ "toby.net.info.mail+git@gmail.com",
62
+ "dev+narwen+rkh@rkh.im",
63
+ "vipulnsward@gmail.com",
64
+ "akzhan.abdulin@gmail.com",
65
+ "brooke@digitalocean.com",
66
+ "bjoerge@bengler.no",
67
+ "cheald@gmail.com",
68
+ "self@hecticjeff.net",
69
+ "coreyward@me.com",
70
+ "dario@uxtemple.com",
71
+ "dek-oss@gravitext.com",
72
+ "homakov@gmail.com"
73
+ ]
74
+
75
+ # generated from git ls-files
76
+ s.files = [
77
+ "License",
78
+ "README.md",
79
+ "Rakefile",
80
+ "lib/rack-protection.rb",
81
+ "lib/rack/protection.rb",
82
+ "lib/rack/protection/authenticity_token.rb",
83
+ "lib/rack/protection/base.rb",
84
+ "lib/rack/protection/escaped_params.rb",
85
+ "lib/rack/protection/form_token.rb",
86
+ "lib/rack/protection/frame_options.rb",
87
+ "lib/rack/protection/http_origin.rb",
88
+ "lib/rack/protection/ip_spoofing.rb",
89
+ "lib/rack/protection/json_csrf.rb",
90
+ "lib/rack/protection/path_traversal.rb",
91
+ "lib/rack/protection/remote_referrer.rb",
92
+ "lib/rack/protection/remote_token.rb",
93
+ "lib/rack/protection/session_hijacking.rb",
94
+ "lib/rack/protection/version.rb",
95
+ "lib/rack/protection/xss_header.rb",
96
+ "rack-protection.gemspec",
97
+ "spec/lib/rack/protection/authenticity_token_spec.rb",
98
+ "spec/lib/rack/protection/base_spec.rb",
99
+ "spec/lib/rack/protection/escaped_params_spec.rb",
100
+ "spec/lib/rack/protection/form_token_spec.rb",
101
+ "spec/lib/rack/protection/frame_options_spec.rb",
102
+ "spec/lib/rack/protection/http_origin_spec.rb",
103
+ "spec/lib/rack/protection/ip_spoofing_spec.rb",
104
+ "spec/lib/rack/protection/json_csrf_spec.rb",
105
+ "spec/lib/rack/protection/path_traversal_spec.rb",
106
+ "spec/lib/rack/protection/protection_spec.rb",
107
+ "spec/lib/rack/protection/remote_referrer_spec.rb",
108
+ "spec/lib/rack/protection/remote_token_spec.rb",
109
+ "spec/lib/rack/protection/session_hijacking_spec.rb",
110
+ "spec/lib/rack/protection/xss_header_spec.rb",
111
+ "spec/spec_helper.rb",
112
+ "spec/support/dummy_app.rb",
113
+ "spec/support/not_implemented_as_pending.rb",
114
+ "spec/support/rack_monkey_patches.rb",
115
+ "spec/support/shared_examples.rb",
116
+ "spec/support/spec_helpers.rb"
117
+ ]
118
+
119
+ # dependencies
120
+ s.add_dependency "rack"
121
+ s.add_development_dependency "rack-test"
122
+ s.add_development_dependency "rspec", "~> 3.0.0"
123
+ end