brakeman-min 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/brakeman CHANGED
@@ -34,6 +34,10 @@ OptionParser.new do |opts|
34
34
  options[:ignore_model_output] = true
35
35
  end
36
36
 
37
+ opts.on "-e", "--escape-html", "Escape HTML by default" do
38
+ options[:escape_html] = true
39
+ end
40
+
37
41
  opts.on "-r", "--report-direct", "Only report direct use of untrusted data" do |option|
38
42
  options[:check_arguments] = !option
39
43
  end
@@ -30,6 +30,8 @@ class CheckCrossSiteScripting < BaseCheck
30
30
 
31
31
  HAML_HELPERS = Sexp.new(:colon2, Sexp.new(:const, :Haml), :Helpers)
32
32
 
33
+ XML_HELPER = Sexp.new(:colon2, Sexp.new(:const, :Erubis), :XmlHelper)
34
+
33
35
  URI = Sexp.new(:const, :URI)
34
36
 
35
37
  CGI = Sexp.new(:const, :CGI)
@@ -48,7 +50,7 @@ class CheckCrossSiteScripting < BaseCheck
48
50
  @current_template = template
49
51
 
50
52
  template[:outputs].each do |out|
51
- type, match = has_immediate_user_input?(out[1])
53
+ type, match = (out[0] == :output and has_immediate_user_input?(out[1]))
52
54
  if type and not duplicate? out
53
55
  add_result out
54
56
  case type
@@ -102,6 +104,16 @@ class CheckCrossSiteScripting < BaseCheck
102
104
  process exp[1].dup
103
105
  end
104
106
 
107
+ #Look for calls to raw()
108
+ #Otherwise, ignore
109
+ def process_escaped_output exp
110
+ if exp[1].node_type == :call and exp[1][2] == :raw
111
+ process_output exp
112
+ else
113
+ exp
114
+ end
115
+ end
116
+
105
117
  #Check a call for user input
106
118
  #
107
119
  #
@@ -154,6 +166,7 @@ class CheckCrossSiteScripting < BaseCheck
154
166
  (@matched == :model and IGNORE_MODEL_METHODS.include? method) or
155
167
  (target == HAML_HELPERS and method == :html_escape) or
156
168
  ((target == URI or target == CGI) and method == :escape) or
169
+ (target == XML_HELPER and method == :escape_xml) or
157
170
  (target == FORM_BUILDER and IGNORE_METHODS.include? method) or
158
171
  (method.to_s[-1,1] == "?")
159
172
 
@@ -163,7 +176,6 @@ class CheckCrossSiteScripting < BaseCheck
163
176
 
164
177
  @matched = :model
165
178
  elsif @inspect_arguments and (ALL_PARAMETERS.include?(exp) or params? exp)
166
-
167
179
  @matched = :params
168
180
  elsif @inspect_arguments
169
181
  process args
data/lib/processor.rb CHANGED
@@ -50,6 +50,8 @@ class Processor
50
50
  result = ErbTemplateProcessor.new(@tracker, name, called_from, file_name).process src
51
51
  when :haml
52
52
  result = HamlTemplateProcessor.new(@tracker, name, called_from, file_name).process src
53
+ when :erubis
54
+ result = ErubisTemplateProcessor.new(@tracker, name, called_from, file_name).process src
53
55
  else
54
56
  abort "Unknown template type: #{type} (#{name})"
55
57
  end
@@ -2,6 +2,7 @@ require 'processors/template_processor'
2
2
 
3
3
  #Processes ERB templates using Erubis instead of erb.
4
4
  class ErubisTemplateProcessor < TemplateProcessor
5
+
5
6
 
6
7
  #s(:call, TARGET, :method, s(:arglist))
7
8
  def process_call exp
@@ -10,10 +11,10 @@ class ErubisTemplateProcessor < TemplateProcessor
10
11
  target = process target
11
12
  end
12
13
  method = exp[2]
13
-
14
+
14
15
  #_buf is the default output variable for Erubis
15
- if target and target[1] == :_buf
16
- if method == :<<
16
+ if target and (target[1] == :_buf or target[1] == :output_buffer)
17
+ if method == :<< or method == :safe_concat
17
18
  args = exp[3][1] = process(exp[3][1])
18
19
 
19
20
  if args.node_type == :call and args[2] == :to_s #just calling to_s on inner code
@@ -59,4 +60,26 @@ class ErubisTemplateProcessor < TemplateProcessor
59
60
  block.line(exp.line)
60
61
  block
61
62
  end
63
+
64
+ #Look for assignments to output buffer
65
+ def process_attrasgn exp
66
+ if exp[1].node_type == :ivar and exp[1][1] == :@output_buffer
67
+ if exp[2] == :append= or exp[2] == :safe_append=
68
+ args = exp[3][1] = process(exp[3][1])
69
+
70
+ if args.node_type == :str
71
+ ignore
72
+ else
73
+ s = Sexp.new :escaped_output, args
74
+ s.line(exp.line)
75
+ @current_template[:outputs] << s
76
+ s
77
+ end
78
+ else
79
+ ignore
80
+ end
81
+ else
82
+ super
83
+ end
84
+ end
62
85
  end
@@ -153,6 +153,23 @@ class OutputProcessor < Ruby2Ruby
153
153
  out
154
154
  end
155
155
 
156
+ def process_escaped_output exp
157
+ out = if exp[0].node_type == :str
158
+ ""
159
+ else
160
+ res = process exp[0]
161
+
162
+ if res == ""
163
+ ""
164
+ else
165
+ "[Escaped Output] #{res}"
166
+ end
167
+ end
168
+ exp.clear
169
+ out
170
+ end
171
+
172
+
156
173
  def process_format exp
157
174
  out = if exp[0].node_type == :str or exp[0].node_type == :ignore
158
175
  ""
data/lib/scanner.rb CHANGED
@@ -53,7 +53,9 @@ class Scanner
53
53
  @processor.process_config(RubyParser.new.parse(File.read("#@path/config/gems.rb")))
54
54
  end
55
55
 
56
- if File.exists? "#@path/vendor/plugins/rails_xss" or OPTIONS[:rails3]
56
+ if File.exists? "#@path/vendor/plugins/rails_xss" or
57
+ OPTIONS[:rails3] or OPTIONS[:escape_html] or
58
+ (File.exists? "#@path/Gemfile" and File.read("#@path/Gemfile").include? "rails_xss")
57
59
  tracker.config[:escape_html] = true
58
60
  warn "[Notice] Escaping HTML by default"
59
61
  end
@@ -139,10 +141,17 @@ class Scanner
139
141
  if type == :erb
140
142
  if tracker.config[:escape_html]
141
143
  initialize_erubis unless @initialized_erubis
142
- src = RailsXSSErubis.new(File.read(f)).src
144
+ type = :erubis
145
+ if OPTIONS[:rails3]
146
+ src = RailsXSSErubis.new(File.read(f)).src
147
+ else
148
+ src = ErubisEscape.new(File.read(f)).src
149
+ end
143
150
  elsif tracker.config[:erubis]
144
151
  initialize_erubis unless @initialized_erubis
145
152
  src = ScannerErubis.new(File.read(f)).src
153
+ type = :erubis
154
+ src = ScannerErubis.new(File.read(f)).src
146
155
  else
147
156
  src = ERB.new(File.read(f), nil, "-").src
148
157
  end
@@ -6,34 +6,49 @@ rescue LoadError => e
6
6
  exit!
7
7
  end
8
8
 
9
- #This is from the rails_xss plugin,
10
- #except we don't care about plain text.
9
+ #This is from Rails 3 version of the Erubis handler
11
10
  class RailsXSSErubis < ::Erubis::Eruby
12
11
  include Erubis::NoTextEnhancer
13
12
 
14
13
  #Initializes output buffer.
15
14
  def add_preamble(src)
16
- src << "@output_buffer = ActionView::SafeBuffer.new;\n"
15
+ # src << "_buf = ActionView::SafeBuffer.new;\n"
17
16
  end
18
17
 
19
18
  #This does nothing.
20
19
  def add_text(src, text)
21
- # src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
20
+ # src << "@output_buffer << ('" << escape_text(text) << "'.html_safe!);"
22
21
  end
23
22
 
24
- #Add an expression to the output buffer _without_ escaping.
23
+ BLOCK_EXPR = /\s+(do|\{)(\s*\|[^|]*\|)?\s*\Z/
24
+
25
25
  def add_expr_literal(src, code)
26
- src << '@output_buffer << ((' << code << ').to_s);'
26
+ if code =~ BLOCK_EXPR
27
+ src << '@output_buffer.append= ' << code
28
+ else
29
+ src << '@output_buffer.append= (' << code << ');'
30
+ end
31
+ end
32
+
33
+ def add_stmt(src, code)
34
+ if code =~ BLOCK_EXPR
35
+ src << '@output_buffer.append_if_string= ' << code
36
+ else
37
+ super
38
+ end
27
39
  end
28
40
 
29
- #Add an expression to the output buffer after escaping it.
30
41
  def add_expr_escaped(src, code)
31
- src << '@output_buffer << ' << escaped_expr(code) << ';'
42
+ if code =~ BLOCK_EXPR
43
+ src << "@output_buffer.safe_append= " << code
44
+ else
45
+ src << "@output_buffer.safe_concat(" << code << ");"
46
+ end
32
47
  end
33
48
 
34
49
  #Add code to output buffer.
35
50
  def add_postamble(src)
36
- src << '@output_buffer.to_s'
51
+ # src << '_buf.to_s'
37
52
  end
38
53
  end
39
54
 
@@ -41,3 +56,8 @@ end
41
56
  class ScannerErubis < Erubis::Eruby
42
57
  include Erubis::NoTextEnhancer
43
58
  end
59
+
60
+ class ErubisEscape < ScannerErubis
61
+ include Erubis::EscapeEnhancer
62
+ end
63
+
data/lib/version.rb CHANGED
@@ -1 +1 @@
1
- Version = "0.3.2"
1
+ Version = "0.4.0"
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
8
- - 2
9
- version: 0.3.2
7
+ - 4
8
+ - 0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Justin Collins
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-05-12 00:00:00 -07:00
17
+ date: 2011-05-18 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency