codesake-dawn 0.60 → 0.70

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 (47) hide show
  1. data/.gitignore +1 -0
  2. data/Competitive_matrix.md +18 -4
  3. data/README.md +26 -44
  4. data/Roadmap.md +25 -11
  5. data/bin/dawn +104 -34
  6. data/{codesake_dawn.gemspec → codesake-dawn.gemspec} +5 -0
  7. data/features/dawn_complains_about_an_incorrect_command_line.feature +2 -2
  8. data/features/dawn_scan_a_secure_sinatra_app.feature +4 -4
  9. data/features/dawn_scan_a_vulnerable_sinatra_app.feature +36 -0
  10. data/features/step_definition/dawn_steps.rb +8 -2
  11. data/lib/codesake-dawn.rb +1 -0
  12. data/lib/codesake/dawn/core.rb +22 -0
  13. data/lib/codesake/dawn/engine.rb +66 -1
  14. data/lib/codesake/dawn/kb/cve_2011_0447.rb +30 -0
  15. data/lib/codesake/dawn/kb/cve_2011_2197.rb +29 -0
  16. data/lib/codesake/dawn/kb/cve_2011_2932.rb +29 -0
  17. data/lib/codesake/dawn/kb/cve_2011_3186.rb +31 -0
  18. data/lib/codesake/dawn/kb/cve_2012_1099.rb +29 -0
  19. data/lib/codesake/dawn/kb/cve_2012_1241.rb +29 -0
  20. data/lib/codesake/dawn/kb/cve_2012_2140.rb +29 -0
  21. data/lib/codesake/dawn/kb/cve_2012_3463.rb +29 -0
  22. data/lib/codesake/dawn/kb/cve_2012_3464.rb +29 -0
  23. data/lib/codesake/dawn/kb/cve_2012_4464.rb +29 -0
  24. data/lib/codesake/dawn/kb/cve_2012_4466.rb +29 -0
  25. data/lib/codesake/dawn/kb/cve_2012_4481.rb +28 -0
  26. data/lib/codesake/dawn/kb/cve_2012_5370.rb +29 -0
  27. data/lib/codesake/dawn/kb/cve_2012_5371.rb +29 -0
  28. data/lib/codesake/dawn/kb/cve_2012_6134.rb +29 -0
  29. data/lib/codesake/dawn/kb/cve_2013_0333.rb +0 -3
  30. data/lib/codesake/dawn/kb/cve_2013_1821.rb +1 -1
  31. data/lib/codesake/dawn/kb/pattern_match_check.rb +4 -3
  32. data/lib/codesake/dawn/kb/ruby_version_check.rb +14 -4
  33. data/lib/codesake/dawn/knowledge_base.rb +30 -0
  34. data/lib/codesake/dawn/sinatra.rb +105 -0
  35. data/lib/codesake/dawn/version.rb +1 -1
  36. data/spec/lib/dawn/codesake_knowledgebase_spec.rb +87 -0
  37. data/spec/lib/dawn/codesake_sinatra_engine_spec.rb +44 -1
  38. data/spec/spec_helper.rb +3 -0
  39. data/spec/support/sinatra-vulnerable/application.rb +6 -0
  40. data/spec/support/sinatra-vulnerable/disabled.png +0 -0
  41. data/spec/support/sinatra-vulnerable/views/xss.haml +3 -0
  42. metadata +91 -15
  43. data/spec/support/hello_world_3.0.19/.gitignore +0 -4
  44. data/spec/support/hello_world_3.1.0/.gitignore +0 -5
  45. data/spec/support/hello_world_3.2.13/.gitignore +0 -15
  46. data/spec/support/sinatra-safe/.gitignore +0 -6
  47. data/spec/support/sinatra-vulnerable/.gitignore +0 -6
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_3463
6
+ include DependencyCheck
7
+
8
+ def initialize
9
+ message="Cross-site scripting (XSS) vulnerability in actionpack/lib/action_view/helpers/form_tag_helper.rb in Ruby on Rails 3.x before 3.0.17, 3.1.x before 3.1.8, and 3.2.x before 3.2.8 allows remote attackers to inject arbitrary web script or HTML via the prompt field to the select_tag helper."
10
+ super({
11
+ :name=>"CVE-2012-3463",
12
+ :cvss=>"AV:N/AC:M/Au:N/C:N/I:P/A:N",
13
+ :release_date => Date.new(2012, 8, 10),
14
+ :cwe=>"79",
15
+ :owasp=>"A3",
16
+ :applies=>["rails"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::DEPENDENCY_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade rails version at least to 3.0.17, 3.1.8 or 3.2.8. As a general rule, using the latest stable rails version is recommended.",
20
+ :aux_links=>["https://groups.google.com/group/rubyonrails-security/msg/961e18e514527078?dmode=source&output=gplain"]
21
+ })
22
+
23
+ self.safe_dependencies = [{:name=>"rails", :version=>['3.0.17', '3.1.8', '3.2.8']}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_3464
6
+ include DependencyCheck
7
+
8
+ def initialize
9
+ message = "Cross-site scripting (XSS) vulnerability in activesupport/lib/active_support/core_ext/string/output_safety.rb in Ruby on Rails before 3.0.17, 3.1.x before 3.1.8, and 3.2.x before 3.2.8 might allow remote attackers to inject arbitrary web script or HTML via vectors involving a ' (quote) character."
10
+ super({
11
+ :name=>"CVE-2012-3464",
12
+ :cvss=>"AV:N/AC:M/Au:N/C:N/I:P/A:N",
13
+ :release_date => Date.new(2012, 8, 10),
14
+ :cwe=>"79",
15
+ :owasp=>"A3",
16
+ :applies=>["rails"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::DEPENDENCY_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade rails version at least to 3.0.17, 3.1.8 or 3.2.8. As a general rule, using the latest stable rails version is recommended.",
20
+ :aux_links=>["https://groups.google.com/group/rubyonrails-security/msg/8f1bbe1cef8c6caf?dmode=source&output=gplain"]
21
+ })
22
+
23
+ self.safe_dependencies = [{:name=>"rails", :version=>['3.0.17', '3.1.8', '3.2.8']}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_4464
6
+ include RubyVersionCheck
7
+
8
+ def initialize
9
+ message = "Ruby 1.9.3 before patchlevel 286 and 2.0 before revision r37068 allows context-dependent attackers to bypass safe-level restrictions and modify untainted strings via the (1) exc_to_s or (2) name_err_to_s API function, which marks the string as tainted, a different vulnerability than CVE-2012-4466. NOTE: this issue might exist because of a CVE-2011-1005 regression."
10
+ super({
11
+ :name=>"CVE-2012-4464",
12
+ :cvss=>"AV:N/AC:L/Au:N/C:N/I:P/A:N",
13
+ :release_date => Date.new(2013, 4, 25),
14
+ :cwe=>"264",
15
+ :owasp=>"A9",
16
+ :applies=>["rails", "sinatra", "padrino"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::RUBY_VERSION_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade ruby interpreter to 1.9.3-p286 or 2.0.0-p195 or latest version available",
20
+ :aux_links=>["ihttp://www.ruby-lang.org/en/news/2012/10/12/cve-2012-4464-cve-2012-4466/"]
21
+ })
22
+
23
+ self.safe_rubies = [{:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p286"}, {:engine=>"ruby", :version=>"2.0.0", :patchlevel=>"p195"}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_4466
6
+ include RubyVersionCheck
7
+
8
+ def initialize
9
+ message="Ruby 1.8.7 before patchlevel 371, 1.9.3 before patchlevel 286, and 2.0 before revision r37068 allows context-dependent attackers to bypass safe-level restrictions and modify untainted strings via the name_err_mesg_to_str API function, which marks the string as tainted, a different vulnerability than CVE-2011-1005."
10
+ super({
11
+ :name=>"CVE-2012-4466",
12
+ :cvss=>"AV:N/AC:L/Au:N/C:N/I:P/A:N",
13
+ :release_date => Date.new(2013, 4, 25),
14
+ :cwe=>"264",
15
+ :owasp=>"A9",
16
+ :applies=>["rails", "sinatra", "padrino"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::RUBY_VERSION_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade ruby interpreter to 1.8.7-p371, 1.9.3-p286 or 2.0.0-p195 or latest version available",
20
+ :aux_links=>["http://www.ruby-lang.org/en/news/2012/10/12/cve-2012-4464-cve-2012-4466/"]
21
+ })
22
+
23
+ self.safe_rubies = [{:engine=>"ruby", :version=>"1.8.7", :patchlevel=>"p371"}, {:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p286"}, {:engine=>"ruby", :version=>"2.0.0", :patchlevel=>"p195"}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-31
5
+ class CVE_2012_4481
6
+ include RubyVersionCheck
7
+
8
+ def initialize
9
+ message="The safe-level feature in Ruby 1.8.7 allows context-dependent attackers to modify strings via the NameError#to_s method when operating on Ruby objects. NOTE: this issue is due to an incomplete fix for CVE-2011-1005."
10
+ super({
11
+ :name=>"CVE-2012-4481",
12
+ :cvss=>"AV:N/AC:M/Au:N/C:N/I:P/A:N",
13
+ :release_date => Date.new(2013, 5, 2),
14
+ :cwe=>"264",
15
+ :owasp=>"A9",
16
+ :applies=>["rails", "sinatra", "padrino"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::RUBY_VERSION_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade ruby interpreter to 1.9.3 or 2.0.0 or latest version available",
20
+ :aux_links=>["https://bugzilla.redhat.com/show_bug.cgi?id=863484"]
21
+ })
22
+
23
+ self.safe_rubies = [{:engine=>"ruby", :version=>"1.8.7", :patchlevel=>"p9999"}]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_5370
6
+ include RubyVersionCheck
7
+
8
+ def initialize
9
+ message="JRuby computes hash values without properly restricting the ability to trigger hash collisions predictably, which allows context-dependent attackers to cause a denial of service (CPU consumption) via crafted input to an application that maintains a hash table, as demonstrated by a universal multicollision attack against the MurmurHash2 algorithm, a different vulnerability than CVE-2011-4838."
10
+ super({
11
+ :name=>"CVE-2012-5370",
12
+ :cvss=>"AV:N/AC:L/Au:N/C:N/I:N/A:P",
13
+ :release_date => Date.new(2012, 11, 28),
14
+ :cwe=>"310",
15
+ :owasp=>"A9",
16
+ :applies=>["rails", "sinatra", "padrino"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::RUBY_VERSION_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"At the moment we're writing this (May 2013) there is no mitigation against this vulnerability. You must consider changing your hashing algorithm",
20
+ :aux_links=>["https://bugzilla.redhat.com/show_bug.cgi?id=880671"]
21
+ })
22
+
23
+ self.safe_rubies = [{:engine=>"jruby", :version=>"999.999.999", :patchlevel=>"p999"}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-30
5
+ class CVE_2012_5371
6
+ include RubyVersionCheck
7
+
8
+ def initialize
9
+ message="Ruby (aka CRuby) 1.9 before 1.9.3-p327 and 2.0 before r37575 computes hash values without properly restricting the ability to trigger hash collisions predictably, which allows context-dependent attackers to cause a denial of service (CPU consumption) via crafted input to an application that maintains a hash table, as demonstrated by a universal multicollision attack against a variant of the MurmurHash2 algorithm, a different vulnerability than CVE-2011-4815."
10
+ super({
11
+ :name=>"CVE-2012-5371",
12
+ :cvss=>"AV:N/AC:L/Au:N/C:N/I:N/A:P",
13
+ :release_date => Date.new(2012, 11, 28),
14
+ :cwe=>"310",
15
+ :owasp=>"A9",
16
+ :applies=>["rails", "sinatra", "padrino"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::RUBY_VERSION_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade ruby interpreter to 1.9.3-p327 or 2.0.0-p195 or latest version available",
20
+ :aux_links=>["http://www.ruby-lang.org/en/news/2012/11/09/ruby19-hashdos-cve-2012-5371/"]
21
+ })
22
+
23
+ self.safe_rubies = [{:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p327"}, {:engine=>"ruby", :version=>"2.0.0", :patchlevel=>"p195"}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Codesake
2
+ module Dawn
3
+ module Kb
4
+ # Automatically created with rake on 2013-05-31
5
+ class CVE_2012_6134
6
+ include DependencyCheck
7
+
8
+ def initialize
9
+ message="Cross-site request forgery (CSRF) vulnerability in the omniauth-oauth2 gem 1.1.1 and earlier for Ruby allows remote attackers to hijack the authentication of users for requests that modify session state."
10
+ super({
11
+ :name=>"CVE-2012-6134",
12
+ :cvss=>"AV:N/AC:M/Au:N/C:P/I:P/A:P",
13
+ :release_date => Date.new(2013, 4, 9),
14
+ :cwe=>"352",
15
+ :owasp=>"A8",
16
+ :applies=>["rails"],
17
+ :kind=>Codesake::Dawn::KnowledgeBase::DEPENDENCY_CHECK,
18
+ :message=>message,
19
+ :mitigation=>"Please upgrade omniauth-oauth2 version to the latest one",
20
+ :aux_links=>["https://github.com/intridea/omniauth-oauth2/pull/25"]
21
+ })
22
+
23
+ self.safe_dependencies = [{:name=>"omniauth-oauth2", :version=>['1.1.2']}]
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,9 +3,6 @@ module Codesake
3
3
  module Kb
4
4
  # Automatically created with rake on 2013-04-30
5
5
  class CVE_2013_0333
6
- #
7
- # Include the testing skeleton for this CVE
8
- # include PatternMatchCheck
9
6
  include DependencyCheck
10
7
 
11
8
 
@@ -20,7 +20,7 @@ module Codesake
20
20
  :aux_links=>["http://www.ruby-lang.org/en/news/2013/02/22/rexml-dos-2013-02-22/"]
21
21
  })
22
22
 
23
- self.safe_rubies = [{:version=>"1.9.3", :patchlevel=>"p392"}, {:version=>"2.0.0", :patchlevel=>"p195"}]
23
+ self.safe_rubies = [{:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p392"}, {:engine=>"ruby", :version=>"2.0.0", :patchlevel=>"p195"}]
24
24
 
25
25
 
26
26
  end
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ require 'ptools'
2
+
2
3
  module Codesake
3
4
  module Dawn
4
5
  module Kb
@@ -16,7 +17,8 @@ module Codesake
16
17
 
17
18
  def vuln?
18
19
  Dir.glob(File.join("#{root_dir}", "*")).each do |filename|
19
- matches = run(load_file(filename))
20
+ matches = []
21
+ matches = run(load_file(filename)) if File.exists?(filename) and File.file?(filename) and ! File.binary?(filename)
20
22
  @evidences << {:filename=>filename, :matches=>matches} unless matches.empty?
21
23
  end
22
24
  return ! @evidences.empty?
@@ -29,7 +31,6 @@ module Codesake
29
31
  end
30
32
 
31
33
  def load_file(filename)
32
- return [] unless File.exists?(filename) and File.file?(filename)
33
34
 
34
35
  f = File.open(filename)
35
36
  lines = f.readlines
@@ -4,20 +4,24 @@ module Codesake
4
4
  module RubyVersionCheck
5
5
  include BasicCheck
6
6
 
7
- # Array of hashes in the {:version=>"1.9.3", :patchlevel=>"p342"} form
7
+ # Array of hashes in the {:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p342"} form
8
8
  attr_accessor :safe_rubies
9
- # Hash in the {:version=>"1.9.3", :patchlevel=>"p342"} form
9
+ # Hash in the {:engine=>"ruby", :version=>"1.9.3", :patchlevel=>"p342"} form
10
10
  attr_accessor :detected_ruby
11
11
 
12
12
  def vuln?
13
13
  vv_a = []
14
14
  vv_p = []
15
+ vv_e = []
15
16
  vp = false
16
17
 
18
+
17
19
  @safe_rubies.each do |ss|
20
+ vv_e << ss[:engine]
18
21
  vv_a << ss[:version]
19
22
  vv_p << ss[:patchlevel].split("p")[1].to_i
20
23
  end
24
+ vengine = self.is_vulnerable_engine?(detected_ruby[:engine], vv_e)
21
25
  vv = self.is_vulnerable_version?(detected_ruby[:version], vv_a)
22
26
 
23
27
  # Since we have also the patch level a fixes version can be the same
@@ -25,10 +29,16 @@ module Codesake
25
29
  ve = self.is_same_version?(detected_ruby[:version], vv_a) unless vv
26
30
  vp = is_vulnerable_patchlevel?(detected_ruby[:patchlevel], vv_p) if ve
27
31
 
28
- return true if vv
29
- return (ve and vp)
32
+ return true if ( vv and vengine )
33
+ return (ve and vp and vengine )
30
34
  end
31
35
 
36
+ def is_vulnerable_engine?(target, fixes = [])
37
+ fixes.each do |f|
38
+ return true if f == target
39
+ end
40
+ end
41
+
32
42
  def is_same_version?(target, fixes = [])
33
43
  fixes.each do |f|
34
44
  return true if f == target
@@ -8,14 +8,29 @@ require "codesake/dawn/kb/ruby_version_check"
8
8
  require "codesake/dawn/kb/not_revised_code"
9
9
 
10
10
  # CVE - 2011
11
+ require "codesake/dawn/kb/cve_2011_0447"
12
+ require "codesake/dawn/kb/cve_2011_2197"
11
13
  require "codesake/dawn/kb/cve_2011_2931"
14
+ require "codesake/dawn/kb/cve_2011_2932"
15
+ require "codesake/dawn/kb/cve_2011_3186"
12
16
 
13
17
  # CVE - 2012
18
+ require "codesake/dawn/kb/cve_2012_1099"
19
+ require "codesake/dawn/kb/cve_2012_1241"
20
+ require "codesake/dawn/kb/cve_2012_2140"
14
21
  require "codesake/dawn/kb/cve_2012_2660"
15
22
  require "codesake/dawn/kb/cve_2012_2661"
16
23
  require "codesake/dawn/kb/cve_2012_2694"
17
24
  require "codesake/dawn/kb/cve_2012_2695"
25
+ require "codesake/dawn/kb/cve_2012_3463"
26
+ require "codesake/dawn/kb/cve_2012_3464"
18
27
  require "codesake/dawn/kb/cve_2012_3465"
28
+ require "codesake/dawn/kb/cve_2012_4464"
29
+ require "codesake/dawn/kb/cve_2012_4466"
30
+ require "codesake/dawn/kb/cve_2012_4481"
31
+ require "codesake/dawn/kb/cve_2012_5370"
32
+ require "codesake/dawn/kb/cve_2012_5371"
33
+ require "codesake/dawn/kb/cve_2012_6134"
19
34
  require "codesake/dawn/kb/cve_2012_6496"
20
35
  require "codesake/dawn/kb/cve_2012_6497"
21
36
 
@@ -110,12 +125,27 @@ module Codesake
110
125
  def self.load_security_checks
111
126
  [
112
127
  Codesake::Dawn::Kb::NotRevisedCode.new,
128
+ Codesake::Dawn::Kb::CVE_2011_0447.new,
129
+ Codesake::Dawn::Kb::CVE_2011_2197.new,
113
130
  Codesake::Dawn::Kb::CVE_2011_2931.new,
131
+ Codesake::Dawn::Kb::CVE_2011_2932.new,
132
+ Codesake::Dawn::Kb::CVE_2011_3186.new,
133
+ Codesake::Dawn::Kb::CVE_2012_1099.new,
134
+ Codesake::Dawn::Kb::CVE_2012_1241.new,
135
+ Codesake::Dawn::Kb::CVE_2012_2140.new,
114
136
  Codesake::Dawn::Kb::CVE_2012_2660.new,
115
137
  Codesake::Dawn::Kb::CVE_2012_2661.new,
116
138
  Codesake::Dawn::Kb::CVE_2012_2694.new,
117
139
  Codesake::Dawn::Kb::CVE_2012_2695.new,
140
+ Codesake::Dawn::Kb::CVE_2012_3463.new,
141
+ Codesake::Dawn::Kb::CVE_2012_3464.new,
118
142
  Codesake::Dawn::Kb::CVE_2012_3465.new,
143
+ Codesake::Dawn::Kb::CVE_2012_4464.new,
144
+ Codesake::Dawn::Kb::CVE_2012_4466.new,
145
+ Codesake::Dawn::Kb::CVE_2012_4481.new,
146
+ Codesake::Dawn::Kb::CVE_2012_5370.new,
147
+ Codesake::Dawn::Kb::CVE_2012_5371.new,
148
+ Codesake::Dawn::Kb::CVE_2012_6134.new,
119
149
  Codesake::Dawn::Kb::CVE_2012_6496.new,
120
150
  Codesake::Dawn::Kb::CVE_2012_6497.new,
121
151
  Codesake::Dawn::Kb::CVE_2013_0155.new,
@@ -1,14 +1,119 @@
1
1
  require "codesake/dawn/engine"
2
+ require 'ruby_parser'
2
3
 
3
4
  module Codesake
4
5
  module Dawn
5
6
  class Sinatra
6
7
  include Codesake::Dawn::Engine
7
8
 
9
+ attr_reader :sinks
10
+ attr_reader :appname
11
+
8
12
  def initialize(dir=nil)
9
13
  super(dir, "sinatra")
14
+ @appname = detect_appname(self.target)
15
+ error! if self.appname == ""
16
+ @sinks = detect_sinks(self.appname) unless self.appname == ""
17
+ @reflected_xss = detect_reflected_xss unless self.appname == ""
18
+ end
19
+
20
+ # TODO: appname should be hopefully autodetect from config.ru
21
+ def detect_appname(target)
22
+ return "app.rb" if File.exist?(File.join(self.target, "app.rb"))
23
+ return "application.rb" if File.exist?(File.join(self.target, "application.rb"))
24
+ file_array = Dir.glob(File.join("#{target}", "*.rb"))
25
+ return file_array[0] if ! file_array.nil? and file_array.count == 1
26
+ return "" # gracefully failure
27
+ end
28
+
29
+ def detect_reflected_xss
30
+ ret = []
31
+ @views.each do |v|
32
+ view_content = File.read(v[:filename])
33
+ @sinks.each do |sink|
34
+ ret << sink if view_content.match(sink[:sink_name])
35
+ end
36
+ end
37
+ ret
38
+ end
39
+
40
+ def detect_sinks(appname=nil)
41
+ ret = []
42
+ appname = "app.rb" if appname.nil? and self.appname == ""
43
+ app_rb = File.readlines(File.join(self.target, appname)) if File.exist?(File.join(self.target, appname))
44
+ return [] if app_rb.nil?
45
+
46
+ parser = RubyParser.new
47
+
48
+ app_rb.each_with_index do |line, i|
49
+ line = line.chomp
50
+
51
+ unless line.match(/params/).nil?
52
+
53
+ begin
54
+ t = parser.parse(line)
55
+
56
+ # a[1] = params["foo"]
57
+ #
58
+ if (! t.nil? and t.sexp_type == :attrasgn)
59
+ body = t.sexp_body.to_a
60
+
61
+ if is_assignement_from_params?(body, :attrasgn)
62
+
63
+ if body[0][0] == :call
64
+ sink_name=body[0][2].to_s unless body[1].to_s == "[]="
65
+ sink_name="#{body[2].to_a[1].to_s}" if body[1].to_s == "[]=" # the sink is assigned to an Array
66
+
67
+ sink_source = "#{body[3].to_a[1][2].to_s}[#{body[3].to_a[3][1].to_s}]"
68
+
69
+ ret << {:sink_name=>sink_name, :sink_kind=>:params, :sink_line=>i+1, :sink_source=>sink_source}
70
+ end
71
+ if body[0][0] == :ivar
72
+ sink_name=body[0][1].to_s
73
+ sink_pos=body[2][1].to_i
74
+ sink_source=body[3][3][1]
75
+
76
+ ret << {:sink_name=>sink_name, :sink_kind=>:params, :sink_line=>i+1, :sink_source=>sink_source}
77
+ end
78
+
79
+ end
80
+ end
81
+
82
+ # a = params["foo"]
83
+ if (! t.nil? and t.sexp_type == :iasgn)
84
+ body = t.sexp_body.to_a
85
+ if is_assignement_from_params?(body, :iasgn)
86
+ sink_name = body[0].to_s
87
+ sink_source = "#{body[1][3][1].to_s}"
88
+ ret << {:sink_name=>sink_name, :sink_kind=>:params, :sink_line=>i+1, :sink_source=>sink_source }
89
+ end
90
+ end
91
+ rescue Racc::ParseError => e
92
+ # TODO: we must pass logger instance to engines if we want some error message
93
+ # For now... silently discard parse errors
94
+ return []
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ ret
10
101
  end
11
102
 
103
+
104
+ def is_assignement_from_params?(body, kind)
105
+ return ( ! body[3].nil? and body[3].to_a[1][2].to_s == "params") if kind == :attrasgn
106
+ return ( ! body[1].nil? and ! body[1][1].nil? and body[1][1][2].to_s == "params") if kind == :iasgn
107
+ end
108
+
109
+ def detect_views
110
+ build_view_array(File.join(self.target, "views")) if File.exist?(File.join(self.target, "views"))
111
+ end
112
+
113
+ # e = Haml::Engine.new(File.read(template))
114
+ # e.precompiled and grep for format_script
115
+
116
+
12
117
  end
13
118
  end
14
119
  end