pwn 0.5.442 → 0.5.444

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +3 -3
  4. data/bin/pwn_sast +1 -0
  5. data/lib/pwn/plugins/file_fu.rb +20 -22
  6. data/lib/pwn/sast/amqp_connect_as_guest.rb +12 -91
  7. data/lib/pwn/sast/apache_file_system_util_api.rb +11 -93
  8. data/lib/pwn/sast/aws.rb +13 -95
  9. data/lib/pwn/sast/banned_function_calls_c.rb +140 -219
  10. data/lib/pwn/sast/base64.rb +12 -92
  11. data/lib/pwn/sast/beef_hook.rb +10 -92
  12. data/lib/pwn/sast/cmd_execution_go_lang.rb +83 -0
  13. data/lib/pwn/sast/cmd_execution_java.rb +14 -93
  14. data/lib/pwn/sast/cmd_execution_python.rb +16 -95
  15. data/lib/pwn/sast/cmd_execution_ruby.rb +24 -103
  16. data/lib/pwn/sast/cmd_execution_scala.rb +14 -93
  17. data/lib/pwn/sast/csrf.rb +10 -92
  18. data/lib/pwn/sast/deserial_java.rb +19 -98
  19. data/lib/pwn/sast/emoticon.rb +17 -100
  20. data/lib/pwn/sast/eval.rb +10 -92
  21. data/lib/pwn/sast/factory.rb +15 -95
  22. data/lib/pwn/sast/http_authorization_header.rb +20 -102
  23. data/lib/pwn/sast/inner_html.rb +10 -92
  24. data/lib/pwn/sast/keystore.rb +10 -92
  25. data/lib/pwn/sast/local_storage.rb +11 -93
  26. data/lib/pwn/sast/location_hash.rb +10 -92
  27. data/lib/pwn/sast/log4j.rb +12 -91
  28. data/lib/pwn/sast/logger.rb +24 -106
  29. data/lib/pwn/sast/md5.rb +10 -92
  30. data/lib/pwn/sast/outer_html.rb +10 -92
  31. data/lib/pwn/sast/padding_oracle.rb +11 -93
  32. data/lib/pwn/sast/password.rb +15 -97
  33. data/lib/pwn/sast/php_input_mechanisms.rb +18 -97
  34. data/lib/pwn/sast/php_type_juggling.rb +16 -95
  35. data/lib/pwn/sast/pom_version.rb +1 -3
  36. data/lib/pwn/sast/port.rb +16 -98
  37. data/lib/pwn/sast/post_message.rb +10 -92
  38. data/lib/pwn/sast/private_key.rb +10 -92
  39. data/lib/pwn/sast/redirect.rb +13 -95
  40. data/lib/pwn/sast/redos.rb +16 -98
  41. data/lib/pwn/sast/shell.rb +18 -100
  42. data/lib/pwn/sast/signature.rb +10 -92
  43. data/lib/pwn/sast/sql.rb +19 -95
  44. data/lib/pwn/sast/ssl.rb +14 -96
  45. data/lib/pwn/sast/sudo.rb +10 -92
  46. data/lib/pwn/sast/task_tag.rb +23 -105
  47. data/lib/pwn/sast/test_case_engine.rb +188 -0
  48. data/lib/pwn/sast/throw_errors.rb +14 -96
  49. data/lib/pwn/sast/token.rb +12 -94
  50. data/lib/pwn/sast/type_script_type_juggling.rb +16 -95
  51. data/lib/pwn/sast/version.rb +12 -94
  52. data/lib/pwn/sast/window_location_hash.rb +10 -92
  53. data/lib/pwn/sast.rb +5 -0
  54. data/lib/pwn/version.rb +1 -1
  55. data/lib/pwn.rb +0 -2
  56. data/spec/lib/pwn/sast/cmd_execution_go_lang_spec.rb +25 -0
  57. data/spec/lib/pwn/sast/test_case_engine_spec.rb +20 -0
  58. data/third_party/pwn_rdoc.jsonl +1 -1
  59. metadata +7 -3
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'json'
4
+ require 'socket'
5
+
6
+ module PWN
7
+ module SAST
8
+ # SAST Module used to identify command
9
+ # execution residing within GoLang source code.
10
+ module CmdExecutionGoLang
11
+ # Supported Method Parameters::
12
+ # PWN::SAST::CmdExecutionGoLang.scan(
13
+ # dir_path: 'optional path to dir defaults to .'
14
+ # git_repo_root_uri: 'optional http uri of git repo scanned'
15
+ # )
16
+
17
+ public_class_method def self.scan(opts = {})
18
+ dir_path = opts[:dir_path]
19
+ git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
20
+
21
+ test_case_filter = "
22
+ grep -Fn \
23
+ -e 'exec.Command(' \
24
+ -e 'exec.CommandContext(' \
25
+ -e 'Cmd.CombinedOutput(' \
26
+ -e 'Cmd.Output(' \
27
+ -e 'Cmd.Run(' \
28
+ -e 'Cmd.Start(' {PWN_SAST_SRC_TARGET} 2> /dev/null
29
+ "
30
+
31
+ include_extensions = %w[.go .s .o .a .mod]
32
+
33
+ PWN::SAST::TestCaseEngine.execute(
34
+ test_case_filter: test_case_filter,
35
+ security_references: security_references,
36
+ dir_path: dir_path,
37
+ include_extensions: include_extensions,
38
+ git_repo_root_uri: git_repo_root_uri
39
+ )
40
+ rescue StandardError => e
41
+ raise e
42
+ end
43
+
44
+ # Used primarily to map NIST 800-53 Revision 4 Security Controls
45
+ # https://web.nvd.nist.gov/view/800-53/Rev4/impact?impactName=HIGH
46
+ # to PWN Exploit & Static Code Anti-Pattern Matching Modules to
47
+ # Determine the level of Testing Coverage w/ PWN.
48
+
49
+ public_class_method def self.security_references
50
+ {
51
+ sast_module: self,
52
+ section: 'INFORMATION INPUT VALIDATION',
53
+ nist_800_53_uri: 'https://csrc.nist.gov/projects/cprt/catalog#/cprt/framework/version/SP_800_53_5_1_1/home?element=SI-10',
54
+ cwe_id: '78',
55
+ cwe_uri: 'https://cwe.mitre.org/data/definitions/78.html'
56
+ }
57
+ rescue StandardError => e
58
+ raise e
59
+ end
60
+
61
+ # Author(s):: 0day Inc. <support@0dayinc.com>
62
+
63
+ public_class_method def self.authors
64
+ "AUTHOR(S):
65
+ 0day Inc. <support@0dayinc.com>
66
+ "
67
+ end
68
+
69
+ # Display Usage for this Module
70
+
71
+ public_class_method def self.help
72
+ puts "USAGE:
73
+ sast_arr = #{self}.scan(
74
+ :dir_path => 'optional path to dir defaults to .',
75
+ :git_repo_root_uri => 'optional http uri of git repo scanned'
76
+ )
77
+
78
+ #{self}.authors
79
+ "
80
+ end
81
+ end
82
+ end
83
+ end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify command
9
9
  # execution residing within Java source code.
10
10
  module CmdExecutionJava
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::CmdExecutionJava.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,100 +17,23 @@ module PWN
19
17
  public_class_method def self.scan(opts = {})
20
18
  dir_path = opts[:dir_path]
21
19
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
22
- result_arr = []
23
- ai_introspection = PWN::Env[:ai][:introspection]
24
- logger_results = "AI Introspection => #{ai_introspection} => "
25
-
26
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
27
- if (File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/) && File.extname(entry) == '.java' && entry !~ /test/i
28
- line_no_and_contents_arr = []
29
- entry_beautified = false
30
-
31
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
32
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
33
- entry = "#{entry}.JS-BEAUTIFIED"
34
- entry_beautified = true
35
- end
36
-
37
- test_case_filter = "
38
- grep -Fn \
39
- -e 'getEngineByName(' \
40
- -e 'ProcessBuilder(' \
41
- -e '.exec(' #{entry} 2> /dev/null
42
- "
43
-
44
- str = `#{test_case_filter}`.to_s.scrub
45
20
 
46
- if str.to_s.empty?
47
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
48
- logger_results = "#{logger_results}~" # Catching bugs is good :)
49
- else
50
- str = "1:Result larger than 64KB -> Size: #{str.to_s.length}. Please click the \"Path\" link for more details." if str.to_s.length >= 64_000
51
-
52
- hash_line = {
53
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
54
- security_references: security_references,
55
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
56
- line_no_and_contents: '',
57
- raw_content: str,
58
- test_case_filter: test_case_filter
59
- }
60
-
61
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
62
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
63
- line_no_count = line_contents_split.length # This should always be an even number
64
- current_count = 0
65
- while line_no_count > current_count
66
- line_no = line_contents_split[current_count]
67
- contents = line_contents_split[current_count + 1]
68
- if Dir.exist?('.git')
69
- repo_root = '.'
70
-
71
- author = PWN::Plugins::Git.get_author(
72
- repo_root: repo_root,
73
- from_line: line_no,
74
- to_line: line_no,
75
- target_file: entry,
76
- entry_beautified: entry_beautified
77
- )
78
- end
79
- author ||= 'N/A'
80
-
81
- ai_analysis = nil
82
- if ai_introspection
83
- request = {
84
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
85
- line_no: line_no,
86
- source_code_snippet: contents
87
- }.to_json
88
- response = PWN::AI::Introspection.reflect(request: request)
89
- if response.is_a?(Hash)
90
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
91
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
92
- end
93
- end
21
+ test_case_filter = "
22
+ grep -Fn \
23
+ -e 'getEngineByName(' \
24
+ -e 'ProcessBuilder(' \
25
+ -e '.exec(' {PWN_SAST_SRC_TARGET} 2> /dev/null
26
+ "
94
27
 
95
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
96
- line_no: line_no,
97
- contents: contents,
98
- author: author,
99
- ai_analysis: ai_analysis
100
- )
28
+ include_extensions = %w[.java .class .jar .war .ear .nar .properties .aj .jsp .jspx .jstm .jsptml .jnlp .jad .ser .gsp]
101
29
 
102
- current_count += 2
103
- end
104
- result_arr.push(hash_line)
105
- logger_results = "#{logger_results}x" # Seeing progress is good :)
106
- end
107
- end
108
- end
109
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
110
- if logger_results.empty?
111
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
112
- else
113
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
114
- end
115
- result_arr
30
+ PWN::SAST::TestCaseEngine.execute(
31
+ test_case_filter: test_case_filter,
32
+ security_references: security_references,
33
+ dir_path: dir_path,
34
+ include_extensions: include_extensions,
35
+ git_repo_root_uri: git_repo_root_uri
36
+ )
116
37
  rescue StandardError => e
117
38
  raise e
118
39
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify command execution
9
9
  # residing within Python source code.
10
10
  module CmdExecutionPython
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::CmdExecutionPython.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,102 +17,25 @@ module PWN
19
17
  public_class_method def self.scan(opts = {})
20
18
  dir_path = opts[:dir_path]
21
19
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
22
- result_arr = []
23
- ai_introspection = PWN::Env[:ai][:introspection]
24
- logger_results = "AI Introspection => #{ai_introspection} => "
25
-
26
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
27
- if (File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/) && (File.extname(entry) == '.py' || File.extname(entry) == '.pyc' || File.extname(entry) == '.pyo' || File.extname(entry) == '.pyd') && entry !~ /test/i
28
- line_no_and_contents_arr = []
29
- entry_beautified = false
30
-
31
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
32
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
33
- entry = "#{entry}.JS-BEAUTIFIED"
34
- entry_beautified = true
35
- end
36
-
37
- test_case_filter = "
38
- grep -Fn \
39
- -e 'eval(' \
40
- -e 'os.popen' \
41
- -e 'os.system' \
42
- -e 'subprocess.call' \
43
- -e 'subprocess.Popen' #{entry} 2> /dev/null
44
- "
45
-
46
- str = `#{test_case_filter}`.to_s.scrub
47
20
 
48
- if str.to_s.empty?
49
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
50
- logger_results = "#{logger_results}~" # Catching bugs is good :)
51
- else
52
- str = "1:Result larger than 64KB -> Size: #{str.to_s.length}. Please click the \"Path\" link for more details." if str.to_s.length >= 64_000
53
-
54
- hash_line = {
55
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
56
- security_references: security_references,
57
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
58
- line_no_and_contents: '',
59
- raw_content: str,
60
- test_case_filter: test_case_filter
61
- }
62
-
63
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
64
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
65
- line_no_count = line_contents_split.length # This should always be an even number
66
- current_count = 0
67
- while line_no_count > current_count
68
- line_no = line_contents_split[current_count]
69
- contents = line_contents_split[current_count + 1]
70
- if Dir.exist?('.git')
71
- repo_root = '.'
72
-
73
- author = PWN::Plugins::Git.get_author(
74
- repo_root: repo_root,
75
- from_line: line_no,
76
- to_line: line_no,
77
- target_file: entry,
78
- entry_beautified: entry_beautified
79
- )
80
- end
81
- author ||= 'N/A'
82
-
83
- ai_analysis = nil
84
- if ai_introspection
85
- request = {
86
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
87
- line_no: line_no,
88
- source_code_snippet: contents
89
- }.to_json
90
- response = PWN::AI::Introspection.reflect(request: request)
91
- if response.is_a?(Hash)
92
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
93
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
94
- end
95
- end
21
+ test_case_filter = "
22
+ grep -Fn \
23
+ -e 'eval(' \
24
+ -e 'os.popen' \
25
+ -e 'os.system' \
26
+ -e 'subprocess.call' \
27
+ -e 'subprocess.Popen' {PWN_SAST_SRC_TARGET} 2> /dev/null
28
+ "
96
29
 
97
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
98
- line_no: line_no,
99
- contents: contents,
100
- author: author,
101
- ai_analysis: ai_analysis
102
- )
30
+ include_extensions = %w[.py .pyc .pyd .pyo .pyw .pyi .pyx .pxd .ipynb .pyz .whl .egg .pth]
103
31
 
104
- current_count += 2
105
- end
106
- result_arr.push(hash_line)
107
- logger_results = "#{logger_results}x" # Seeing progress is good :)
108
- end
109
- end
110
- end
111
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
112
- if logger_results.empty?
113
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
114
- else
115
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
116
- end
117
- result_arr
32
+ PWN::SAST::TestCaseEngine.execute(
33
+ test_case_filter: test_case_filter,
34
+ security_references: security_references,
35
+ dir_path: dir_path,
36
+ include_extensions: include_extensions,
37
+ git_repo_root_uri: git_repo_root_uri
38
+ )
118
39
  rescue StandardError => e
119
40
  raise e
120
41
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify command
9
9
  # execution residing within Ruby source code.
10
10
  module CmdExecutionRuby
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::CmdExecutionRuby(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,110 +17,33 @@ module PWN
19
17
  public_class_method def self.scan(opts = {})
20
18
  dir_path = opts[:dir_path]
21
19
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
22
- result_arr = []
23
- ai_introspection = PWN::Env[:ai][:introspection]
24
- logger_results = "AI Introspection => #{ai_introspection} => "
25
-
26
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
27
- if (File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/) && (File.extname(entry) == '.rb' || File.extname(entry) == '.rbw') && entry !~ /test/i
28
- line_no_and_contents_arr = []
29
- entry_beautified = false
30
-
31
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
32
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
33
- entry = "#{entry}.JS-BEAUTIFIED"
34
- entry_beautified = true
35
- end
36
-
37
- test_case_filter = "
38
- grep -n \
39
- -e '`.*`' \
40
- -e 'eval(' \
41
- -e 'exec(' \
42
- -e 'exec \"' \
43
- -e 'system(' \
44
- -e 'system \"' \
45
- -e 'IO.popen' \
46
- -e 'Open3.popen3' \
47
- -e 'Open3.popen3' \
48
- -e 'Facter::Util::Resolution::exec' \
49
- -e 'PTY.spawn' \
50
- -e 'Process.fork' \
51
- -e '%x' #{entry} 2> /dev/null
52
- "
53
-
54
- str = `#{test_case_filter}`.to_s.scrub
55
20
 
56
- if str.to_s.empty?
57
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
58
- logger_results = "#{logger_results}~" # Catching bugs is good :)
59
- else
60
- str = "1:Result larger than 64KB -> Size: #{str.to_s.length}. Please click the \"Path\" link for more details." if str.to_s.length >= 64_000
61
-
62
- hash_line = {
63
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
64
- security_references: security_references,
65
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
66
- line_no_and_contents: '',
67
- raw_content: str,
68
- test_case_filter: test_case_filter
69
- }
70
-
71
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
72
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
73
- line_no_count = line_contents_split.length # This should always be an even number
74
- current_count = 0
75
- while line_no_count > current_count
76
- line_no = line_contents_split[current_count]
77
- contents = line_contents_split[current_count + 1]
78
- if Dir.exist?('.git')
79
- repo_root = '.'
80
-
81
- author = PWN::Plugins::Git.get_author(
82
- repo_root: repo_root,
83
- from_line: line_no,
84
- to_line: line_no,
85
- target_file: entry,
86
- entry_beautified: entry_beautified
87
- )
88
- end
89
- author ||= 'N/A'
90
-
91
- ai_analysis = nil
92
- if ai_introspection
93
- request = {
94
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
95
- line_no: line_no,
96
- source_code_snippet: contents
97
- }.to_json
98
- response = PWN::AI::Introspection.reflect(request: request)
99
- if response.is_a?(Hash)
100
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
101
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
102
- end
103
- end
21
+ test_case_filter = "
22
+ grep -n \
23
+ -e '`.*`' \
24
+ -e 'eval(' \
25
+ -e 'exec(' \
26
+ -e 'exec \"' \
27
+ -e 'system(' \
28
+ -e 'system \"' \
29
+ -e 'IO.popen' \
30
+ -e 'Open3.popen3' \
31
+ -e 'Open3.popen3' \
32
+ -e 'Facter::Util::Resolution::exec' \
33
+ -e 'PTY.spawn' \
34
+ -e 'Process.fork' \
35
+ -e '%x' {PWN_SAST_SRC_TARGET} 2> /dev/null
36
+ "
104
37
 
105
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
106
- line_no: line_no,
107
- contents: contents,
108
- author: author,
109
- ai_analysis: ai_analysis
110
- )
38
+ include_extensions = %w[.rb .erb .rhtml .rake .gemspec .gem .ru .bundle]
111
39
 
112
- current_count += 2
113
- end
114
- result_arr.push(hash_line)
115
- logger_results = "#{logger_results}x" # Seeing progress is good :)
116
- end
117
- end
118
- end
119
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
120
- if logger_results.empty?
121
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
122
- else
123
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
124
- end
125
- result_arr
40
+ PWN::SAST::TestCaseEngine.execute(
41
+ test_case_filter: test_case_filter,
42
+ security_references: security_references,
43
+ dir_path: dir_path,
44
+ include_extensions: include_extensions,
45
+ git_repo_root_uri: git_repo_root_uri
46
+ )
126
47
  rescue StandardError => e
127
48
  raise e
128
49
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify command
9
9
  # execution residing within scala source code.
10
10
  module CmdExecutionScala
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::CmdExecutionScala.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,100 +17,23 @@ module PWN
19
17
  public_class_method def self.scan(opts = {})
20
18
  dir_path = opts[:dir_path]
21
19
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
22
- result_arr = []
23
- ai_introspection = PWN::Env[:ai][:introspection]
24
- logger_results = "AI Introspection => #{ai_introspection} => "
25
-
26
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
27
- if (File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/) && File.extname(entry) == '.scala' && entry !~ /test/i
28
- line_no_and_contents_arr = []
29
- entry_beautified = false
30
-
31
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
32
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
33
- entry = "#{entry}.JS-BEAUTIFIED"
34
- entry_beautified = true
35
- end
36
-
37
- test_case_filter = "
38
- grep -Fn \
39
- -e 'Process(' \
40
- -e '.!' \
41
- -e '.!!' #{entry} 2> /dev/null
42
- "
43
-
44
- str = `#{test_case_filter}`.to_s.scrub
45
20
 
46
- if str.to_s.empty?
47
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
48
- logger_results = "#{logger_results}~" # Catching bugs is good :)
49
- else
50
- str = "1:Result larger than 64KB -> Size: #{str.to_s.length}. Please click the \"Path\" link for more details." if str.to_s.length >= 64_000
51
-
52
- hash_line = {
53
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
54
- security_references: security_references,
55
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
56
- line_no_and_contents: '',
57
- raw_content: str,
58
- test_case_filter: test_case_filter
59
- }
60
-
61
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
62
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
63
- line_no_count = line_contents_split.length # This should always be an even number
64
- current_count = 0
65
- while line_no_count > current_count
66
- line_no = line_contents_split[current_count]
67
- contents = line_contents_split[current_count + 1]
68
- if Dir.exist?('.git')
69
- repo_root = '.'
70
-
71
- author = PWN::Plugins::Git.get_author(
72
- repo_root: repo_root,
73
- from_line: line_no,
74
- to_line: line_no,
75
- target_file: entry,
76
- entry_beautified: entry_beautified
77
- )
78
- end
79
- author ||= 'N/A'
80
-
81
- ai_analysis = nil
82
- if ai_introspection
83
- request = {
84
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
85
- line_no: line_no,
86
- source_code_snippet: contents
87
- }.to_json
88
- response = PWN::AI::Introspection.reflect(request: request)
89
- if response.is_a?(Hash)
90
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
91
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
92
- end
93
- end
21
+ test_case_filter = "
22
+ grep -Fn \
23
+ -e 'Process(' \
24
+ -e '.!' \
25
+ -e '.!!' {PWN_SAST_SRC_TARGET} 2> /dev/null
26
+ "
94
27
 
95
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
96
- line_no: line_no,
97
- contents: contents,
98
- author: author,
99
- ai_analysis: ai_analysis
100
- )
28
+ include_extensions = %w[.scala .sc .sbt .class .jar .war .tasty .scala.html .scala.js .scala.txt .properties]
101
29
 
102
- current_count += 2
103
- end
104
- result_arr.push(hash_line)
105
- logger_results = "#{logger_results}x" # Seeing progress is good :)
106
- end
107
- end
108
- end
109
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
110
- if logger_results.empty?
111
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
112
- else
113
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
114
- end
115
- result_arr
30
+ PWN::SAST::TestCaseEngine.execute(
31
+ test_case_filter: test_case_filter,
32
+ security_references: security_references,
33
+ dir_path: dir_path,
34
+ include_extensions: include_extensions,
35
+ git_repo_root_uri: git_repo_root_uri
36
+ )
116
37
  rescue StandardError => e
117
38
  raise e
118
39
  end