pwn 0.5.352 → 0.5.354

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/bin/pwn_fuzz_net_app_proto +4 -3
  4. data/bin/pwn_phone +2 -2
  5. data/bin/pwn_sast +1 -2
  6. data/bin/pwn_www_uri_buster +1 -2
  7. data/lib/pwn/plugins/burp_suite.rb +14 -17
  8. data/lib/pwn/plugins/git.rb +3 -3
  9. data/lib/pwn/plugins/sock.rb +2 -2
  10. data/lib/pwn/reports/fuzz.rb +41 -37
  11. data/lib/pwn/reports/phone.rb +50 -30
  12. data/lib/pwn/reports/sast.rb +19 -18
  13. data/lib/pwn/reports/uri_buster.rb +47 -30
  14. data/lib/pwn/sast/amqp_connect_as_guest.rb +2 -2
  15. data/lib/pwn/sast/apache_file_system_util_api.rb +2 -2
  16. data/lib/pwn/sast/aws.rb +2 -2
  17. data/lib/pwn/sast/banned_function_calls_c.rb +2 -2
  18. data/lib/pwn/sast/base64.rb +2 -2
  19. data/lib/pwn/sast/beef_hook.rb +2 -2
  20. data/lib/pwn/sast/cmd_execution_java.rb +2 -2
  21. data/lib/pwn/sast/cmd_execution_python.rb +2 -2
  22. data/lib/pwn/sast/cmd_execution_ruby.rb +2 -2
  23. data/lib/pwn/sast/cmd_execution_scala.rb +2 -2
  24. data/lib/pwn/sast/csrf.rb +2 -2
  25. data/lib/pwn/sast/deserial_java.rb +2 -2
  26. data/lib/pwn/sast/emoticon.rb +2 -2
  27. data/lib/pwn/sast/eval.rb +2 -2
  28. data/lib/pwn/sast/factory.rb +2 -2
  29. data/lib/pwn/sast/http_authorization_header.rb +2 -2
  30. data/lib/pwn/sast/inner_html.rb +2 -2
  31. data/lib/pwn/sast/keystore.rb +2 -2
  32. data/lib/pwn/sast/local_storage.rb +2 -2
  33. data/lib/pwn/sast/location_hash.rb +2 -2
  34. data/lib/pwn/sast/log4j.rb +2 -2
  35. data/lib/pwn/sast/logger.rb +2 -2
  36. data/lib/pwn/sast/md5.rb +2 -2
  37. data/lib/pwn/sast/outer_html.rb +2 -2
  38. data/lib/pwn/sast/padding_oracle.rb +2 -2
  39. data/lib/pwn/sast/password.rb +2 -2
  40. data/lib/pwn/sast/php_input_mechanisms.rb +2 -2
  41. data/lib/pwn/sast/php_type_juggling.rb +2 -2
  42. data/lib/pwn/sast/pom_version.rb +2 -2
  43. data/lib/pwn/sast/port.rb +2 -2
  44. data/lib/pwn/sast/post_message.rb +2 -2
  45. data/lib/pwn/sast/private_key.rb +2 -2
  46. data/lib/pwn/sast/redirect.rb +2 -2
  47. data/lib/pwn/sast/redos.rb +2 -2
  48. data/lib/pwn/sast/shell.rb +2 -2
  49. data/lib/pwn/sast/signature.rb +2 -2
  50. data/lib/pwn/sast/sql.rb +2 -2
  51. data/lib/pwn/sast/ssl.rb +2 -2
  52. data/lib/pwn/sast/sudo.rb +2 -2
  53. data/lib/pwn/sast/task_tag.rb +2 -2
  54. data/lib/pwn/sast/throw_errors.rb +3 -2
  55. data/lib/pwn/sast/token.rb +2 -2
  56. data/lib/pwn/sast/type_script_type_juggling.rb +2 -2
  57. data/lib/pwn/sast/version.rb +2 -2
  58. data/lib/pwn/sast/window_location_hash.rb +2 -2
  59. data/lib/pwn/version.rb +1 -1
  60. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ed1ecac3031877ce2727dca9ed321e834c8a864de719923106c0e4630f88f15
4
- data.tar.gz: ca5dff2fb03d1600932cdc4fad2dafc8ee1f1a4712262306d0a04b52074f552f
3
+ metadata.gz: 8512e5e4d1177bad32c255ef76118b23cf334c579f75c7e89fcf01ffacfc4e4c
4
+ data.tar.gz: f14e9efed8c396aa61ab72a3a60437854c924b694f8c70c793abb2f3536a3260
5
5
  SHA512:
6
- metadata.gz: 5b923dc37f4f57041c2667c1bacf4f7b7cb763fdb0d2528faf647a09c8196793916c1734357f36d69b06afe5daa462103861aab0f81585868b2d10d4bf749a86
7
- data.tar.gz: 9db9f36b6586bcc58f6f825cd6ef3d4484f981df1666985b9d110a683dd521dac24fd9d23ae86b6210f5d26a77467dfc247eb64a376fd582551c254d72715d61
6
+ metadata.gz: 0ea6aed1954cf83f6ad74518aafb11386679e4a387b063b80b8286609c54d634bc9d65528a6fe569dd80ed0581cb1dfbd93b8d463741c68e5807793f8c65d6d9
7
+ data.tar.gz: dc78f00786760d81eeca854594acaa1dbaae3e8401c958458fc3d1ddc01d492b23d42ba9dd4737e35aeca3d661519b35a4ce98f17e814edd1cee9a1f7ab83069
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.352]:001 >>> PWN.help
40
+ pwn[v0.5.354]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
@@ -52,7 +52,7 @@ $ rvm use ruby-3.4.4@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.352]:001 >>> PWN.help
55
+ pwn[v0.5.354]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.4.4@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.352]:001 >>> PWN.help
65
+ pwn[v0.5.354]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pwn'
5
- require 'optparse'
4
+ require 'htmlentities'
6
5
  require 'json'
6
+ require 'optparse'
7
+ require 'pwn'
7
8
 
8
9
  opts = {}
9
10
  OptionParser.new do |options|
@@ -93,7 +94,7 @@ else
93
94
  raise "PWN_PROVIDER env variable is not set to 'ruby-gem' or 'docker'"
94
95
  end
95
96
 
96
- dir_path = opts[:dir_path].to_s.scrub
97
+ dir_path = opts[:dir_path] ||= '.'
97
98
  target = opts[:target]
98
99
  port = opts[:port]
99
100
  protocol = opts[:protocol]
data/bin/pwn_phone CHANGED
@@ -80,8 +80,8 @@ begin
80
80
  seconds_to_record = opts[:seconds_to_record]
81
81
  baresip_bin = opts[:baresip_bin]
82
82
  sox_bin = opts[:sox_bin]
83
- session_root = opts[:session_root]
84
- session_root ||= Dir.pwd
83
+ session_root = opts[:session_root] ||= '.'
84
+ # session_root = opts[:session_root] ||= Dir.pwd
85
85
 
86
86
  # Optional Flag Variables
87
87
  randomize = opts[:randomize]
data/bin/pwn_sast CHANGED
@@ -53,8 +53,7 @@ begin
53
53
  green = "\e[32m"
54
54
  end_of_color = "\e[0m"
55
55
 
56
- dir_path = opts[:dir_path]
57
- dir_path ||= '.'
56
+ dir_path = opts[:dir_path] ||= '.'
58
57
 
59
58
  uri_source_root = opts[:uri_source_root].to_s.scrub
60
59
 
@@ -259,8 +259,7 @@ begin
259
259
 
260
260
  raise 'ERROR: Flags --include-response-codes and --exclude-response-codes cannot be used together.' if include_http_response_codes && exclude_http_response_codes
261
261
 
262
- dir_path = opts[:dir_path]
263
- dir_path ||= '.'
262
+ dir_path = opts[:dir_path] ||= '.'
264
263
 
265
264
  report_name = opts[:report_name]
266
265
  report_name ||= "#{parsed_target_url.host}-#{File.basename(wordlist)}-#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}"
@@ -486,6 +486,12 @@ module PWN
486
486
  end
487
487
 
488
488
  begin
489
+ # Construct HTTP request headers
490
+ request_headers = {
491
+ host: host
492
+ }
493
+ request_headers.merge!(additional_http_headers)
494
+
489
495
  # Combine path-level and operation-level parameters
490
496
  operation_parameters = operation[:parameters].is_a?(Array) ? operation[:parameters] : []
491
497
  all_parameters = path_parameters + operation_parameters
@@ -500,6 +506,13 @@ module PWN
500
506
 
501
507
  param_name = param[:name].to_s
502
508
  case param[:in]
509
+ when 'header'
510
+ # Aggregate remaining HTTP header names from spec,
511
+ # reference as keys, and assign their respective
512
+ # values to the request_headers hash
513
+ param_key = param_name.downcase
514
+ param_value = param[:schema]&.dig(:example) || 'PLACEHOLDER'
515
+ request_headers[param_key] = param_value.to_s
503
516
  when 'path'
504
517
  # Substitute path parameter with a default value (e.g., 'PLACEHOLDER')
505
518
  param_value = param[:schema]&.dig(:example) || 'PLACEHOLDER'
@@ -507,29 +520,13 @@ module PWN
507
520
  when 'query'
508
521
  # Collect query parameters
509
522
  param_value = param[:schema]&.dig(:example) || 'PLACEHOLDER'
510
- query_params << "#{URI.encode_www_form_component(param_name)}=#{URI.encode_www_form_component(param_value.to_s)}"
523
+ query_params.push("#{URI.encode_www_form_component(param_name)}=#{URI.encode_www_form_component(param_value.to_s)}")
511
524
  end
512
525
  end
513
526
 
514
527
  # Append query parameters to path if any
515
528
  request_path += "?#{query_params.join('&')}" if query_params.any?
516
529
 
517
- # Construct HTTP request headers
518
- request_headers = {
519
- host: host
520
- }
521
- request_headers.merge!(additional_http_headers)
522
- # Aggregate remaining HTTP header names from spec,
523
- # reference as keys, and assign their respective
524
- # values to the request_headers hash
525
- operation[:parameters]&.each do |param|
526
- next unless param.is_a?(Hash) && param[:in] == 'header' && param[:name]
527
-
528
- header_name = param[:name].to_s.downcase
529
- header_value = param[:schema]&.dig(:example) || 'PLACEHOLDER'
530
- request_headers[header_name] = header_value.to_s
531
- end
532
-
533
530
  # Construct request lines, including all headers
534
531
  request_lines = [
535
532
  "#{method_str.upcase} #{request_path} HTTP/1.1"
@@ -27,7 +27,7 @@ module PWN
27
27
  git_entity = `git log --since #{since_date} --stat-width=65535 --graph`.to_s.scrub
28
28
  else
29
29
  git_pull_output << "<h3>#{git_repo_name}->#{git_repo_branch} Diff Summary Since Last Pull</h3>"
30
- git_entity = `git log ORIG_HEAD.. --stat-width=65535 --graph`.to_s.scrub
30
+ git_entity = `git log ORIG_HEAD.. --stat-width=65535 --graph 2> /dev/null`.to_s.scrub
31
31
  end
32
32
  # For debugging purposes
33
33
  @@logger.info(git_entity)
@@ -60,7 +60,7 @@ module PWN
60
60
  target_file.gsub!(%r{^#{repo_root}/}, '')
61
61
 
62
62
  if File.directory?(repo_root) && File.file?("#{repo_root}/#{target_file}")
63
- `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" | grep Author | head -n 1`.to_s.scrub
63
+ `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" 2> /dev/null | grep Author | head -n 1`.to_s.scrub
64
64
  else
65
65
  -1
66
66
  end
@@ -75,7 +75,7 @@ module PWN
75
75
 
76
76
  public_class_method def self.dump_all_repo_branches(opts = {})
77
77
  git_url = opts[:git_url].to_s.scrub
78
- `git ls-remote #{git_url}`.to_s.scrub
78
+ `git ls-remote #{git_url} 2> /dev/null`.to_s.scrub
79
79
  rescue StandardError => e
80
80
  raise e
81
81
  end
@@ -13,7 +13,7 @@ module PWN
13
13
  # sock_obj = PWN::Plugins::Sock.connect(
14
14
  # target: 'required - target host or ip',
15
15
  # port: 'required - target port',
16
- # protocol: 'optional - :tcp || :udp (defaults to tcp)',
16
+ # protocol: 'optional - :tcp || :udp (defaults to :tcp)',
17
17
  # tls: 'optional - boolean connect to target socket using TLS (defaults to false)'
18
18
  # )
19
19
 
@@ -31,7 +31,7 @@ module PWN
31
31
 
32
32
  tls_min_version = OpenSSL::SSL::TLS1_VERSION if tls_min_version.nil?
33
33
 
34
- case protocol
34
+ case protocol.to_s.to_sym
35
35
  when :tcp
36
36
  if tls
37
37
  sock = TCPSocket.open(target, port)
@@ -70,17 +70,13 @@ module PWN
70
70
  border-spacing:0px;
71
71
  }
72
72
 
73
- table.squish {
74
- table-layout: fixed;
75
- }
76
-
77
73
  td {
78
74
  vertical-align: top;
79
75
  word-wrap: break-word !important;
80
76
  }
81
77
 
82
- .highlighted {
83
- background-color: #F2F5A9 !important;
78
+ tr.selected td {
79
+ background-color: #FFF396 !important;
84
80
  }
85
81
  </style>
86
82
 
@@ -98,15 +94,18 @@ module PWN
98
94
  &nbsp;~&nbsp;<a href="https://github.com/0dayinc/pwn/tree/master">pwn network fuzzer</a>
99
95
  </h1><br /><br />
100
96
 
101
- <div><button type="button" id="button">Rows Selected</button></div><br />
97
+ <div>
98
+ <button type="button" id="export_selected">Export Selected to JSON</button>
99
+ </div><br />
100
+
102
101
  <div>
103
102
  <b>Toggle Column(s):</b>&nbsp;
104
103
  <a class="toggle-vis" data-column="1" href="#">Timestamp</a>&nbsp;|&nbsp;
105
104
  <a class="toggle-vis" data-column="2" href="#">Request</a>&nbsp;|&nbsp;
106
105
  <a class="toggle-vis" data-column="3" href="#">Request Encoding</a>&nbsp;|&nbsp;
107
- <a class="toggle-vis" data-column="3" href="#">Request Length</a>&nbsp;|&nbsp;
108
- <a class="toggle-vis" data-column="3" href="#">Response</a>&nbsp;|&nbsp;
109
- <a class="toggle-vis" data-column="3" href="#">Response Length</a>&nbsp;|&nbsp;
106
+ <a class="toggle-vis" data-column="4" href="#">Request Length</a>&nbsp;|&nbsp;
107
+ <a class="toggle-vis" data-column="5" href="#">Response</a>&nbsp;|&nbsp;
108
+ <a class="toggle-vis" data-column="6" href="#">Response Length</a>&nbsp;|&nbsp;
110
109
  </div>
111
110
  <br /><br />
112
111
 
@@ -115,7 +114,7 @@ module PWN
115
114
  </div><br />
116
115
 
117
116
  <div>
118
- <table id="pwn_fuzz_net_app_proto" class="display squish" cellspacing="0">
117
+ <table id="pwn_fuzz_net_app_proto" class="display" cellspacing="0">
119
118
  <thead>
120
119
  <tr>
121
120
  <th>#</th>
@@ -141,7 +140,6 @@ module PWN
141
140
  <script>
142
141
  var htmlEntityEncode = $.fn.dataTable.render.text().display;
143
142
 
144
- var line_entry_uri = "";
145
143
  $(document).ready(function() {
146
144
  var oldStart = 0;
147
145
  var table = $('#pwn_fuzz_net_app_proto').DataTable( {
@@ -161,30 +159,21 @@ module PWN
161
159
  $('html,body').animate({scrollTop: targetOffset}, 500);
162
160
  oldStart = oSettings._iDisplayStart;
163
161
  }
164
- // Select individual lines in a row
165
- $('#multi_line_select tbody').on('click', 'tr', function () {
166
- $(this).toggleClass('highlighted');
167
- if ($('#multi_line_select tr.highlighted').length > 0) {
168
- $('#multi_line_select tr td button').attr('disabled', 'disabled');
169
- // Remove multi-line bug button
170
- } else {
171
- $('#multi_line_select tr td button').removeAttr('disabled');
172
- // Add multi-line bug button
173
- }
174
- });
175
162
  },
176
163
  "ajax": "#{report_name}.json",
177
164
  //"deferRender": true,
178
165
  "dom": "fplitfpliS",
179
166
  "autoWidth": false,
180
- "fixedColumns": true,
167
+ "select": {
168
+ "style": "multi"
169
+ },
181
170
  "columnDefs": [
182
171
  {
183
- targets: 3,
172
+ targets: 4,
184
173
  className: 'dt-body-center'
185
174
  },
186
175
  {
187
- targets: 5,
176
+ targets: 6,
188
177
  className: 'dt-body-center'
189
178
  }
190
179
  ],
@@ -277,19 +266,34 @@ module PWN
277
266
  column.visible( ! column.visible() );
278
267
  });
279
268
 
280
- // TODO: Open bug for highlighted rows ;)
281
- $('#button').click( function () {
282
- alert($('#multi_line_select tr.highlighted').length +' row(s) highlighted');
283
- });
284
- });
269
+ $('#export_selected').click( function () {
270
+ var selectedRows = table.rows({ selected: true });
271
+ if (selectedRows.count() === 0) {
272
+ alert('No rows selected');
273
+ return;
274
+ }
285
275
 
286
- function multi_line_select() {
287
- // Select all lines in a row
288
- //$('#pwn_fuzz_net_app_proto tbody').on('click', 'tr', function () {
289
- // $(this).children('td').children('#multi_line_select').children('tbody').children('tr').toggleClass('highlighted');
290
- //});
276
+ $.getJSON(table.ajax.url(), function(original_json) {
277
+ var selected_data = selectedRows.data().toArray();
278
+ original_json.data = selected_data;
291
279
 
292
- }
280
+ if (original_json.report_name) {
281
+ original_json.report_name += '_selected';
282
+ }
283
+
284
+ var json_str = JSON.stringify(original_json, null, 2);
285
+ var blob = new Blob([json_str], { type: 'application/json' });
286
+ var url = URL.createObjectURL(blob);
287
+ var a = document.createElement('a');
288
+ a.href = url;
289
+ a.download = (original_json.report_name || 'selected') + '.json';
290
+ document.body.appendChild(a);
291
+ a.click();
292
+ document.body.removeChild(a);
293
+ URL.revokeObjectURL(url);
294
+ });
295
+ });
296
+ });
293
297
  </script>
294
298
  </body>
295
299
  </html>
@@ -62,17 +62,13 @@ module PWN
62
62
  border-spacing:0px;
63
63
  }
64
64
 
65
- table.squish {
66
- table-layout: fixed;
67
- }
68
-
69
65
  td {
70
66
  vertical-align: top;
71
67
  word-wrap: break-word !important;
72
68
  }
73
69
 
74
- .highlighted {
75
- background-color: #F2F5A9 !important;
70
+ tr.selected td {
71
+ background-color: #FFF396 !important;
76
72
  }
77
73
  </style>
78
74
 
@@ -95,7 +91,11 @@ module PWN
95
91
  </h1><br /><br />
96
92
  <h2 id="report_name"></h2><br />
97
93
 
98
- <div><button type="button" id="button">Rows Selected</button></div><br />
94
+ <div>
95
+ <!--<button type="button" id="button">Rows Selected</button>-->
96
+ <button type="button" id="export_selected">Export Selected to JSON</button>
97
+ </div><br />
98
+
99
99
  <div>
100
100
  <b>Toggle Column(s):</b>&nbsp;
101
101
  <a class="toggle-vis" data-column="1" href="#">Call Started</a>&nbsp;|&nbsp;
@@ -136,13 +136,26 @@ module PWN
136
136
  <th>Waveform</th>
137
137
  </tr>
138
138
  </thead>
139
+ <col width="30px" />
140
+ <col width="60px" />
141
+ <col width="60px" />
142
+ <col width="90px" />
143
+ <col width="60px" />
144
+ <col width="30px" />
145
+ <col width="30px" />
146
+ <col width="60px" />
147
+ <col width="300px" />
148
+ <col width="90px" />
149
+ <col width="300px" />
150
+ <col width="300px" />
151
+ <col width="300px" />
139
152
  <!-- DataTables <tbody> -->
140
153
  </table>
141
154
  </div>
142
155
 
143
156
  <script>
144
157
  var htmlEntityEncode = $.fn.dataTable.render.text().display;
145
- var line_entry_uri = "";
158
+
146
159
  $(document).ready(function() {
147
160
  var oldStart = 0;
148
161
  var table = $('#pwn_phone_results').DataTable( {
@@ -162,22 +175,14 @@ module PWN
162
175
  $('html,body').animate({scrollTop: targetOffset}, 500);
163
176
  oldStart = oSettings._iDisplayStart;
164
177
  }
165
- // Select individual lines in a row
166
- $('#multi_line_select tbody').on('click', 'tr', function () {
167
- $(this).toggleClass('highlighted');
168
- if ($('#multi_line_select tr.highlighted').length > 0) {
169
- $('#multi_line_select tr td button').attr('disabled', 'disabled');
170
- // Remove multi-line bug button
171
- } else {
172
- $('#multi_line_select tr td button').removeAttr('disabled');
173
- // Add multi-line bug button
174
- }
175
- });
176
178
  },
177
179
  "ajax": "#{report_name}.json",
178
180
  //"deferRender": true,
179
181
  "dom": "fplitfpliS",
180
182
  "autoWidth": false,
183
+ "select": {
184
+ "style": "multi"
185
+ },
181
186
  "columns": [
182
187
  { "data": null },
183
188
  {
@@ -318,19 +323,34 @@ module PWN
318
323
  column.visible( ! column.visible() );
319
324
  });
320
325
 
321
- // TODO: Open bug for highlighted rows ;)
322
- $('#button').click( function () {
323
- alert($('#multi_line_select tr.highlighted').length +' row(s) highlighted');
324
- });
325
- });
326
+ $('#export_selected').click( function () {
327
+ var selectedRows = table.rows({ selected: true });
328
+ if (selectedRows.count() === 0) {
329
+ alert('No rows selected');
330
+ return;
331
+ }
326
332
 
327
- function multi_line_select() {
328
- // Select all lines in a row
329
- //$('#pwn_phone_results tbody').on('click', 'tr', function () {
330
- // $(this).children('td').children('#multi_line_select').children('tbody').children('tr').toggleClass('highlighted');
331
- //});
333
+ $.getJSON(table.ajax.url(), function(original_json) {
334
+ var selected_data = selectedRows.data().toArray();
335
+ original_json.data = selected_data;
332
336
 
333
- }
337
+ if (original_json.report_name) {
338
+ original_json.report_name += '_selected';
339
+ }
340
+
341
+ var json_str = JSON.stringify(original_json, null, 2);
342
+ var blob = new Blob([json_str], { type: 'application/json' });
343
+ var url = URL.createObjectURL(blob);
344
+ var a = document.createElement('a');
345
+ a.href = url;
346
+ a.download = (original_json.report_name || 'selected') + '.json';
347
+ document.body.appendChild(a);
348
+ a.click();
349
+ document.body.removeChild(a);
350
+ URL.revokeObjectURL(url);
351
+ });
352
+ });
353
+ });
334
354
  </script>
335
355
  </body>
336
356
  </html>
@@ -98,7 +98,11 @@ module PWN
98
98
  </h1><br /><br />
99
99
  <h2 id="report_name"></h2><br />
100
100
 
101
- <div><button type="button" id="button">Rows Selected</button> <button type="button" id="export_selected">Export Selected to JSON</button></div><br />
101
+ <div>
102
+ <!--<button type="button" id="button">Rows Selected</button>-->
103
+ <button type="button" id="export_selected">Export Selected to JSON</button>
104
+ </div><br />
105
+
102
106
  <div>
103
107
  <b>Toggle Column(s):</b>&nbsp;
104
108
  <a class="toggle-vis" data-column="1" href="#">Timestamp</a>&nbsp;|&nbsp;
@@ -127,12 +131,20 @@ module PWN
127
131
  <th>Test Case (Anti-Pattern) Filter</th>
128
132
  </tr>
129
133
  </thead>
134
+ <col width="30px" />
135
+ <col width="60px" />
136
+ <col width="300px" />
137
+ <col width="90px" />
138
+ <col width="90px" />
139
+ <col width="300px" />
140
+ <col width="90px" />
130
141
  <!-- DataTables <tbody> -->
131
142
  </table>
132
143
  </div>
133
144
 
134
145
  <script>
135
146
  var htmlEntityEncode = $.fn.dataTable.render.text().display;
147
+
136
148
  var line_entry_uri = "";
137
149
  $(document).ready(function() {
138
150
  var oldStart = 0;
@@ -196,17 +208,6 @@ module PWN
196
208
 
197
209
  var filename_link = row.filename;
198
210
 
199
- var bug_comment = 'Timestamp: ' + row.timestamp + '\\n' +
200
- 'Test Case: http://' + window.location.hostname + ':8808/doc_root/pwn-0.1.0/' +
201
- row.security_references['sast_module'].replace(/::/g, "/") + '\\n' +
202
- 'Source Code Impacted: ' + $("<div/>").html(filename_link).text() + '\\n\\n' +
203
- 'Test Case Request:\\n' +
204
- $("<div/>").html(row.test_case_filter.replace(/\\s{2,}/g, " ")).text() + '\\n\\n' +
205
- 'Test Case Response:\\n' +
206
- '\\tCommitted by: ' + $("<div/>").html(data[i]['author']).text() + '\\t' +
207
- data[i]['line_no'] + ': ' +
208
- $("<div/>").html(data[i]['contents'].replace(/\\s{2,}/g, " ")).text() + '\\n\\n';
209
-
210
211
  var author_and_email_arr = data[i]['author'].split(" ");
211
212
  var email = author_and_email_arr[author_and_email_arr.length - 1];
212
213
  var email_user_arr = email.split("@");
@@ -214,13 +215,13 @@ module PWN
214
215
 
215
216
  var uri = '#uri';
216
217
 
217
- var canned_email_results = 'Timestamp: ' + row.timestamp + '\\n' +
218
- 'Source Code File Impacted: ' + $("<div/>").html(filename_link).text() + '\\n\\n' +
219
- 'Source Code in Question:\\n\\n' +
220
- data[i]['line_no'] + ': ' +
221
- $("<div/>").html(data[i]['contents'].replace(/\\s{2,}/g, " ")).text() + '\\n\\n';
218
+ var canned_email_results = 'Timestamp: ' + row.timestamp + '\\n' +
219
+ 'Source Code File Impacted: ' + $("<div/>").html(filename_link).text() + '\\n\\n' +
220
+ 'Source Code in Question:\\n\\n' +
221
+ data[i]['line_no'] + ': ' +
222
+ $("<div/>").html(data[i]['contents'].replace(/\\s{2,}/g, " ")).text() + '\\n\\n';
222
223
 
223
- var canned_email = email.replace("&lt;", "").replace("&gt;", "") + '?subject=Potential%20Bug%20within%20Source%20File:%20'+ encodeURIComponent(row.filename) +'&body=Greetings,%0A%0AThe%20following%20information%20likely%20represents%20a%20bug%20discovered%20through%20automated%20security%20testing%20initiatives:%0A%0A' + encodeURIComponent(canned_email_results) + 'Is%20this%20something%20that%20can%20be%20addressed%20immediately%20or%20would%20filing%20a%20bug%20be%20more%20appropriate?%20%20Please%20let%20us%20know%20at%20your%20earliest%20convenience%20to%20ensure%20we%20can%20meet%20security%20expectations%20for%20this%20release.%20%20Thanks%20and%20have%20a%20great%20day!';
224
+ var canned_email = email.replace("&lt;", "").replace("&gt;", "") + '?subject=Potential%20Bug%20within%20Source%20File:%20'+ encodeURIComponent(row.filename) +'&body=Greetings,%0A%0AThe%20following%20information%20likely%20represents%20a%20bug%20discovered%20through%20automated%20security%20testing%20initiatives:%0A%0A' + encodeURIComponent(canned_email_results) + 'Is%20this%20something%20that%20can%20be%20addressed%20immediately%20or%20would%20filing%20a%20bug%20be%20more%20appropriate?%20%20Please%20let%20us%20know%20at%20your%20earliest%20convenience%20to%20ensure%20we%20can%20meet%20security%20expectations%20for%20this%20release.%20%20Thanks%20and%20have%20a%20great%20day!';
224
225
 
225
226
  domain = line_entry_uri.replace('http://','').replace('https://','').split(/[/?#]/)[0];
226
227
  if (domain.includes('stash') || domain.includes('bitbucket') || domain.includes('gerrit')) {