rack-protection-monkey 1.5.3

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