pwn 0.5.405 → 0.5.406

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4b31134e90c20f44f69f6b1fbf8b6e4c8e7911bbec857597c729c0801578d5f
4
- data.tar.gz: 8774dc902ef4eadf6d32303cac8efe5fea2a909997a4d7d2c0fdb2e8c137e58a
3
+ metadata.gz: 3a4875ea87dd3f0605bc2ac889621fc124d43016086b2ef914a71dd8104879ff
4
+ data.tar.gz: 68addc891a15eea06b39b9e575fd98ce3b9e5a4d3e490c20bdfbe138699b8f2e
5
5
  SHA512:
6
- metadata.gz: a583c93c1288496cb703e5b4e48a9a70f258c955b05d0dbbf9ffa27b1be25c0d1c2568537379ebe65ae63a423bf31cc022221074e3d8cdbfe100c59739d25099
7
- data.tar.gz: b9b3af817aa7ccd08a05cbc6cbe1107c5760db93b6ec9343a01b74d3b7d992d6f72abe4c11ef5d156f96649268a51b3b1177daa97fff2b04d7c759c781a69884
6
+ metadata.gz: 6b9211d610152046dec2ddcb6c96687085ae3004d104713064831c511e7ce1aa490c5f4e69c12066bc6d11e4f81b47dd90e6b289d5df88a6a5d65abb67d24dd7
7
+ data.tar.gz: e43570d37f21c2a3dc4008da1b42ee0aa379f4aebe5880dd47bb1b4c881a767db74a85b4121a125fbcdb67a4fc7526e239dfb595fd2327dbc0742c67e76027c7
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.405]:001 >>> PWN.help
40
+ pwn[v0.5.406]: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.405]:001 >>> PWN.help
55
+ pwn[v0.5.406]: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.405]:001 >>> PWN.help
65
+ pwn[v0.5.406]: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:
@@ -450,7 +450,7 @@ module PWN
450
450
  raise 'ERROR: burp_obj parameter is required' unless burp_obj.is_a?(Hash)
451
451
 
452
452
  openapi_spec = opts[:openapi_spec]
453
- raise 'ERROR: openapi_spec parameter not found' unless File.exist?(openapi_spec)
453
+ raise 'ERROR: openapi_spec parameter is required' if openapi_spec.nil?
454
454
 
455
455
  additional_http_headers = opts[:additional_http_headers] ||= {}
456
456
  raise 'ERROR: additional_http_headers must be a Hash' unless additional_http_headers.is_a?(Hash)
@@ -1013,6 +1013,31 @@ module PWN
1013
1013
  raise e
1014
1014
  end
1015
1015
 
1016
+ # Supported Method Parameters::
1017
+ # repeater_id = PWN::Plugins::BurpSuite.find_sitemap_entries(
1018
+ # burp_obj: 'required - burp_obj returned by #start method',
1019
+ # search_string: 'required - string to search for in the sitemap entries'
1020
+ # )
1021
+
1022
+ public_class_method def self.find_sitemap_entries(opts = {})
1023
+ burp_obj = opts[:burp_obj]
1024
+ raise 'ERROR: burp_obj parameter is required' unless burp_obj.is_a?(Hash)
1025
+
1026
+ search_string = opts[:search_string]
1027
+ raise 'ERROR: search_string parameter is required' if search_string.nil?
1028
+
1029
+ rest_browser = burp_obj[:rest_browser]
1030
+ mitm_rest_api = burp_obj[:mitm_rest_api]
1031
+
1032
+ json_sitemap = get_sitemap(burp_obj: burp_obj)
1033
+ matching_entries = json_sitemap.select do |entry|
1034
+ decoded_request = Base64.strict_decode64(entry[:request])
1035
+ decoded_request.include?(search_string)
1036
+ end
1037
+ rescue StandardError => e
1038
+ raise e
1039
+ end
1040
+
1016
1041
  # Supported Method Parameters::
1017
1042
  # repeater_id = PWN::Plugins::BurpSuite.add_repeater_tab(
1018
1043
  # burp_obj: 'required - burp_obj returned by #start method',
@@ -171,147 +171,16 @@ module PWN
171
171
  raise e
172
172
  end
173
173
 
174
- # Supported Method Parameters::
175
- # PWN::Plugins::Zaproxy.add_to_scope(
176
- # zap_obj: 'required - zap_obj returned from #open method',
177
- # target_regex: 'required - url regex to add to scope (e.g. https://test.domain.local.*)',
178
- # context_name: 'optional - context name to add target_regex to (defaults to Default Context)'
179
- # )
180
-
181
- public_class_method def self.add_to_scope(opts = {})
182
- zap_obj = opts[:zap_obj]
183
- api_key = zap_obj[:api_key].to_s.scrub
184
- target_regex = opts[:target_regex]
185
- raise 'ERROR: target_url must be provided' if target_regex.nil?
186
-
187
- context_name = opts[:context_name] ||= 'Default Context'
188
-
189
- params = {
190
- apikey: api_key,
191
- contextName: context_name,
192
- regex: target_regex
193
- }
194
-
195
- response = zap_rest_call(
196
- zap_obj: zap_obj,
197
- rest_call: 'JSON/context/action/includeInContext/',
198
- params: params
199
- )
200
-
201
- JSON.parse(response.body, symbolize_names: true)
202
- rescue StandardError, SystemExit, Interrupt => e
203
- stop(zap_obj: zap_obj) unless zap_obj.nil?
204
- raise e
205
- end
206
-
207
- # Supported Method Parameters::
208
- # PWN::Plugins::Zaproxy.add_requester_tab(
209
- # zap_obj: 'required - zap_obj returned from #open method',
210
- # request: 'required - base64 encoded HTTP request (e.g. from #get_sitemap method)'
211
- # )
212
-
213
- public_class_method def self.add_requester_tab(opts = {})
214
- zap_obj = opts[:zap_obj]
215
- api_key = zap_obj[:api_key].to_s.scrub
216
- request = opts[:request]
217
-
218
- dec_request = Base64.strict_decode64(request).force_encoding('ASCII-8BIT')
219
-
220
- # Parse the full request string
221
- parts = dec_request.split("\r\n\r\n", 2)
222
- headers_part = parts[0]
223
- body = parts[1] || ''
224
-
225
- header_lines = headers_part.split("\r\n")
226
- first_line = header_lines.shift
227
- method, full_url, http_version = first_line.split
228
-
229
- headers = []
230
- header_lines.each do |line|
231
- name, value = line.split(': ', 2)
232
- headers << { name: name, value: value }
233
- end
234
-
235
- # Parse URL for queryString and adjust url
236
- uri = URI.parse(full_url)
237
- query_string = []
238
- if uri.query
239
- URI.decode_www_form(uri.query).each do |name, value|
240
- query_string << { name: name, value: value }
241
- end
242
- end
243
- url = "#{uri.scheme}://#{uri.host}"
244
- url += ":#{uri.port}" if uri.port && uri.port != (uri.scheme == 'https' ? 443 : 80)
245
- url += uri.path
246
-
247
- # Determine content-type
248
- content_type_header = headers.find { |h| h[:name].downcase == 'content-type' }
249
- mime_type = content_type_header ? content_type_header[:value] : 'application/octet-stream'
250
-
251
- # Handle postData
252
- post_data = nil
253
- methods_with_body = %w[POST PUT PATCH]
254
- if methods_with_body.include?(method) && !body.empty?
255
- post_data = {
256
- mimeType: mime_type,
257
- params: [],
258
- text: body
259
- }
260
-
261
- temp_body = body.dup.force_encoding('UTF-8')
262
- if temp_body.valid_encoding?
263
- if mime_type.include?('application/x-www-form-urlencoded')
264
- URI.decode_www_form(temp_body).each do |name, value|
265
- post_data[:params] << { name: name, value: value }
266
- end
267
- end
268
- else
269
- post_data[:text] = Base64.encode64(body)
270
- post_data[:encoding] = 'base64'
271
- end
272
- end
273
-
274
- # Construct HAR request
275
- har_request = {
276
- method: method,
277
- url: url,
278
- httpVersion: http_version,
279
- cookies: [],
280
- headers: headers,
281
- queryString: query_string,
282
- headersSize: -1,
283
- bodySize: -1
284
- }
285
- har_request[:postData] = post_data if post_data
286
-
287
- har_json = JSON.generate(har_request)
288
-
289
- params = {
290
- apikey: api_key,
291
- request: har_json,
292
- followRedirects: 'true'
293
- }
294
-
295
- response = zap_rest_call(
296
- zap_obj: zap_obj,
297
- rest_call: 'OTHER/core/other/sendHarRequest/',
298
- params: params
299
- )
300
-
301
- JSON.parse(response.body, symbolize_names: true)
302
- rescue StandardError, SystemExit, Interrupt => e
303
- stop(zap_obj: zap_obj) unless zap_obj.nil?
304
- raise e
305
- end
306
-
307
174
  # Supported Method Parameters::
308
175
  # json_sitemap = PWN::Plugins::Zaproxy.get_sitemap(
309
- # zap_obj: 'required - zap_obj returned from #open method'
176
+ # zap_obj: 'required - zap_obj returned from #open method',
177
+ # return_as: 'optional - :base64 or :har (defaults to :base64)'
310
178
  # )
311
179
 
312
180
  public_class_method def self.get_sitemap(opts = {})
313
181
  zap_obj = opts[:zap_obj]
314
182
  api_key = zap_obj[:api_key].to_s.scrub
183
+ return_as = opts[:return_as] ||= :base64
315
184
 
316
185
  entries = []
317
186
  start = 0
@@ -333,6 +202,7 @@ module PWN
333
202
  entries += new_entries
334
203
  start += count
335
204
  end
205
+ return entries if return_as == :har
336
206
 
337
207
  # Deduplicate entries based on method + url
338
208
  seen = Set.new
@@ -390,6 +260,119 @@ module PWN
390
260
  raise e
391
261
  end
392
262
 
263
+ # Supported Method Parameters::
264
+ # PWN::Plugins::Zaproxy.add_to_scope(
265
+ # zap_obj: 'required - zap_obj returned from #open method',
266
+ # target_regex: 'required - url regex to add to scope (e.g. https://test.domain.local.*)',
267
+ # context_name: 'optional - context name to add target_regex to (defaults to Default Context)'
268
+ # )
269
+
270
+ public_class_method def self.add_to_scope(opts = {})
271
+ zap_obj = opts[:zap_obj]
272
+ api_key = zap_obj[:api_key].to_s.scrub
273
+ target_regex = opts[:target_regex]
274
+ raise 'ERROR: target_url must be provided' if target_regex.nil?
275
+
276
+ context_name = opts[:context_name] ||= 'Default Context'
277
+
278
+ params = {
279
+ apikey: api_key,
280
+ contextName: context_name,
281
+ regex: target_regex
282
+ }
283
+
284
+ response = zap_rest_call(
285
+ zap_obj: zap_obj,
286
+ rest_call: 'JSON/context/action/includeInContext/',
287
+ params: params
288
+ )
289
+
290
+ JSON.parse(response.body, symbolize_names: true)
291
+ rescue StandardError, SystemExit, Interrupt => e
292
+ stop(zap_obj: zap_obj) unless zap_obj.nil?
293
+ raise e
294
+ end
295
+
296
+ # Supported Method Parameters::
297
+ # PWN::Plugins::Zaproxy.find_har_entries(
298
+ # zap_obj: 'required - zap_obj returned from #open method',
299
+ # request: 'required - base64 encoded request or HAR entry :request (e.g. from #get_sitemap method)'
300
+ # )
301
+
302
+ public_class_method def self.find_har_entries(opts = {})
303
+ zap_obj = opts[:zap_obj]
304
+ api_key = zap_obj[:api_key].to_s.scrub
305
+ request = opts[:request]
306
+ raise 'ERROR: request must be provided' if request.nil?
307
+
308
+ har_sitemap = get_sitemap(
309
+ zap_obj: zap_obj,
310
+ return_as: :har
311
+ )
312
+
313
+ # HAR entry
314
+ if request.is_a?(Hash) && request.key?(:method) && request.key?(:url) && request.key?(:httpVersion)
315
+ har_entries = har_sitemap.select { |entry| entry[:request] == request }
316
+ else
317
+ # Base64 encoded string
318
+ dec_request = Base64.strict_decode64(request).force_encoding('ASCII-8BIT') unless dec_request.is_a?(Hash)
319
+
320
+ # Find the har request for the given base64 decoded dec_request value
321
+ har_entries = har_sitemap.select do |entry|
322
+ req = entry[:request]
323
+ req_line = "#{req[:method]} #{req[:url]} #{req[:httpVersion]}\r\n"
324
+ req_headers = req[:headers].map { |h| "#{h[:name]}: #{h[:value]}\r\n" }.join
325
+ req_body = ''
326
+ if req[:postData] && req[:postData][:text]
327
+ req_body = req[:postData][:text]
328
+ req_body = Base64.decode64(req_body) if req[:postData][:encoding] == 'base64'
329
+ end
330
+ full_req = "#{req_line}#{req_headers}\r\n#{req_body}".force_encoding('ASCII-8BIT')
331
+ full_req == dec_request
332
+ end
333
+ end
334
+
335
+ har_entries
336
+ rescue StandardError, SystemExit, Interrupt => e
337
+ stop(zap_obj: zap_obj) unless zap_obj.nil?
338
+ raise e
339
+ end
340
+
341
+ # Supported Method Parameters::
342
+ # PWN::Plugins::Zaproxy.requester(
343
+ # zap_obj: 'required - zap_obj returned from #open method',
344
+ # har_entry: 'required - har entry (e.g. from #get_sitemap method or #find_har_entries method)',
345
+ # redirect: 'optional - follow redirects if set to true (defaults to false)'
346
+ # )
347
+
348
+ public_class_method def self.requester(opts = {})
349
+ zap_obj = opts[:zap_obj]
350
+ api_key = zap_obj[:api_key].to_s.scrub
351
+ har_entry = opts[:har_entry]
352
+ raise 'ERROR: har_entry must be provided and be a valid HAR entry' unless har_entry.is_a?(Hash) && har_entry.key?(:request) && har_entry.key?(:response)
353
+
354
+ redirect = opts[:redirect] || false
355
+ raise 'ERROR: redirect must be a boolean' unless redirect.is_a?(TrueClass) || redirect.is_a?(FalseClass)
356
+
357
+ har_json = har_entry.to_json
358
+ params = {
359
+ apikey: api_key,
360
+ request: har_json,
361
+ followRedirects: redirect.to_s
362
+ }
363
+
364
+ response = zap_rest_call(
365
+ zap_obj: zap_obj,
366
+ rest_call: 'OTHER/exim/other/sendHarRequest/',
367
+ params: params
368
+ )
369
+
370
+ JSON.parse(response.body, symbolize_names: true)
371
+ rescue StandardError, SystemExit, Interrupt => e
372
+ stop(zap_obj: zap_obj) unless zap_obj.nil?
373
+ raise e
374
+ end
375
+
393
376
  # Supported Method Parameters::
394
377
  # PWN::Plugins::Zaproxy.spider(
395
378
  # zap_obj: 'required - zap_obj returned from #open method',
@@ -785,19 +768,26 @@ module PWN
785
768
  openapi_spec: 'required - path to OpenAPI JSON or YAML spec file'
786
769
  )
787
770
 
771
+ #{self}.get_sitemap(
772
+ zap_obj: 'required - zap_obj returned from #open method',
773
+ return_as: 'optional - :base64 or :har (defaults to :base64)'
774
+ )
775
+
788
776
  #{self}.add_to_scope(
789
777
  zap_obj: 'required - zap_obj returned from #open method',
790
778
  target_regex: 'required - url regex to add to scope (e.g. https://test.domain.local.*)',
791
779
  context_name: 'optional - context name to add target_regex to (defaults to Default Context)'
792
780
  )
793
781
 
794
- #{self}.add_requester_tab(
782
+ #{self}.find_har_entries(
795
783
  zap_obj: 'required - zap_obj returned from #open method',
796
- request: 'required - base64 encoded HTTP request (e.g. from #get_sitemap method)'
784
+ request: 'required - base64 encoded request or HAR entry :request (e.g. from #get_sitemap method)'
797
785
  )
798
786
 
799
- #{self}.get_sitemap(
800
- zap_obj: 'required - zap_obj returned from #open method'
787
+ #{self}.requester(
788
+ zap_obj: 'required - zap_obj returned from #open method',
789
+ har_entry: 'required - har entry (e.g. from #get_sitemap method or #find_har_entries method)',
790
+ redirect: 'optional - follow redirects if set to true (defaults to true)'
801
791
  )
802
792
 
803
793
  json_sitemap = #{self}.spider(
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.405'
4
+ VERSION = '0.5.406'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.405
4
+ version: 0.5.406
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.