codesake-dawn 0.60 → 0.70

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