pwn 0.5.612 → 0.5.613
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 +4 -4
- data/README.md +3 -3
- data/lib/pwn/version.rb +1 -1
- metadata +1 -2
- data/lib/pwn/plugins/zaproxy.rb.bak +0 -837
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0563c6746728c394749e21798be5d36bceea0ce56035d9335c502859d6759e26
|
|
4
|
+
data.tar.gz: 9120b0f1dd304181819f92c818aada0410e3e597cb8b5786014d29af645bf414
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e568e242a20341084cd27c12f899b31125eb7b91c07c0df0b54782798c293b2787ab78fcdd1ff1f751cd7e83f928777586e534e1e3c0a7d7bbf2f0a0dd355dfe
|
|
7
|
+
data.tar.gz: 0e833b7e1ccab11809488dff111ca65c5f41919e7f5f6d62653898f0daf0a72ad86d154814467a74e8b8a2d79c0764a551c616acc1ec2d868b00108878589088
|
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.
|
|
40
|
+
pwn[v0.5.613]:001 >>> PWN.help
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
[](https://youtu.be/G7iLUY4FzsI)
|
|
@@ -52,7 +52,7 @@ $ rvm use ruby-4.0.5@pwn
|
|
|
52
52
|
$ gem uninstall --all --executables pwn
|
|
53
53
|
$ gem install --verbose pwn
|
|
54
54
|
$ pwn
|
|
55
|
-
pwn[v0.5.
|
|
55
|
+
pwn[v0.5.613]: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-4.0.5@pwn
|
|
|
62
62
|
$ rvmsudo gem uninstall --all --executables pwn
|
|
63
63
|
$ rvmsudo gem install --verbose pwn
|
|
64
64
|
$ pwn
|
|
65
|
-
pwn[v0.5.
|
|
65
|
+
pwn[v0.5.613]: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:
|
data/lib/pwn/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.5.613
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 0day Inc.
|
|
@@ -1983,7 +1983,6 @@ files:
|
|
|
1983
1983
|
- lib/pwn/plugins/vsphere.rb
|
|
1984
1984
|
- lib/pwn/plugins/xxd.rb
|
|
1985
1985
|
- lib/pwn/plugins/zaproxy.rb
|
|
1986
|
-
- lib/pwn/plugins/zaproxy.rb.bak
|
|
1987
1986
|
- lib/pwn/reports.rb
|
|
1988
1987
|
- lib/pwn/reports/fuzz.rb
|
|
1989
1988
|
- lib/pwn/reports/html_footer.rb
|
|
@@ -1,837 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'cgi'
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
require 'pty'
|
|
6
|
-
require 'securerandom'
|
|
7
|
-
require 'json'
|
|
8
|
-
require 'uri'
|
|
9
|
-
|
|
10
|
-
module PWN
|
|
11
|
-
module Plugins
|
|
12
|
-
# This plugin converts images to readable text
|
|
13
|
-
# TODO: Convert all rest requests to POST instead of GET
|
|
14
|
-
module Zaproxy
|
|
15
|
-
@@logger = PWN::Plugins::PWNLogger.create
|
|
16
|
-
|
|
17
|
-
# Supported Method Parameters::
|
|
18
|
-
# zap_rest_call(
|
|
19
|
-
# zap_obj: 'required zap_obj returned from #start method',
|
|
20
|
-
# rest_call: 'required rest call to make per the schema',
|
|
21
|
-
# http_method: 'optional HTTP method (defaults to GET)
|
|
22
|
-
# http_body: 'optional HTTP body sent in HTTP methods that support it e.g. POST'
|
|
23
|
-
# )
|
|
24
|
-
|
|
25
|
-
private_class_method def self.zap_rest_call(opts = {})
|
|
26
|
-
zap_obj = opts[:zap_obj]
|
|
27
|
-
rest_call = opts[:rest_call].to_s.scrub
|
|
28
|
-
http_method = opts[:http_method] ||= :get
|
|
29
|
-
http_method = http_method.to_s.downcase.to_sym unless http_method.is_a?(Symbol)
|
|
30
|
-
params = opts[:params]
|
|
31
|
-
http_body = opts[:http_body].to_s.scrub
|
|
32
|
-
|
|
33
|
-
rest_client = zap_obj[:rest_browser]::Request
|
|
34
|
-
mitm_rest_api = zap_obj[:mitm_rest_api]
|
|
35
|
-
|
|
36
|
-
base_zap_api_uri = "http://#{mitm_rest_api}"
|
|
37
|
-
|
|
38
|
-
case http_method
|
|
39
|
-
when :get
|
|
40
|
-
response = rest_client.execute(
|
|
41
|
-
method: :get,
|
|
42
|
-
url: "#{base_zap_api_uri}/#{rest_call}",
|
|
43
|
-
headers: {
|
|
44
|
-
params: params
|
|
45
|
-
},
|
|
46
|
-
verify_ssl: false
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
when :post
|
|
50
|
-
response = rest_client.execute(
|
|
51
|
-
method: :post,
|
|
52
|
-
url: "#{base_zap_api_uri}/#{rest_call}",
|
|
53
|
-
headers: {
|
|
54
|
-
content_type: 'application/json; charset=UTF-8'
|
|
55
|
-
},
|
|
56
|
-
payload: http_body,
|
|
57
|
-
verify_ssl: false
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
else
|
|
61
|
-
raise @@logger.error("Unsupported HTTP Method #{http_method} for #{self} Plugin")
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
sleep 3
|
|
65
|
-
|
|
66
|
-
response
|
|
67
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
68
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
69
|
-
raise e
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Supported Method Parameters::
|
|
73
|
-
# zap_obj = PWN::Plugins::Zaproxy.start(
|
|
74
|
-
# api_key: 'required - api key for API authorization',
|
|
75
|
-
# zap_bin_path: 'optional - path to zap.sh file'
|
|
76
|
-
# headless: 'optional - run zap headless if set to true',
|
|
77
|
-
# browser_type: 'optional - defaults to :firefox. See PWN::Plugins::TransparentBrowser.help for a list of types',
|
|
78
|
-
# proxy: 'optional - change local zap proxy listener (defaults to http://127.0.0.1:<Random 1024-65535>)',
|
|
79
|
-
# )
|
|
80
|
-
|
|
81
|
-
public_class_method def self.start(opts = {})
|
|
82
|
-
zap_obj = {}
|
|
83
|
-
api_key = opts[:api_key]
|
|
84
|
-
raise 'ERROR: api_key must be provided' if api_key.nil?
|
|
85
|
-
|
|
86
|
-
zap_obj[:api_key] = api_key
|
|
87
|
-
|
|
88
|
-
zap_bin_path = opts[:zap_bin_path] ||= '/usr/share/zaproxy/zap.sh'
|
|
89
|
-
raise "ERROR: #{zap_bin_path} not found." unless File.exist?(zap_bin_path)
|
|
90
|
-
|
|
91
|
-
zap_bin = File.basename(zap_bin_path)
|
|
92
|
-
zap_root = File.dirname(zap_bin_path)
|
|
93
|
-
|
|
94
|
-
headless = opts[:headless] || false
|
|
95
|
-
browser_type = opts[:browser_type] ||= :firefox
|
|
96
|
-
browser_type = browser_type.to_s.downcase.to_sym unless browser_type.is_a?(Symbol)
|
|
97
|
-
browser_type = :headless if headless
|
|
98
|
-
zap_ip = opts[:zap_ip] ||= '127.0.0.1'
|
|
99
|
-
zap_port = opts[:zap_port] ||= PWN::Plugins::Sock.get_random_unused_port
|
|
100
|
-
|
|
101
|
-
zap_rest_ip = zap_ip
|
|
102
|
-
zap_rest_port = zap_port
|
|
103
|
-
|
|
104
|
-
browser_obj1 = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)
|
|
105
|
-
rest_browser = browser_obj1[:browser]
|
|
106
|
-
|
|
107
|
-
zap_obj[:mitm_proxy] = "#{zap_ip}:#{zap_port}"
|
|
108
|
-
zap_obj[:mitm_rest_api] = zap_obj[:mitm_proxy]
|
|
109
|
-
zap_obj[:rest_browser] = rest_browser
|
|
110
|
-
|
|
111
|
-
browser_obj2 = PWN::Plugins::TransparentBrowser.open(
|
|
112
|
-
browser_type: browser_type,
|
|
113
|
-
proxy: "http://#{zap_obj[:mitm_proxy]}",
|
|
114
|
-
devtools: true
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
zap_obj[:mitm_browser] = browser_obj2
|
|
118
|
-
|
|
119
|
-
timestamp = Time.now.strftime('%Y-%m-%d_%H-%M-%S%z')
|
|
120
|
-
session_path = "/tmp/zaproxy-#{timestamp}.session"
|
|
121
|
-
zap_obj[:session_path] = session_path
|
|
122
|
-
|
|
123
|
-
if headless
|
|
124
|
-
# TODO: Ensure Default Context still exists and is default context
|
|
125
|
-
zaproxy_cmd = "cd #{zap_root} && ./#{zap_bin} -daemon -newsession #{session_path}"
|
|
126
|
-
else
|
|
127
|
-
zaproxy_cmd = "cd #{zap_root} && ./#{zap_bin} -newsession #{session_path}"
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
zaproxy_cmd = "#{zaproxy_cmd} -host #{zap_ip} -port #{zap_port}"
|
|
131
|
-
|
|
132
|
-
zap_obj[:pid] = Process.spawn(zaproxy_cmd, pgroup: true)
|
|
133
|
-
# Wait for pwn_burp_port to open prior to returning burp_obj
|
|
134
|
-
loop do
|
|
135
|
-
s = TCPSocket.new(zap_rest_ip, zap_rest_port)
|
|
136
|
-
s.close
|
|
137
|
-
break
|
|
138
|
-
rescue Errno::ECONNREFUSED
|
|
139
|
-
print '.'
|
|
140
|
-
sleep 3
|
|
141
|
-
next
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
zap_obj
|
|
145
|
-
rescue Selenium::WebDriver::Error::SessionNotCreatedError, StandardError, SystemExit, Interrupt => e
|
|
146
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
147
|
-
raise e
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
# Supported Method Parameters::
|
|
151
|
-
# PWN::Plugins::Zaproxy.import_openapi_to_sitemap(
|
|
152
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
153
|
-
# openapi_spec: 'required - path to OpenAPI JSON or YAML spec file',
|
|
154
|
-
# additional_http_headers: 'optional - hash of additional HTTP headers to include in requests (default: {})',
|
|
155
|
-
# target_regex: 'optional - url regex to inject additional_http_headers into (e.g. https://test.domain.local.*)'
|
|
156
|
-
# )
|
|
157
|
-
|
|
158
|
-
public_class_method def self.import_openapi_to_sitemap(opts = {})
|
|
159
|
-
zap_obj = opts[:zap_obj]
|
|
160
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
161
|
-
openapi_spec = opts[:openapi_spec]
|
|
162
|
-
raise "ERROR: openapi_spec file #{openapi_spec} does not exist" unless File.exist?(openapi_spec)
|
|
163
|
-
|
|
164
|
-
openapi_spec_root = File.dirname(openapi_spec)
|
|
165
|
-
Dir.chdir(openapi_spec_root)
|
|
166
|
-
|
|
167
|
-
additional_http_headers = opts[:additional_http_headers] ||= {}
|
|
168
|
-
raise 'ERROR: additional_http_headers must be a Hash' unless additional_http_headers.is_a?(Hash)
|
|
169
|
-
|
|
170
|
-
target_regex = opts[:target_regex]
|
|
171
|
-
|
|
172
|
-
if additional_http_headers.any?
|
|
173
|
-
inject_additional_http_headers(
|
|
174
|
-
zap_obj: zap_obj,
|
|
175
|
-
target_regex: target_regex,
|
|
176
|
-
headers: additional_http_headers
|
|
177
|
-
)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
params = {
|
|
181
|
-
apikey: api_key,
|
|
182
|
-
file: openapi_spec
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
response = zap_rest_call(
|
|
186
|
-
zap_obj: zap_obj,
|
|
187
|
-
rest_call: 'JSON/openapi/action/importFile/',
|
|
188
|
-
params: params
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
JSON.parse(response.body, symbolize_names: true)
|
|
192
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
193
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
194
|
-
raise e
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# Supported Method Parameters::
|
|
198
|
-
# json_sitemap = PWN::Plugins::Zaproxy.get_sitemap(
|
|
199
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
200
|
-
# keyword: 'optional - string to search for in the sitemap entries (defaults to nil)',
|
|
201
|
-
# return_as: 'optional - :base64 or :har (defaults to :base64)'
|
|
202
|
-
# )
|
|
203
|
-
|
|
204
|
-
public_class_method def self.get_sitemap(opts = {})
|
|
205
|
-
zap_obj = opts[:zap_obj]
|
|
206
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
207
|
-
keyword = opts[:keyword]
|
|
208
|
-
return_as = opts[:return_as] ||= :base64
|
|
209
|
-
raise 'ERROR: return_as must be :base64 or :har' unless %i[base64 har].include?(return_as)
|
|
210
|
-
|
|
211
|
-
entries = []
|
|
212
|
-
start = 0
|
|
213
|
-
count = 1000
|
|
214
|
-
|
|
215
|
-
# Get all entries in sitemap
|
|
216
|
-
loop do
|
|
217
|
-
params = { apikey: api_key, start: start, count: count }
|
|
218
|
-
|
|
219
|
-
response = zap_rest_call(
|
|
220
|
-
zap_obj: zap_obj,
|
|
221
|
-
rest_call: 'OTHER/exim/other/exportHar/',
|
|
222
|
-
params: params
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
har_data = JSON.parse(response.body, symbolize_names: true)
|
|
226
|
-
new_entries = har_data[:log][:entries]
|
|
227
|
-
break if new_entries.empty?
|
|
228
|
-
|
|
229
|
-
entries += new_entries
|
|
230
|
-
start += count
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
if keyword
|
|
234
|
-
entries = har_sitemap.select do |site|
|
|
235
|
-
json_request = site[:request].to_json
|
|
236
|
-
json_request.include?(keyword)
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
if return_as == :base64
|
|
241
|
-
# Deduplicate entries based on method + url
|
|
242
|
-
base64_entries = []
|
|
243
|
-
entries.each do |entry|
|
|
244
|
-
entry_hash = {}
|
|
245
|
-
req = entry[:request]
|
|
246
|
-
key = [req[:method], req[:url]]
|
|
247
|
-
|
|
248
|
-
# Build full request string
|
|
249
|
-
req_line = "#{req[:method]} #{req[:url]} #{req[:httpVersion]}\r\n"
|
|
250
|
-
req_headers = req[:headers].map { |h| "#{h[:name]}: #{h[:value]}\r\n" }.join
|
|
251
|
-
req_body = ''
|
|
252
|
-
if req[:postData] && req[:postData][:text]
|
|
253
|
-
req_body = req[:postData][:text]
|
|
254
|
-
req_body = Base64.decode64(req_body) if req[:postData][:encoding] == 'base64'
|
|
255
|
-
end
|
|
256
|
-
full_req = "#{req_line}#{req_headers}\r\n#{req_body}".force_encoding('ASCII-8BIT')
|
|
257
|
-
encoded_req = Base64.strict_encode64(full_req)
|
|
258
|
-
|
|
259
|
-
# Build full response string
|
|
260
|
-
res = entry[:response]
|
|
261
|
-
res_line = "#{res[:httpVersion]} #{res[:status]} #{res[:statusText]}\r\n"
|
|
262
|
-
res_headers = res[:headers].map { |h| "#{h[:name]}: #{h[:value]}\r\n" }.join
|
|
263
|
-
res_body = ''
|
|
264
|
-
if res[:content] && res[:content][:text]
|
|
265
|
-
res_body = res[:content][:text]
|
|
266
|
-
res_body = Base64.decode64(res_body) if res[:content][:encoding] == 'base64'
|
|
267
|
-
end
|
|
268
|
-
full_res = "#{res_line}#{res_headers}\r\n#{res_body}".force_encoding('ASCII-8BIT')
|
|
269
|
-
encoded_res = Base64.strict_encode64(full_res)
|
|
270
|
-
|
|
271
|
-
# Extract http_service
|
|
272
|
-
uri = URI.parse(req[:url])
|
|
273
|
-
http_service = {
|
|
274
|
-
host: uri.host,
|
|
275
|
-
port: uri.port,
|
|
276
|
-
protocol: uri.scheme
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
# Add to array
|
|
280
|
-
entry_hash[:request] = encoded_req
|
|
281
|
-
entry_hash[:response] = encoded_res
|
|
282
|
-
entry_hash[:http_service] = http_service
|
|
283
|
-
base64_entries.push(entry_hash)
|
|
284
|
-
end
|
|
285
|
-
entries = base64_entries
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
entries.uniq
|
|
289
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
290
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
291
|
-
raise e
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
# Supported Method Parameters::
|
|
295
|
-
# PWN::Plugins::Zaproxy.add_to_scope(
|
|
296
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
297
|
-
# target_regex: 'required - url regex to add to scope (e.g. https://test.domain.local.*)',
|
|
298
|
-
# context_name: 'optional - context name to add target_regex to (defaults to Default Context)'
|
|
299
|
-
# )
|
|
300
|
-
|
|
301
|
-
public_class_method def self.add_to_scope(opts = {})
|
|
302
|
-
zap_obj = opts[:zap_obj]
|
|
303
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
304
|
-
target_regex = opts[:target_regex]
|
|
305
|
-
raise 'ERROR: target_url must be provided' if target_regex.nil?
|
|
306
|
-
|
|
307
|
-
context_name = opts[:context_name] ||= 'Default Context'
|
|
308
|
-
|
|
309
|
-
params = {
|
|
310
|
-
apikey: api_key,
|
|
311
|
-
contextName: context_name,
|
|
312
|
-
regex: target_regex
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
response = zap_rest_call(
|
|
316
|
-
zap_obj: zap_obj,
|
|
317
|
-
rest_call: 'JSON/context/action/includeInContext/',
|
|
318
|
-
params: params
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
JSON.parse(response.body, symbolize_names: true)
|
|
322
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
323
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
324
|
-
raise e
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
# Supported Method Parameters::
|
|
328
|
-
# PWN::Plugins::Zaproxy.requester(
|
|
329
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
330
|
-
# har_entry: 'required - har entry (e.g. from #get_sitemap method method)',
|
|
331
|
-
# redirect: 'optional - follow redirects if set to true (defaults to false)'
|
|
332
|
-
# )
|
|
333
|
-
|
|
334
|
-
public_class_method def self.requester(opts = {})
|
|
335
|
-
zap_obj = opts[:zap_obj]
|
|
336
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
337
|
-
har_entry = opts[:har_entry]
|
|
338
|
-
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)
|
|
339
|
-
|
|
340
|
-
redirect = opts[:redirect] || false
|
|
341
|
-
raise 'ERROR: redirect must be a boolean' unless redirect.is_a?(TrueClass) || redirect.is_a?(FalseClass)
|
|
342
|
-
|
|
343
|
-
har_json = har_entry.to_json
|
|
344
|
-
params = {
|
|
345
|
-
apikey: api_key,
|
|
346
|
-
request: har_json,
|
|
347
|
-
followRedirects: redirect.to_s
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
response = zap_rest_call(
|
|
351
|
-
zap_obj: zap_obj,
|
|
352
|
-
rest_call: 'OTHER/exim/other/sendHarRequest/',
|
|
353
|
-
params: params
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
JSON.parse(response.body, symbolize_names: true)
|
|
357
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
358
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
359
|
-
raise e
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
# Supported Method Parameters::
|
|
363
|
-
# PWN::Plugins::Zaproxy.spider(
|
|
364
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
365
|
-
# target_url: 'required - url to spider'
|
|
366
|
-
# )
|
|
367
|
-
|
|
368
|
-
public_class_method def self.spider(opts = {})
|
|
369
|
-
zap_obj = opts[:zap_obj]
|
|
370
|
-
target_url = opts[:target_url].to_s.scrub
|
|
371
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
372
|
-
|
|
373
|
-
# target_domain_name = URI.parse(target_url).host
|
|
374
|
-
|
|
375
|
-
params = {
|
|
376
|
-
apikey: api_key,
|
|
377
|
-
url: target_url,
|
|
378
|
-
maxChildren: 9,
|
|
379
|
-
recurse: 3,
|
|
380
|
-
contextName: '',
|
|
381
|
-
subtreeOnly: target_url
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
response = zap_rest_call(
|
|
385
|
-
zap_obj: zap_obj,
|
|
386
|
-
rest_call: 'JSON/spider/action/scan/',
|
|
387
|
-
params: params
|
|
388
|
-
)
|
|
389
|
-
|
|
390
|
-
spider = JSON.parse(response.body, symbolize_names: true)
|
|
391
|
-
spider_id = spider[:scan].to_i
|
|
392
|
-
|
|
393
|
-
loop do
|
|
394
|
-
params = {
|
|
395
|
-
apikey: api_key,
|
|
396
|
-
scanId: spider_id
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
response = zap_rest_call(
|
|
400
|
-
zap_obj: zap_obj,
|
|
401
|
-
rest_call: 'JSON/spider/view/status/',
|
|
402
|
-
params: params
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
spider = JSON.parse(response.body, symbolize_names: true)
|
|
406
|
-
status = spider[:status].to_i
|
|
407
|
-
puts "Spider ID: #{spider_id} => #{status}% Complete"
|
|
408
|
-
break if status == 100
|
|
409
|
-
end
|
|
410
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
411
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
412
|
-
raise e
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
# Supported Method Parameters::
|
|
416
|
-
# PWN::Plugins::Zaproxy.inject_additional_http_headers(
|
|
417
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
418
|
-
# target_regex: 'required - url regex to inject headers into (e.g. https://test.domain.local.*)',
|
|
419
|
-
# headers: 'required - hash of additional headers to inject into each request',
|
|
420
|
-
# )
|
|
421
|
-
|
|
422
|
-
public_class_method def self.inject_additional_http_headers(opts = {})
|
|
423
|
-
zap_obj = opts[:zap_obj]
|
|
424
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
425
|
-
target_regex = opts[:target_regex]
|
|
426
|
-
raise 'ERROR: target_regex must be provided' if target_regex.nil?
|
|
427
|
-
|
|
428
|
-
headers = opts[:headers] ||= {}
|
|
429
|
-
raise 'ERROR: headers must be provided' if headers.empty? || !headers.is_a?(Hash)
|
|
430
|
-
|
|
431
|
-
# Check if replacer rule already exists
|
|
432
|
-
params = { apikey: api_key }
|
|
433
|
-
response = zap_rest_call(
|
|
434
|
-
zap_obj: zap_obj,
|
|
435
|
-
rest_call: 'JSON/replacer/view/rules/',
|
|
436
|
-
params: params
|
|
437
|
-
)
|
|
438
|
-
replacer = JSON.parse(response.body, symbolize_names: true)
|
|
439
|
-
|
|
440
|
-
replacer_resp_arr = []
|
|
441
|
-
headers.each_key do |header_key|
|
|
442
|
-
this_header = { header: header_key }
|
|
443
|
-
rule_exists = replacer[:rules].any? { |rule| rule[:description] == header_key.to_s && rule[:url] == target_regex }
|
|
444
|
-
|
|
445
|
-
if rule_exists
|
|
446
|
-
# Remove existing rule first
|
|
447
|
-
puts "Removing existing replacer rule for header key: #{header_key}..."
|
|
448
|
-
params = {
|
|
449
|
-
apikey: api_key,
|
|
450
|
-
description: header_key
|
|
451
|
-
}
|
|
452
|
-
zap_rest_call(
|
|
453
|
-
zap_obj: zap_obj,
|
|
454
|
-
rest_call: 'JSON/replacer/action/removeRule/',
|
|
455
|
-
params: params
|
|
456
|
-
)
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
puts "Adding replacer rule for header key: #{header_key}..."
|
|
460
|
-
params = {
|
|
461
|
-
apikey: api_key,
|
|
462
|
-
description: header_key,
|
|
463
|
-
enabled: 'true',
|
|
464
|
-
matchType: 'REQ_HEADER',
|
|
465
|
-
matchRegex: 'false',
|
|
466
|
-
matchString: header_key,
|
|
467
|
-
replacement: headers[header_key],
|
|
468
|
-
initiators: '',
|
|
469
|
-
url: target_regex
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
response = zap_rest_call(
|
|
473
|
-
zap_obj: zap_obj,
|
|
474
|
-
rest_call: 'JSON/replacer/action/addRule/',
|
|
475
|
-
params: params
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
json_resp = JSON.parse(response.body, symbolize_names: true)
|
|
479
|
-
this_header[:Result] = json_resp[:Result]
|
|
480
|
-
replacer_resp_arr.push(this_header)
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
replacer_resp_arr
|
|
484
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
485
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
486
|
-
raise e
|
|
487
|
-
end
|
|
488
|
-
|
|
489
|
-
# Supported Method Parameters::
|
|
490
|
-
# PWN::Plugins::Zaproxy.active_scan(
|
|
491
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
492
|
-
# target_url: 'required - url to scan',
|
|
493
|
-
# exclude_paths: 'optional - array of paths to exclude from scan (default: [])',
|
|
494
|
-
# scan_policy: 'optional - scan policy to use (defaults to Default Policy)'
|
|
495
|
-
# )
|
|
496
|
-
|
|
497
|
-
public_class_method def self.active_scan(opts = {})
|
|
498
|
-
zap_obj = opts[:zap_obj]
|
|
499
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
500
|
-
target_url = opts[:target_url]
|
|
501
|
-
raise 'ERROR: target_url must be provided' if target_url.nil?
|
|
502
|
-
|
|
503
|
-
exclude_paths = opts[:exclude_paths] ||= []
|
|
504
|
-
scan_policy = opts[:scan_policy] ||= 'Default Policy'
|
|
505
|
-
|
|
506
|
-
exclude_paths.each do |exclude_path|
|
|
507
|
-
# Remove trailing .* from target_url if it exists
|
|
508
|
-
target_url = target_url.delete_suffix('.*') if target_url.end_with?('.*')
|
|
509
|
-
exclude_path_regex = "#{target_url}#{exclude_path}.*"
|
|
510
|
-
params = {
|
|
511
|
-
apikey: api_key,
|
|
512
|
-
regex: exclude_path_regex
|
|
513
|
-
}
|
|
514
|
-
zap_rest_call(
|
|
515
|
-
zap_obj: zap_obj,
|
|
516
|
-
rest_call: 'JSON/ascan/action/excludeFromScan/',
|
|
517
|
-
params: params
|
|
518
|
-
)
|
|
519
|
-
puts "Excluding #{exclude_path_regex} from Active Scan"
|
|
520
|
-
end
|
|
521
|
-
|
|
522
|
-
# TODO: Implement adding target_url to scope so that inScopeOnly can be changed to true
|
|
523
|
-
params = {
|
|
524
|
-
apikey: api_key,
|
|
525
|
-
url: target_url,
|
|
526
|
-
recurse: true,
|
|
527
|
-
inScopeOnly: true,
|
|
528
|
-
scanPolicyName: scan_policy
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
response = zap_rest_call(
|
|
532
|
-
zap_obj: zap_obj,
|
|
533
|
-
rest_call: 'JSON/ascan/action/scan/',
|
|
534
|
-
params: params
|
|
535
|
-
)
|
|
536
|
-
|
|
537
|
-
active_scan = JSON.parse(response.body, symbolize_names: true)
|
|
538
|
-
active_scan_id = active_scan[:scan].to_i
|
|
539
|
-
|
|
540
|
-
loop do
|
|
541
|
-
params = {
|
|
542
|
-
apikey: api_key,
|
|
543
|
-
scanId: active_scan_id
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
response = zap_rest_call(
|
|
547
|
-
zap_obj: zap_obj,
|
|
548
|
-
rest_call: 'JSON/ascan/view/status/',
|
|
549
|
-
params: params
|
|
550
|
-
)
|
|
551
|
-
|
|
552
|
-
active_scan = JSON.parse(response.body, symbolize_names: true)
|
|
553
|
-
status = active_scan[:status].to_i
|
|
554
|
-
puts "Active Scan ID: #{active_scan_id} => #{status}% Complete"
|
|
555
|
-
break if status == 100
|
|
556
|
-
end
|
|
557
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
558
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
559
|
-
raise e
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
# Supported Method Parameters::
|
|
563
|
-
# PWN::Plugins::Zaproxy.get_alerts(
|
|
564
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
565
|
-
# target_url: 'required - base url to return alerts'
|
|
566
|
-
# )
|
|
567
|
-
|
|
568
|
-
public_class_method def self.get_alerts(opts = {})
|
|
569
|
-
zap_obj = opts[:zap_obj]
|
|
570
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
571
|
-
target_url = opts[:target_url]
|
|
572
|
-
|
|
573
|
-
params = {
|
|
574
|
-
apikey: api_key,
|
|
575
|
-
url: target_url
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
response = zap_rest_call(
|
|
579
|
-
zap_obj: zap_obj,
|
|
580
|
-
rest_call: 'JSON/core/view/alerts/',
|
|
581
|
-
params: params
|
|
582
|
-
)
|
|
583
|
-
|
|
584
|
-
JSON.parse(response.body, symbolize_names: true)
|
|
585
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
586
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
587
|
-
raise e
|
|
588
|
-
end
|
|
589
|
-
|
|
590
|
-
# Supported Method Parameters::
|
|
591
|
-
# report_path = PWN::Plugins::Zaproxy.generate_scan_report(
|
|
592
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
593
|
-
# output_dir: 'required - directory to save report',
|
|
594
|
-
# report_type: 'required - <:html|:markdown|:xml>'
|
|
595
|
-
# )
|
|
596
|
-
|
|
597
|
-
public_class_method def self.generate_scan_report(opts = {})
|
|
598
|
-
zap_obj = opts[:zap_obj]
|
|
599
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
600
|
-
output_dir = opts[:output_dir]
|
|
601
|
-
raise "ERROR: output_dir #{output_dir} does not exist." unless Dir.exist?(output_dir)
|
|
602
|
-
|
|
603
|
-
report_type = opts[:report_type]
|
|
604
|
-
|
|
605
|
-
valid_report_types_arr = %i[html markdown xml]
|
|
606
|
-
raise "ERROR: Invalid report_type => #{report_type}" unless valid_report_types_arr.include?(report_type)
|
|
607
|
-
|
|
608
|
-
case report_type
|
|
609
|
-
when :html
|
|
610
|
-
report_path = "#{output_dir}/zaproxy_active_scan_results.html"
|
|
611
|
-
rest_call = 'OTHER/core/other/htmlreport/'
|
|
612
|
-
when :markdown
|
|
613
|
-
report_path = "#{output_dir}/zaproxy_active_scan_results.md"
|
|
614
|
-
rest_call = 'OTHER/core/other/mdreport/'
|
|
615
|
-
when :xml
|
|
616
|
-
report_path = "#{output_dir}/zaproxy_active_scan_results.xml"
|
|
617
|
-
rest_call = 'OTHER/core/other/xmlreport/'
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
params = {
|
|
621
|
-
apikey: api_key
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
response = zap_rest_call(
|
|
625
|
-
zap_obj: zap_obj,
|
|
626
|
-
rest_call: rest_call,
|
|
627
|
-
params: params
|
|
628
|
-
)
|
|
629
|
-
|
|
630
|
-
File.open(report_path, 'w') do |f|
|
|
631
|
-
f.puts response.body
|
|
632
|
-
end
|
|
633
|
-
|
|
634
|
-
report_path
|
|
635
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
636
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
637
|
-
raise e
|
|
638
|
-
end
|
|
639
|
-
|
|
640
|
-
# Supported Method Parameters::
|
|
641
|
-
# PWN::Plugins::Zaproxy.breakpoint(
|
|
642
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
643
|
-
# regex_type: 'required - :url, :request_header, :request_body, :response_header or :response_body',
|
|
644
|
-
# regex_pattern: 'required - regex pattern to search for respective regex_type',
|
|
645
|
-
# enabled: 'optional - boolean (defaults to true)'
|
|
646
|
-
# )
|
|
647
|
-
|
|
648
|
-
public_class_method def self.breakpoint(opts = {})
|
|
649
|
-
zap_obj = opts[:zap_obj]
|
|
650
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
651
|
-
|
|
652
|
-
case opts[:regex_type].to_sym
|
|
653
|
-
when :url, :request_header, :request_body, :response_header, :response_body
|
|
654
|
-
regex_type = opts[:regex_type].to_sym
|
|
655
|
-
else
|
|
656
|
-
raise "Unknown regex_type: #{opts[:regex_type].to_sym}\noptions are :url, :request_header, :request_body, :response_header or :response_body"
|
|
657
|
-
end
|
|
658
|
-
regex_pattern = opts[:regex_pattern]
|
|
659
|
-
enabled = opts[:enabled]
|
|
660
|
-
|
|
661
|
-
enabled = true if enabled.nil?
|
|
662
|
-
enabled ? (action = 'addHttpBreakpoint') : (action = 'removeHttpBreakpoint')
|
|
663
|
-
|
|
664
|
-
zap_rest_call(
|
|
665
|
-
zap_obj: zap_obj,
|
|
666
|
-
rest_call: "JSON/break/action/#{action}/?zapapiformat=JSON&apikey=#{api_key}&string=#{regex_pattern}&location=#{regex_type}&match=regex&inverse=false&ignorecase=true",
|
|
667
|
-
http_method: :get
|
|
668
|
-
)
|
|
669
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
670
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
671
|
-
raise e
|
|
672
|
-
end
|
|
673
|
-
|
|
674
|
-
# Supported Method Parameters::
|
|
675
|
-
# PWN::Plugins::Zaproxy.tamper(
|
|
676
|
-
# zap_obj: 'required - zap_obj returned from #open method',
|
|
677
|
-
# domain: 'required - FQDN to tamper (e.g. test.domain.local)',
|
|
678
|
-
# enabled: 'optional - boolean (defaults to true)'
|
|
679
|
-
# )
|
|
680
|
-
|
|
681
|
-
public_class_method def self.tamper(opts = {})
|
|
682
|
-
zap_obj = opts[:zap_obj]
|
|
683
|
-
api_key = zap_obj[:api_key].to_s.scrub
|
|
684
|
-
domain = opts[:domain]
|
|
685
|
-
enabled = opts[:enabled]
|
|
686
|
-
|
|
687
|
-
enabled = true if enabled.nil?
|
|
688
|
-
enabled ? (action = 'addHttpBreakpoint') : (action = 'removeHttpBreakpoint')
|
|
689
|
-
|
|
690
|
-
zap_rest_call(
|
|
691
|
-
zap_obj: zap_obj,
|
|
692
|
-
rest_call: "JSON/break/action/#{action}/?zapapiformat=JSON&apikey=#{api_key}&string=#{domain}&location=url&match=contains&inverse=false&ignorecase=true",
|
|
693
|
-
http_method: :get
|
|
694
|
-
)
|
|
695
|
-
|
|
696
|
-
zap_rest_call(
|
|
697
|
-
zap_obj: zap_obj,
|
|
698
|
-
rest_call: "JSON/break/action/break/?zapapiformat=JSON&apikey=#{api_key}&type=http-request&state=#{enabled}",
|
|
699
|
-
http_method: :get
|
|
700
|
-
)
|
|
701
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
702
|
-
stop(zap_obj: zap_obj) unless zap_obj.nil?
|
|
703
|
-
raise e
|
|
704
|
-
end
|
|
705
|
-
|
|
706
|
-
# Supported Method Parameters::
|
|
707
|
-
# PWN::Plugins::Zaproxy.stop(
|
|
708
|
-
# zap_obj: 'required - zap_obj returned from #open method'
|
|
709
|
-
# )
|
|
710
|
-
|
|
711
|
-
public_class_method def self.stop(opts = {})
|
|
712
|
-
zap_obj = opts[:zap_obj]
|
|
713
|
-
api_key = zap_obj[:api_key]
|
|
714
|
-
browser_obj = zap_obj[:mitm_browser]
|
|
715
|
-
|
|
716
|
-
PWN::Plugins::TransparentBrowser.close(browser_obj: browser_obj)
|
|
717
|
-
|
|
718
|
-
params = { apikey: api_key }
|
|
719
|
-
zap_rest_call(
|
|
720
|
-
zap_obj: zap_obj,
|
|
721
|
-
rest_call: 'JSON/core/action/shutdown/',
|
|
722
|
-
params: params
|
|
723
|
-
)
|
|
724
|
-
|
|
725
|
-
session_path = zap_obj[:session_path]
|
|
726
|
-
session_path_files = Dir.glob("#{session_path}*")
|
|
727
|
-
# Remove session files - need to add a slight delay between each unlink to work around file locks
|
|
728
|
-
session_path_files.each do |f|
|
|
729
|
-
FileUtils.rm_f(f)
|
|
730
|
-
sleep 0.3
|
|
731
|
-
end
|
|
732
|
-
|
|
733
|
-
zap_obj = nil
|
|
734
|
-
rescue StandardError, SystemExit, Interrupt => e
|
|
735
|
-
raise e
|
|
736
|
-
end
|
|
737
|
-
|
|
738
|
-
# Author(s):: 0day Inc. <support@0dayinc.com>
|
|
739
|
-
|
|
740
|
-
public_class_method def self.authors
|
|
741
|
-
"AUTHOR(S):
|
|
742
|
-
0day Inc. <support@0dayinc.com>
|
|
743
|
-
"
|
|
744
|
-
end
|
|
745
|
-
|
|
746
|
-
# Display Usage for this Module
|
|
747
|
-
|
|
748
|
-
public_class_method def self.help
|
|
749
|
-
puts "USAGE:
|
|
750
|
-
zap_obj = #{self}.start(
|
|
751
|
-
api_key: 'required - api key for API authorization',
|
|
752
|
-
zap_bin_path: 'optional - path to zap.sh file',
|
|
753
|
-
headless: 'optional - run zap headless if set to true',
|
|
754
|
-
proxy: 'optional - change local zap proxy listener (defaults to http://127.0.0.1:<Random 1024-65535>)'
|
|
755
|
-
)
|
|
756
|
-
|
|
757
|
-
#{self}.spider(
|
|
758
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
759
|
-
target_url: 'required - url to spider'
|
|
760
|
-
)
|
|
761
|
-
|
|
762
|
-
#{self}.import_openapi_to_sitemap(
|
|
763
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
764
|
-
openapi_spec: 'required - path to OpenAPI JSON or YAML spec file',
|
|
765
|
-
additional_http_headers: 'optional - hash of additional HTTP headers to include in requests (default: {})',
|
|
766
|
-
target_regex: 'optional - url regex to inject additional_http_headers into (e.g. https://test.domain.local.*)'
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
#{self}.get_sitemap(
|
|
770
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
771
|
-
keyword: 'optional - string to search for in the sitemap entries (defaults to nil)',
|
|
772
|
-
return_as: 'optional - :base64 or :har (defaults to :base64)'
|
|
773
|
-
)
|
|
774
|
-
|
|
775
|
-
#{self}.add_to_scope(
|
|
776
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
777
|
-
target_regex: 'required - url regex to add to scope (e.g. https://test.domain.local.*)',
|
|
778
|
-
context_name: 'optional - context name to add target_regex to (defaults to Default Context)'
|
|
779
|
-
)
|
|
780
|
-
|
|
781
|
-
#{self}.requester(
|
|
782
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
783
|
-
har_entry: 'required - har entry (e.g. from #get_sitemap method method)',
|
|
784
|
-
redirect: 'optional - follow redirects if set to true (defaults to true)'
|
|
785
|
-
)
|
|
786
|
-
|
|
787
|
-
json_sitemap = #{self}.spider(
|
|
788
|
-
zap_obj: 'required - zap_obj returned from #open method'
|
|
789
|
-
)
|
|
790
|
-
|
|
791
|
-
#{self}.inject_additional_http_headers(
|
|
792
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
793
|
-
target_regex: 'required - url regex to inject headers into (e.g. https://test.domain.local.*)',
|
|
794
|
-
headers: 'required - hash of additional headers to inject into each request'
|
|
795
|
-
)
|
|
796
|
-
|
|
797
|
-
#{self}.active_scan(
|
|
798
|
-
zap_obj: 'required - zap_obj returned from #open method'
|
|
799
|
-
target_url: 'required - url to scan',
|
|
800
|
-
exclude_paths: 'optional - array of paths to exclude from scan (default: [])',
|
|
801
|
-
scan_policy: 'optional - scan policy to use (defaults to Default Policy)'
|
|
802
|
-
)
|
|
803
|
-
|
|
804
|
-
json_alerts = #{self}.get_alerts(
|
|
805
|
-
zap_obj: 'required - zap_obj returned from #open method'
|
|
806
|
-
target_url: 'required - base url to return alerts'
|
|
807
|
-
)
|
|
808
|
-
|
|
809
|
-
report_path = #{self}.generate_scan_report(
|
|
810
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
811
|
-
output_dir: 'required - directory to save report',
|
|
812
|
-
report_type: 'required - <:html|:markdown|:xml>'
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
#{self}.breakpoint(
|
|
816
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
817
|
-
regex_type: 'required - :url, :request_header, :request_body, :response_header or :response_body',
|
|
818
|
-
regex_pattern: 'required - regex pattern to search for respective regex_type',
|
|
819
|
-
enabled: 'optional - boolean (defaults to true)'
|
|
820
|
-
)
|
|
821
|
-
|
|
822
|
-
#{self}.tamper(
|
|
823
|
-
zap_obj: 'required - zap_obj returned from #open method',
|
|
824
|
-
domain: 'required - FQDN to tamper (e.g. test.domain.local)',
|
|
825
|
-
enabled: 'optional - boolean (defaults to true)'
|
|
826
|
-
)
|
|
827
|
-
|
|
828
|
-
#{self}.stop(
|
|
829
|
-
zap_obj: 'required - zap_obj returned from #start method'
|
|
830
|
-
)
|
|
831
|
-
|
|
832
|
-
#{self}.authors
|
|
833
|
-
"
|
|
834
|
-
end
|
|
835
|
-
end
|
|
836
|
-
end
|
|
837
|
-
end
|