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 command
9
9
  # execution residing within Java source code.
10
10
  module Log4J
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::Log4J.scan(
15
13
  # dir_path: 'optional path to dir defaults to .'
@@ -19,98 +17,21 @@ 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 -Fin \
39
- -e 'log4j' #{entry} 2> /dev/null
40
- "
41
-
42
- str = `#{test_case_filter}`.to_s.scrub
43
20
 
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
-
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
21
+ test_case_filter = "
22
+ grep -Fin \
23
+ -e 'log4j' {PWN_SAST_SRC_TARGET} 2> /dev/null
24
+ "
92
25
 
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
- )
26
+ include_extensions = %w[.java .class .jar .war .ear .nar .properties .aj .jsp .jspx .jstm .jsptml .jnlp .jad .ser .gsp]
99
27
 
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
28
+ PWN::SAST::TestCaseEngine.execute(
29
+ test_case_filter: test_case_filter,
30
+ security_references: security_references,
31
+ dir_path: dir_path,
32
+ include_extensions: include_extensions,
33
+ git_repo_root_uri: git_repo_root_uri
34
+ )
114
35
  rescue StandardError => e
115
36
  raise e
116
37
  end
@@ -9,8 +9,6 @@ module PWN
9
9
  # artifacts such as passwords, pre-auth tokens, etc are persisted
10
10
  # to log files (which may lead to unauthorized access).
11
11
  module Logger
12
- @@logger = PWN::Plugins::PWNLogger.create
13
-
14
12
  # Supported Method Parameters::
15
13
  # PWN::SAST::Logger.scan(
16
14
  # dir_path: 'optional path to dir defaults to .'
@@ -20,112 +18,32 @@ 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 '.warn' \
41
- -e '.info' \
42
- -e '.error' \
43
- -e '.debug' #{entry} > /dev/null | grep -i \
44
- -e log | grep -i \
45
- -e pass \
46
- -e pwd \
47
- -e saml \
48
- -e uri \
49
- -e url \
50
- -e auth \
51
- -e cred \
52
- -e token \
53
- -e session \
54
- -e key
55
- "
56
-
57
- str = `#{test_case_filter}`.to_s.scrub
58
-
59
- if str.to_s.empty?
60
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
61
- logger_results = "#{logger_results}~" # Catching bugs is good :)
62
- else
63
- 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
64
21
 
65
- hash_line = {
66
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
67
- security_references: security_references,
68
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
69
- line_no_and_contents: '',
70
- raw_content: str,
71
- test_case_filter: test_case_filter
72
- }
73
-
74
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
75
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
76
- line_no_count = line_contents_split.length # This should always be an even number
77
- current_count = 0
78
- while line_no_count > current_count
79
- line_no = line_contents_split[current_count]
80
- contents = line_contents_split[current_count + 1]
81
- if Dir.exist?('.git')
82
- repo_root = '.'
83
-
84
- author = PWN::Plugins::Git.get_author(
85
- repo_root: repo_root,
86
- from_line: line_no,
87
- to_line: line_no,
88
- target_file: entry,
89
- entry_beautified: entry_beautified
90
- )
91
- end
92
- author ||= 'N/A'
93
-
94
- ai_analysis = nil
95
- if ai_introspection
96
- request = {
97
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
98
- line_no: line_no,
99
- source_code_snippet: contents
100
- }.to_json
101
- response = PWN::AI::Introspection.reflect(request: request)
102
- if response.is_a?(Hash)
103
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
104
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
105
- end
106
- end
107
-
108
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
109
- line_no: line_no,
110
- contents: contents,
111
- author: author,
112
- ai_analysis: ai_analysis
113
- )
22
+ test_case_filter = "
23
+ grep -Fin \
24
+ -e '.warn' \
25
+ -e '.info' \
26
+ -e '.error' \
27
+ -e '.debug' {PWN_SAST_SRC_TARGET} > /dev/null | grep -i \
28
+ -e log | grep -i \
29
+ -e pass \
30
+ -e pwd \
31
+ -e saml \
32
+ -e uri \
33
+ -e url \
34
+ -e auth \
35
+ -e cred \
36
+ -e token \
37
+ -e session \
38
+ -e key
39
+ "
114
40
 
115
- current_count += 2
116
- end
117
- result_arr.push(hash_line)
118
- logger_results = "#{logger_results}x" # Seeing progress is good :)
119
- end
120
- end
121
- end
122
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
123
- if logger_results.empty?
124
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
125
- else
126
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
127
- end
128
- result_arr
41
+ PWN::SAST::TestCaseEngine.execute(
42
+ test_case_filter: test_case_filter,
43
+ security_references: security_references,
44
+ dir_path: dir_path,
45
+ git_repo_root_uri: git_repo_root_uri
46
+ )
129
47
  rescue StandardError => e
130
48
  raise e
131
49
  end
data/lib/pwn/sast/md5.rb CHANGED
@@ -8,8 +8,6 @@ module PWN
8
8
  # SAST Module used to identify MD5 hash related objects, methods, classes, etc.
9
9
  # to determine if deprecated hashing is still supported.
10
10
  module MD5
11
- @@logger = PWN::Plugins::PWNLogger.create
12
-
13
11
  # Supported Method Parameters::
14
12
  # PWN::SAST::MD5.scan(
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 -in \
39
- -e 'md5' #{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 -in \
23
+ -e 'md5' {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
@@ -9,8 +9,6 @@ module PWN
9
9
  # declarations within source code in an effort to
10
10
  # determine if XSS is possible.
11
11
  module OuterHTML
12
- @@logger = PWN::Plugins::PWNLogger.create
13
-
14
12
  # Supported Method Parameters::
15
13
  # PWN::SAST::OuterHTML.scan(
16
14
  # dir_path: 'optional path to dir defaults to .'
@@ -20,98 +18,18 @@ 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 -n \
40
- -e 'outerHTML' #{entry} 2> /dev/null
41
- "
42
-
43
- str = `#{test_case_filter}`.to_s.scrub
44
-
45
- if str.to_s.empty?
46
- # If str length is >= 64 KB do not include results. (Due to Mongo Document Size Restrictions)
47
- logger_results = "#{logger_results}~" # Catching bugs is good :)
48
- else
49
- 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
50
21
 
51
- hash_line = {
52
- timestamp: Time.now.strftime('%Y-%m-%d %H:%M:%S.%9N %z').to_s,
53
- security_references: security_references,
54
- filename: { git_repo_root_uri: git_repo_root_uri, entry: entry },
55
- line_no_and_contents: '',
56
- raw_content: str,
57
- test_case_filter: test_case_filter
58
- }
59
-
60
- # COMMMENT: Must be a better way to implement this (regex is kinda funky)
61
- line_contents_split = str.split(/^(\d{1,}):|\n(\d{1,}):/)[1..-1]
62
- line_no_count = line_contents_split.length # This should always be an even number
63
- current_count = 0
64
- while line_no_count > current_count
65
- line_no = line_contents_split[current_count]
66
- contents = line_contents_split[current_count + 1]
67
- if Dir.exist?('.git')
68
- repo_root = '.'
69
-
70
- author = PWN::Plugins::Git.get_author(
71
- repo_root: repo_root,
72
- from_line: line_no,
73
- to_line: line_no,
74
- target_file: entry,
75
- entry_beautified: entry_beautified
76
- )
77
- end
78
- author ||= 'N/A'
79
-
80
- ai_analysis = nil
81
- if ai_introspection
82
- request = {
83
- scm_uri: "#{hash_line[:filename][:git_repo_root_uri]}/#{hash_line[:filename][:entry]}",
84
- line_no: line_no,
85
- source_code_snippet: contents
86
- }.to_json
87
- response = PWN::AI::Introspection.reflect(request: request)
88
- if response.is_a?(Hash)
89
- ai_analysis = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
90
- ai_analysis = response[:choices].last[:content] if response[:choices].last.keys.include?(:content)
91
- end
92
- end
93
-
94
- hash_line[:line_no_and_contents] = line_no_and_contents_arr.push(
95
- line_no: line_no,
96
- contents: contents,
97
- author: author,
98
- ai_analysis: ai_analysis
99
- )
22
+ test_case_filter = "
23
+ grep -n \
24
+ -e 'outerHTML' {PWN_SAST_SRC_TARGET} 2> /dev/null
25
+ "
100
26
 
101
- current_count += 2
102
- end
103
- result_arr.push(hash_line)
104
- logger_results = "#{logger_results}x" # Seeing progress is good :)
105
- end
106
- end
107
- end
108
- logger_banner = "http://#{Socket.gethostname}:8808/doc_root/pwn-#{PWN::VERSION.to_s.scrub}/#{to_s.scrub.gsub('::', '/')}.html"
109
- if logger_results.empty?
110
- @@logger.info("#{logger_banner}: No files applicable to this test case.\n")
111
- else
112
- @@logger.info("#{logger_banner} => #{logger_results}complete.\n")
113
- end
114
- result_arr
27
+ PWN::SAST::TestCaseEngine.execute(
28
+ test_case_filter: test_case_filter,
29
+ security_references: security_references,
30
+ dir_path: dir_path,
31
+ git_repo_root_uri: git_repo_root_uri
32
+ )
115
33
  rescue StandardError => e
116
34
  raise e
117
35
  end
@@ -7,8 +7,6 @@ module PWN
7
7
  module SAST
8
8
  # SAST Module used to identify padding oracle vulnerabilities involving weak CBC block cipher padding.
9
9
  module PaddingOracle
10
- @@logger = PWN::Plugins::PWNLogger.create
11
-
12
10
  # Supported Method Parameters::
13
11
  # PWN::SAST::PaddingOracle.scan(
14
12
  # dir_path: 'optional path to dir defaults to .'
@@ -18,99 +16,19 @@ module PWN
18
16
  public_class_method def self.scan(opts = {})
19
17
  dir_path = opts[:dir_path]
20
18
  git_repo_root_uri = opts[:git_repo_root_uri].to_s.scrub
21
- result_arr = []
22
- ai_introspection = PWN::Env[:ai][:introspection]
23
- logger_results = "AI Introspection => #{ai_introspection} => "
24
-
25
- PWN::Plugins::FileFu.recurse_in_dir(dir_path: dir_path) do |entry|
26
- if File.file?(entry) && File.basename(entry) !~ /^pwn.+(html|json|db)$/ && File.basename(entry) !~ /\.JS-BEAUTIFIED$/ && entry !~ /test/i
27
- line_no_and_contents_arr = []
28
- entry_beautified = false
29
-
30
- if File.extname(entry) == '.js' && (`wc -l #{entry}`.split.first.to_i < 20 || entry.include?('.min.js') || entry.include?('-all.js'))
31
- js_beautify = `js-beautify #{entry} > #{entry}.JS-BEAUTIFIED 2> /dev/null`.to_s.scrub
32
- entry = "#{entry}.JS-BEAUTIFIED"
33
- entry_beautified = true
34
- end
35
-
36
- # TODO: Include regex to search for weak CBC block cipher padding
37
- test_case_filter = "
38
- grep -Ein \
39
- -e 'AES/CBC/PKCS' #{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
19
 
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
- )
20
+ # TODO: Include regex to search for weak CBC block cipher padding
21
+ test_case_filter = "
22
+ grep -Ein \
23
+ -e 'AES/CBC/PKCS' {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