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
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify private keys used for authenticating
9
9
  # with remote hosts.
10
10
  module PrivateKey
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::PrivateKey(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,98 +17,18 @@ 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$/ && 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 'PRIVATE KEY' #{entry} 2> /dev/null
40
- "
41
-
42
- str = `#{test_case_filter}`.to_s.scrub
43
-
44
- if str.to_s.empty?
45
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
46
- logger_results = "#{logger_results}~" # Catching bugs is good :)
47
- else
48
- 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
49
20
 
50
- hash_line = {
51
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
52
- security_references: security_references,
53
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
54
- line_no_and_contents: '',
55
- raw_content: str,
56
- test_case_filter: test_case_filter
57
- }
58
-
59
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
60
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
61
- line_no_count = line_contents_split.length # This should always be an even number
62
- current_count = 0
63
- while line_no_count > current_count
64
- line_no = line_contents_split[current_count]
65
- contents = line_contents_split[current_count + 1]
66
- if Dir.exist?('.git')
67
- repo_root = '.'
68
-
69
- author = PWN::Plugins::Git.get_author(
70
- repo_root: repo_root,
71
- from_line: line_no,
72
- to_line: line_no,
73
- target_file: entry,
74
- entry_beautified: entry_beautified
75
- )
76
- end
77
- author ||= 'N/A'
78
-
79
- ai_analysis = nil
80
- if ai_introspection
81
- request = {
82
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
83
- line_no: line_no,
84
- source_code_snippet: contents
85
- }.to_json
86
- response = PWN::AI::Introspection.reflect(request: request)
87
- if response.is_a?(Hash)
88
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
89
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
90
- end
91
- end
92
-
93
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
94
- line_no: line_no,
95
- contents: contents,
96
- author: author,
97
- ai_analysis: ai_analysis
98
- )
21
+ test_case_filter = "
22
+ grep -n \
23
+ -e 'PRIVATE KEY' {PWN_SAST_SRC_TARGET} 2> /dev/null
24
+ "
99
25
 
100
- current_count += 2
101
- end
102
- result_arr.push(hash_line)
103
- logger_results = "#{logger_results}x" # Seeing progress is good :)
104
- end
105
- end
106
- end
107
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
108
- if logger_results.empty?
109
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
110
- else
111
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
112
- end
113
- result_arr
26
+ PWN::SAST::TestCaseEngine.execute(
27
+ test_case_filter: test_case_filter,
28
+ security_references: security_references,
29
+ dir_path: dir_path,
30
+ git_repo_root_uri: git_repo_root_uri
31
+ )
114
32
  rescue StandardError => e
115
33
  raise e
116
34
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify if applications
9
9
  # allow arbritrary redirects to third-party URLs w/o a whitelist
10
10
  module Redirect
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::Redirect.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,100 +17,20 @@ 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$/ && 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 -Ein \
39
- -e "redirect(\\s=|=)" \
40
- -e "redirect_url(\\s=|=)" \
41
- -e "redirect_uri(\\s=|=)" #{entry} 2> /dev/null
42
- )
43
-
44
- str = `#{test_case_filter}`.to_s.scrub
45
-
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
94
-
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
- )
101
20
 
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
21
+ test_case_filter = %(
22
+ grep -Ein \
23
+ -e "redirect(\\s=|=)" \
24
+ -e "redirect_url(\\s=|=)" \
25
+ -e "redirect_uri(\\s=|=)" {PWN_SAST_SRC_TARGET} 2> /dev/null
26
+ )
27
+
28
+ PWN::SAST::TestCaseEngine.execute(
29
+ test_case_filter: test_case_filter,
30
+ security_references: security_references,
31
+ dir_path: dir_path,
32
+ git_repo_root_uri: git_repo_root_uri
33
+ )
116
34
  rescue StandardError => e
117
35
  raise e
118
36
  end
@@ -9,8 +9,6 @@ module PWN
9
9
  # within source code. For more information, see:
10
10
  # https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
11
11
  module ReDOS
12
- @@logger = PWN::Plugins::PWNLogger.create
13
-
14
12
  # Supported Method Parameters::
15
13
  # PWN::SAST::ReDOS.scan(
16
14
  # dir_path: 'optional path to dir defaults to .'
@@ -20,104 +18,24 @@ module PWN
20
18
  public_class_method def self.scan(opts = {})
21
19
  dir_path = opts[:dir_path]
22
20
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
23
- result_arr = []
24
- ai_introspection = PWN::Env[:ai][:introspection]
25
- logger_results = "AI Introspection => #{ai_introspection} => "
26
-
27
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
28
- if File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/ && entry !~ /test/i
29
- line_no_and_contents_arr = []
30
- entry_beautified = false
31
-
32
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
33
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
34
- entry = "#{entry}.JS-BEAUTIFIED"
35
- entry_beautified = true
36
- end
37
-
38
- test_case_filter = "
39
- grep -Fin \
40
- -e '(a+)+' \
41
- -e '([a-zA-Z]+)*' \
42
- -e '(a|aa)+' \
43
- -e '(a|a?)+' \
44
- -e '(([a-z])' \
45
- -e '([a-zA-Z0-9])' \
46
- -e '(.*a)\{' #{entry} 2> /dev/null
47
- "
48
-
49
- str = `#{test_case_filter}`.to_s.scrub
50
-
51
- if str.to_s.empty?
52
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
53
- logger_results = "#{logger_results}~" # Catching bugs is good :)
54
- else
55
- 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
56
21
 
57
- hash_line = {
58
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
59
- security_references: security_references,
60
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
61
- line_no_and_contents: '',
62
- raw_content: str,
63
- test_case_filter: test_case_filter
64
- }
65
-
66
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
67
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
68
- line_no_count = line_contents_split.length # This should always be an even number
69
- current_count = 0
70
- while line_no_count > current_count
71
- line_no = line_contents_split[current_count]
72
- contents = line_contents_split[current_count + 1]
73
- if Dir.exist?('.git')
74
- repo_root = '.'
75
-
76
- author = PWN::Plugins::Git.get_author(
77
- repo_root: repo_root,
78
- from_line: line_no,
79
- to_line: line_no,
80
- target_file: entry,
81
- entry_beautified: entry_beautified
82
- )
83
- end
84
- author ||= 'N/A'
85
-
86
- ai_analysis = nil
87
- if ai_introspection
88
- request = {
89
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
90
- line_no: line_no,
91
- source_code_snippet: contents
92
- }.to_json
93
- response = PWN::AI::Introspection.reflect(request: request)
94
- if response.is_a?(Hash)
95
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
96
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
97
- end
98
- end
99
-
100
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
101
- line_no: line_no,
102
- contents: contents,
103
- author: author,
104
- ai_analysis: ai_analysis
105
- )
22
+ test_case_filter = "
23
+ grep -Fin \
24
+ -e '(a+)+' \
25
+ -e '([a-zA-Z]+)*' \
26
+ -e '(a|aa)+' \
27
+ -e '(a|a?)+' \
28
+ -e '(([a-z])' \
29
+ -e '([a-zA-Z0-9])' \
30
+ -e '(.*a)\{' {PWN_SAST_SRC_TARGET} 2> /dev/null
31
+ "
106
32
 
107
- current_count += 2
108
- end
109
- result_arr.push(hash_line)
110
- logger_results = "#{logger_results}x" # Seeing progress is good :)
111
- end
112
- end
113
- end
114
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
115
- if logger_results.empty?
116
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
117
- else
118
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
119
- end
120
- result_arr
33
+ PWN::SAST::TestCaseEngine.execute(
34
+ test_case_filter: test_case_filter,
35
+ security_references: security_references,
36
+ dir_path: dir_path,
37
+ git_repo_root_uri: git_repo_root_uri
38
+ )
121
39
  rescue StandardError => e
122
40
  raise e
123
41
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify if application is
9
9
  # shelling-out which may lead to arbitrary command execution
10
10
  module Shell
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::Shell.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,106 +17,26 @@ 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$/ && 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 -niE \
39
- -e '/bin/bash' \
40
- -e '/bin/csh' \
41
- -e '/bin/dash' \
42
- -e '/bin/ksh' \
43
- -e '/bin/rbash' \
44
- -e '/bin/sh' \
45
- -e '/bin/tcsh' \
46
- -e '/usr/bin/screen' \
47
- -e '/bin/zsh' #{entry} 2> /dev/null
48
- "
49
-
50
- str = `#{test_case_filter}`.to_s.scrub
51
-
52
- if str.to_s.empty?
53
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
54
- logger_results = "#{logger_results}~" # Catching bugs is good :)
55
- else
56
- 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
57
20
 
58
- hash_line = {
59
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
60
- security_references: security_references,
61
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
62
- line_no_and_contents: '',
63
- raw_content: str,
64
- test_case_filter: test_case_filter
65
- }
66
-
67
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
68
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
69
- line_no_count = line_contents_split.length # This should always be an even number
70
- current_count = 0
71
- while line_no_count > current_count
72
- line_no = line_contents_split[current_count]
73
- contents = line_contents_split[current_count + 1]
74
- if Dir.exist?('.git')
75
- repo_root = '.'
76
-
77
- author = PWN::Plugins::Git.get_author(
78
- repo_root: repo_root,
79
- from_line: line_no,
80
- to_line: line_no,
81
- target_file: entry,
82
- entry_beautified: entry_beautified
83
- )
84
- end
85
- author ||= 'N/A'
86
-
87
- ai_analysis = nil
88
- if ai_introspection
89
- request = {
90
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
91
- line_no: line_no,
92
- source_code_snippet: contents
93
- }.to_json
94
- response = PWN::AI::Introspection.reflect(request: request)
95
- if response.is_a?(Hash)
96
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
97
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
98
- end
99
- end
100
-
101
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
102
- line_no: line_no,
103
- contents: contents,
104
- author: author,
105
- ai_analysis: ai_analysis
106
- )
21
+ test_case_filter = "
22
+ grep -niE \
23
+ -e '/bin/bash' \
24
+ -e '/bin/csh' \
25
+ -e '/bin/dash' \
26
+ -e '/bin/ksh' \
27
+ -e '/bin/rbash' \
28
+ -e '/bin/sh' \
29
+ -e '/bin/tcsh' \
30
+ -e '/usr/bin/screen' \
31
+ -e '/bin/zsh' {PWN_SAST_SRC_TARGET} 2> /dev/null
32
+ "
107
33
 
108
- current_count += 2
109
- end
110
- result_arr.push(hash_line)
111
- logger_results = "#{logger_results}x" # Seeing progress is good :)
112
- end
113
- end
114
- end
115
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
116
- if logger_results.empty?
117
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
118
- else
119
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
120
- end
121
- result_arr
34
+ PWN::SAST::TestCaseEngine.execute(
35
+ test_case_filter: test_case_filter,
36
+ security_references: security_references,
37
+ dir_path: dir_path,
38
+ git_repo_root_uri: git_repo_root_uri
39
+ )
122
40
  rescue StandardError => e
123
41
  raise e
124
42
  end
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify private keys used for authenticating
9
9
  # with remote hosts.
10
10
  module Signature
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::Signature(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,98 +17,18 @@ 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$/ && 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 'Signature' #{entry} 2> /dev/null
40
- "
41
-
42
- str = `#{test_case_filter}`.to_s.scrub
43
-
44
- if str.to_s.empty?
45
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
46
- logger_results = "#{logger_results}~" # Catching bugs is good :)
47
- else
48
- 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
49
20
 
50
- hash_line = {
51
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
52
- security_references: security_references,
53
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
54
- line_no_and_contents: '',
55
- raw_content: str,
56
- test_case_filter: test_case_filter
57
- }
58
-
59
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
60
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
61
- line_no_count = line_contents_split.length # This should always be an even number
62
- current_count = 0
63
- while line_no_count > current_count
64
- line_no = line_contents_split[current_count]
65
- contents = line_contents_split[current_count + 1]
66
- if Dir.exist?('.git')
67
- repo_root = '.'
68
-
69
- author = PWN::Plugins::Git.get_author(
70
- repo_root: repo_root,
71
- from_line: line_no,
72
- to_line: line_no,
73
- target_file: entry,
74
- entry_beautified: entry_beautified
75
- )
76
- end
77
- author ||= 'N/A'
78
-
79
- ai_analysis = nil
80
- if ai_introspection
81
- request = {
82
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
83
- line_no: line_no,
84
- source_code_snippet: contents
85
- }.to_json
86
- response = PWN::AI::Introspection.reflect(request: request)
87
- if response.is_a?(Hash)
88
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
89
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
90
- end
91
- end
92
-
93
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
94
- line_no: line_no,
95
- contents: contents,
96
- author: author,
97
- ai_analysis: ai_analysis
98
- )
21
+ test_case_filter = "
22
+ grep -n \
23
+ -e 'Signature' {PWN_SAST_SRC_TARGET} 2> /dev/null
24
+ "
99
25
 
100
- current_count += 2
101
- end
102
- result_arr.push(hash_line)
103
- logger_results = "#{logger_results}x" # Seeing progress is good :)
104
- end
105
- end
106
- end
107
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
108
- if logger_results.empty?
109
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
110
- else
111
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
112
- end
113
- result_arr
26
+ PWN::SAST::TestCaseEngine.execute(
27
+ test_case_filter: test_case_filter,
28
+ security_references: security_references,
29
+ dir_path: dir_path,
30
+ git_repo_root_uri: git_repo_root_uri
31
+ )
114
32
  rescue StandardError => e
115
33
  raise e
116
34
  end