pwn 0.5.494 → 0.5.495
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/.rubocop.yml +3 -3
- data/Gemfile +5 -5
- data/README.md +3 -3
- data/lib/pwn/ai/introspection.rb +7 -4
- data/lib/pwn/ai/open_ai.rb +4 -8
- data/lib/pwn/config.rb +1 -0
- data/lib/pwn/plugins/burp_suite.rb +62 -29
- data/lib/pwn/plugins/transparent_browser.rb +223 -143
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/hacker_one.rb +29 -0
- metadata +11 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60c64fa5b4751ee72882a87e666c22ca826bb94bab63f0dca925a92520241afd
|
|
4
|
+
data.tar.gz: 6ddf3436eca29081e4d53f81183555d80daaf847ebab4b9f6174114372bcde63
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25a82f578e16c23fbf958e353381c39f0ec9126a6d254c51849620b42d68012024f987cacbbf79790889bd282936f13c8ae8fba060b39b3bd2738e44270f76f7
|
|
7
|
+
data.tar.gz: 378c9b00d02d832aa820c4cf53cb09c01949d3a1ff2e7f4fd2d6e17833d84266d9a6be6a1fb5f2e792335a90b21ae88e42c574f2fb152d8b0bf74b56ab672112
|
data/.rubocop.yml
CHANGED
|
@@ -14,13 +14,13 @@ Metrics/BlockNesting:
|
|
|
14
14
|
Metrics/ClassLength:
|
|
15
15
|
Max: 134
|
|
16
16
|
Metrics/CyclomaticComplexity:
|
|
17
|
-
Max:
|
|
17
|
+
Max: 158
|
|
18
18
|
Metrics/MethodLength:
|
|
19
19
|
Max: 565
|
|
20
20
|
Metrics/ModuleLength:
|
|
21
|
-
Max:
|
|
21
|
+
Max: 1133
|
|
22
22
|
Metrics/PerceivedComplexity:
|
|
23
|
-
Max:
|
|
23
|
+
Max: 157
|
|
24
24
|
Style/HashEachMethods:
|
|
25
25
|
Enabled: true
|
|
26
26
|
Style/HashSyntax:
|
data/Gemfile
CHANGED
|
@@ -11,14 +11,14 @@ gemspec
|
|
|
11
11
|
# In some circumstances custom flags are passed to gems in order
|
|
12
12
|
# to build appropriately. Defer to ./reinstall_pwn_gemset.sh
|
|
13
13
|
# to review these custom flags (e.g. pg, serialport, etc).
|
|
14
|
-
gem 'activesupport', '<8.1.
|
|
14
|
+
gem 'activesupport', '<8.1.1'
|
|
15
15
|
gem 'anemone', '0.7.2'
|
|
16
16
|
gem 'authy', '3.0.1'
|
|
17
17
|
gem 'aws-sdk', '3.3.0'
|
|
18
18
|
gem 'barby', '0.7.0'
|
|
19
19
|
gem 'base32', '0.3.4'
|
|
20
20
|
gem 'bitcoin-ruby', '0.0.20'
|
|
21
|
-
gem 'brakeman', '7.1.
|
|
21
|
+
gem 'brakeman', '7.1.1'
|
|
22
22
|
gem 'bson', '5.2.0'
|
|
23
23
|
gem 'bundler', '>=2.7.2'
|
|
24
24
|
gem 'bundler-audit', '0.9.2'
|
|
@@ -70,17 +70,17 @@ gem 'pdf-reader', '2.15.0'
|
|
|
70
70
|
gem 'pg', '1.6.2'
|
|
71
71
|
gem 'pry', '0.15.2'
|
|
72
72
|
gem 'pry-doc', '1.6.0'
|
|
73
|
-
gem 'rake', '13.3.
|
|
73
|
+
gem 'rake', '13.3.1'
|
|
74
74
|
gem 'rb-readline', '0.5.5'
|
|
75
75
|
gem 'rbvmomi2', '3.8.0'
|
|
76
|
-
gem 'rdoc', '6.15.
|
|
76
|
+
gem 'rdoc', '6.15.1'
|
|
77
77
|
gem 'rest-client', '2.1.0'
|
|
78
78
|
gem 'rex', '2.0.13'
|
|
79
79
|
gem 'rmagick', '6.1.4'
|
|
80
80
|
gem 'rqrcode', '3.1.0'
|
|
81
81
|
gem 'rspec', '3.13.2'
|
|
82
82
|
gem 'rtesseract', '3.1.4'
|
|
83
|
-
gem 'rubocop', '1.81.
|
|
83
|
+
gem 'rubocop', '1.81.7'
|
|
84
84
|
gem 'rubocop-rake', '0.7.1'
|
|
85
85
|
gem 'rubocop-rspec', '3.7.0'
|
|
86
86
|
gem 'ruby-audio', '1.6.1'
|
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.495]:001 >>> PWN.help
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
[](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.
|
|
55
|
+
pwn[v0.5.495]: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.
|
|
65
|
+
pwn[v0.5.495]: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/ai/introspection.rb
CHANGED
|
@@ -11,7 +11,8 @@ module PWN
|
|
|
11
11
|
# Supported Method Parameters::
|
|
12
12
|
# response = PWN::AI::Introspection.reflect_on(
|
|
13
13
|
# request: 'required - String - What you want the AI to reflect on',
|
|
14
|
-
# system_role_content: 'optional - context to set up the model behavior for reflection'
|
|
14
|
+
# system_role_content: 'optional - context to set up the model behavior for reflection',
|
|
15
|
+
# spinner: 'optional - Boolean - Display spinner during operation (default: false)'
|
|
15
16
|
# )
|
|
16
17
|
|
|
17
18
|
public_class_method def self.reflect_on(opts = {})
|
|
@@ -20,6 +21,8 @@ module PWN
|
|
|
20
21
|
|
|
21
22
|
system_role_content = opts[:system_role_content]
|
|
22
23
|
|
|
24
|
+
spinner = opts[:spinner] || false
|
|
25
|
+
|
|
23
26
|
response = nil
|
|
24
27
|
|
|
25
28
|
ai_introspection = PWN::Env[:ai][:introspection]
|
|
@@ -34,7 +37,7 @@ module PWN
|
|
|
34
37
|
response = PWN::AI::Grok.chat(
|
|
35
38
|
request: request.chomp,
|
|
36
39
|
system_role_content: system_role_content,
|
|
37
|
-
spinner:
|
|
40
|
+
spinner: spinner
|
|
38
41
|
)
|
|
39
42
|
response = response[:choices].last[:content] if response.is_a?(Hash) &&
|
|
40
43
|
response.key?(:choices) &&
|
|
@@ -43,7 +46,7 @@ module PWN
|
|
|
43
46
|
response = PWN::AI::Ollama.chat(
|
|
44
47
|
request: request.chomp,
|
|
45
48
|
system_role_content: system_role_content,
|
|
46
|
-
spinner:
|
|
49
|
+
spinner: spinner
|
|
47
50
|
)
|
|
48
51
|
response = response[:choices].last[:content] if response.is_a?(Hash) &&
|
|
49
52
|
response.key?(:choices) &&
|
|
@@ -52,7 +55,7 @@ module PWN
|
|
|
52
55
|
response = PWN::AI::OpenAI.chat(
|
|
53
56
|
request: request.chomp,
|
|
54
57
|
system_role_content: system_role_content,
|
|
55
|
-
spinner:
|
|
58
|
+
spinner: spinner
|
|
56
59
|
)
|
|
57
60
|
if response.is_a?(Hash) && response.key?(:choices)
|
|
58
61
|
response = response[:choices].last[:text] if response[:choices].last.keys.include?(:text)
|
data/lib/pwn/ai/open_ai.rb
CHANGED
|
@@ -158,16 +158,12 @@ module PWN
|
|
|
158
158
|
case model
|
|
159
159
|
when 'gpt-3.5-turbo', 'gpt-3.5-turbo-0125', 'gpt-3.5-turbo-1106', 'gpt-3.5-turbo-instruct',
|
|
160
160
|
'gpt-4-turbo', 'gpt-4-turbo-2024-04-09', 'gpt-4-turbo-preview', 'gpt-4-0125-preview', 'gpt-4-1106-preview'
|
|
161
|
-
max_completion_tokens = 4_096
|
|
161
|
+
max_completion_tokens = 4_096
|
|
162
162
|
when 'gpt-4', 'gpt-4-0613', 'gpt-4-0314',
|
|
163
163
|
'gpt-4o', 'gpt-4o-2024-05-13'
|
|
164
|
-
max_completion_tokens = 8_192
|
|
165
|
-
|
|
166
|
-
max_completion_tokens = 16_384
|
|
167
|
-
when 'o1-preview', 'o1-preview-2024-09-12'
|
|
168
|
-
max_completion_tokens = 32_768 - (request.to_s.length / 4)
|
|
169
|
-
when 'o1-mini', 'o1-mini-2024-09-12'
|
|
170
|
-
max_completion_tokens = 65_536 - (request.to_s.length / 4)
|
|
164
|
+
max_completion_tokens = 8_192
|
|
165
|
+
else
|
|
166
|
+
max_completion_tokens = 16_384
|
|
171
167
|
end
|
|
172
168
|
|
|
173
169
|
response_history = opts[:response_history]
|
data/lib/pwn/config.rb
CHANGED
|
@@ -108,12 +108,20 @@ module PWN
|
|
|
108
108
|
next
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
#
|
|
112
|
-
|
|
111
|
+
# Delete existing proxy listener and add new one
|
|
112
|
+
# in favor of weird update behavior in event the port is alread in use
|
|
113
|
+
# by another application which refuses to enable the listener even when
|
|
114
|
+
# the port is changed via the update method.
|
|
115
|
+
delete_proxy_listener(
|
|
113
116
|
burp_obj: burp_obj,
|
|
114
|
-
id:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
id: 0
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
add_proxy_listener(
|
|
121
|
+
burp_obj: burp_obj,
|
|
122
|
+
bindAddress: burp_ip,
|
|
123
|
+
port: burp_port,
|
|
124
|
+
enabled: true
|
|
117
125
|
)
|
|
118
126
|
|
|
119
127
|
burp_obj
|
|
@@ -270,7 +278,7 @@ module PWN
|
|
|
270
278
|
# Supported Method Parameters::
|
|
271
279
|
# json_proxy_listener = PWN::Plugins::BurpSuite.add_proxy_listener(
|
|
272
280
|
# burp_obj: 'required - burp_obj returned by #start method',
|
|
273
|
-
#
|
|
281
|
+
# bindAddress: 'required - bind address for the proxy listener (e.g., "127.0.0.1")',
|
|
274
282
|
# port: 'required - port for the proxy listener (e.g., 8081)',
|
|
275
283
|
# enabled: 'optional - enable the listener (defaults to true)'
|
|
276
284
|
# )
|
|
@@ -279,8 +287,8 @@ module PWN
|
|
|
279
287
|
burp_obj = opts[:burp_obj]
|
|
280
288
|
rest_browser = burp_obj[:rest_browser]
|
|
281
289
|
mitm_rest_api = burp_obj[:mitm_rest_api]
|
|
282
|
-
bind_address = opts[:
|
|
283
|
-
raise 'ERROR:
|
|
290
|
+
bind_address = opts[:bindAddress]
|
|
291
|
+
raise 'ERROR: bindAddress parameter is required' if bind_address.nil?
|
|
284
292
|
|
|
285
293
|
port = opts[:port]
|
|
286
294
|
raise 'ERROR: port parameter is required' if port.nil?
|
|
@@ -288,12 +296,14 @@ module PWN
|
|
|
288
296
|
enabled = opts[:enabled] != false # Default to true if not specified
|
|
289
297
|
|
|
290
298
|
proxy_listeners = get_proxy_listeners(burp_obj: burp_obj)
|
|
291
|
-
|
|
299
|
+
puts "Proxy Listeners: #{proxy_listeners.inspect}"
|
|
300
|
+
last_known_proxy_id = 0
|
|
301
|
+
last_known_proxy_id = proxy_listeners.last[:id].to_i if proxy_listeners.any?
|
|
292
302
|
next_id = last_known_proxy_id + 1
|
|
293
303
|
|
|
294
304
|
post_body = {
|
|
295
305
|
id: next_id.to_s,
|
|
296
|
-
|
|
306
|
+
bindAddress: bind_address,
|
|
297
307
|
port: port,
|
|
298
308
|
enabled: enabled
|
|
299
309
|
}.to_json
|
|
@@ -308,24 +318,29 @@ module PWN
|
|
|
308
318
|
# Supported Method Parameters::
|
|
309
319
|
# json_proxy_listener = PWN::Plugins::BurpSuite.update_proxy_listener(
|
|
310
320
|
# burp_obj: 'required - burp_obj returned by #start method',
|
|
311
|
-
# id: 'optional - ID of the proxy listener (defaults to
|
|
312
|
-
#
|
|
313
|
-
# port: 'optional - port for the proxy listener (defaults to
|
|
314
|
-
# enabled: 'optional - enable or disable the listener (defaults to
|
|
321
|
+
# id: 'optional - ID of the proxy listener (defaults to 0)',
|
|
322
|
+
# bindAddress: 'optional - bind address for the proxy listener (defaults to value of existing listener)',
|
|
323
|
+
# port: 'optional - port for the proxy listener (defaults to value of existing listener)',
|
|
324
|
+
# enabled: 'optional - enable or disable the listener (defaults to value of existing listener)'
|
|
315
325
|
# )
|
|
316
326
|
|
|
317
327
|
public_class_method def self.update_proxy_listener(opts = {})
|
|
318
328
|
burp_obj = opts[:burp_obj]
|
|
319
329
|
rest_browser = burp_obj[:rest_browser]
|
|
320
330
|
mitm_rest_api = burp_obj[:mitm_rest_api]
|
|
321
|
-
id = opts[:id] ||=
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
331
|
+
id = opts[:id] ||= 0
|
|
332
|
+
|
|
333
|
+
proxy_listeners = get_proxy_listeners(burp_obj: burp_obj)
|
|
334
|
+
listener_by_id = proxy_listeners.find { |listener| listener[:id].to_i == id.to_i }
|
|
335
|
+
raise "ERROR: No proxy listener found with ID #{id}" if listener_by_id.nil?
|
|
336
|
+
|
|
337
|
+
bind_address = opts[:bindAddress] ||= listener_by_id[:bindAddress]
|
|
338
|
+
port = opts[:port] ||= listener_by_id[:port]
|
|
339
|
+
enabled = opts[:enabled] ||= listener_by_id[:enabled]
|
|
325
340
|
|
|
326
341
|
post_body = {
|
|
327
|
-
id: id,
|
|
328
|
-
|
|
342
|
+
id: id.to_s,
|
|
343
|
+
bindAddress: bind_address,
|
|
329
344
|
port: port,
|
|
330
345
|
enabled: enabled
|
|
331
346
|
}.to_json
|
|
@@ -340,15 +355,17 @@ module PWN
|
|
|
340
355
|
# Supported Method Parameters::
|
|
341
356
|
# PWN::Plugins::BurpSuite.delete_proxy_listener(
|
|
342
357
|
# burp_obj: 'required - burp_obj returned by #start method',
|
|
343
|
-
# id: '
|
|
358
|
+
# id: 'optional - ID of the proxy listener (defaults to 0)'
|
|
344
359
|
# )
|
|
345
360
|
|
|
346
361
|
public_class_method def self.delete_proxy_listener(opts = {})
|
|
347
362
|
burp_obj = opts[:burp_obj]
|
|
348
363
|
rest_browser = burp_obj[:rest_browser]
|
|
349
364
|
mitm_rest_api = burp_obj[:mitm_rest_api]
|
|
350
|
-
id = opts[:id] ||=
|
|
351
|
-
|
|
365
|
+
id = opts[:id] ||= 0
|
|
366
|
+
proxy_listeners = get_proxy_listeners(burp_obj: burp_obj)
|
|
367
|
+
listener_by_id = proxy_listeners.find { |listener| listener[:id].to_i == id.to_i }
|
|
368
|
+
raise "ERROR: No proxy listener found with ID #{id}" if listener_by_id.nil?
|
|
352
369
|
|
|
353
370
|
rest_browser.delete("http://#{mitm_rest_api}/proxy/listeners/#{id}")
|
|
354
371
|
true # Return true to indicate successful deletion (or error if API fails)
|
|
@@ -567,6 +584,22 @@ module PWN
|
|
|
567
584
|
sitemap = opts[:sitemap] ||= {}
|
|
568
585
|
debug = opts[:debug] || false
|
|
569
586
|
|
|
587
|
+
decoded_sitemap = {
|
|
588
|
+
request: Base64.strict_decode64(sitemap[:request]),
|
|
589
|
+
http_service: {
|
|
590
|
+
host: sitemap[:http_service][:host],
|
|
591
|
+
port: sitemap[:http_service][:port],
|
|
592
|
+
protocol: sitemap[:http_service][:protocol]
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
system_role_content = 'Your sole purpose is to analyze each `protocol`, `host`, `port`, and `request` and generate an Exploit Prediction Scoring System (EPSS) score from 0%-100%. Just generate a score unless the score is >= 75% in which a PoC should also be generated to communicate the threat. You can always generate an score - provide the score at _the beggining of your analysis_. Be concise and to the point.'
|
|
596
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
597
|
+
system_role_content: system_role_content,
|
|
598
|
+
request: decoded_sitemap.to_json,
|
|
599
|
+
spinner: true
|
|
600
|
+
)
|
|
601
|
+
sitemap[:comment] = ai_analysis unless ai_analysis.nil?
|
|
602
|
+
|
|
570
603
|
rest_client = rest_browser::Request
|
|
571
604
|
response = rest_client.execute(
|
|
572
605
|
method: :post,
|
|
@@ -1484,22 +1517,22 @@ module PWN
|
|
|
1484
1517
|
|
|
1485
1518
|
json_proxy_listener = #{self}.add_proxy_listener(
|
|
1486
1519
|
burp_obj: 'required - burp_obj returned by #start method',
|
|
1487
|
-
|
|
1520
|
+
bindAddress: 'required - bind address for the proxy listener (e.g., \"127.0.0.1\")',
|
|
1488
1521
|
port: 'required - port for the proxy listener (e.g., 8081)',
|
|
1489
1522
|
enabled: 'optional - enable the listener (defaults to true)'
|
|
1490
1523
|
)
|
|
1491
1524
|
|
|
1492
1525
|
json_proxy_listener = #{self}.update_proxy_listener(
|
|
1493
1526
|
burp_obj: 'required - burp_obj returned by #start method',
|
|
1494
|
-
id: 'optional - ID of the proxy listener (defaults to
|
|
1495
|
-
|
|
1496
|
-
port: '
|
|
1497
|
-
enabled: 'optional - enable the listener (defaults to
|
|
1527
|
+
id: 'optional - ID of the proxy listener (defaults to 0)',
|
|
1528
|
+
bindAddress: 'optional - bind address for the proxy listener (defaults to value of existing listener)',
|
|
1529
|
+
port: 'optional - port for the proxy listener (defaults to value of existing listener)',
|
|
1530
|
+
enabled: 'optional - enable the listener (defaults to value of existing listener)'
|
|
1498
1531
|
)
|
|
1499
1532
|
|
|
1500
1533
|
#{self}.delete_proxy_listener(
|
|
1501
1534
|
burp_obj: 'required - burp_obj returned by #start method',
|
|
1502
|
-
id: '
|
|
1535
|
+
id: 'optional - ID of the proxy listener (defaults to 0)'
|
|
1503
1536
|
)
|
|
1504
1537
|
|
|
1505
1538
|
json_sitemap = #{self}.get_sitemap(
|
|
@@ -190,11 +190,6 @@ module PWN
|
|
|
190
190
|
args.push("--proxy-server=#{proxy}")
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
-
if devtools
|
|
194
|
-
args.push('--auto-open-devtools-for-tabs')
|
|
195
|
-
args.push('--disable-hang-monitor')
|
|
196
|
-
end
|
|
197
|
-
|
|
198
193
|
# Incognito browsing mode
|
|
199
194
|
args.push('--incognito')
|
|
200
195
|
options = Selenium::WebDriver::Chrome::Options.new(
|
|
@@ -202,6 +197,13 @@ module PWN
|
|
|
202
197
|
accept_insecure_certs: true
|
|
203
198
|
)
|
|
204
199
|
|
|
200
|
+
if devtools
|
|
201
|
+
args.push('--auto-open-devtools-for-tabs')
|
|
202
|
+
args.push('--disable-hang-monitor')
|
|
203
|
+
options.add_preference('devtools.preferences.enable-ignore-listing', false)
|
|
204
|
+
options.add_preference('devtools.preferences.default-indentation', '2 spaces')
|
|
205
|
+
end
|
|
206
|
+
|
|
205
207
|
# This is required for BiDi support
|
|
206
208
|
options.web_socket_url = true
|
|
207
209
|
options.add_preference('remote.active-protocols', 3)
|
|
@@ -1148,69 +1150,150 @@ module PWN
|
|
|
1148
1150
|
raise 'ERROR: action parameter must be :enable|:pause|:resume|:disable' unless valid_actions.include?(action)
|
|
1149
1151
|
|
|
1150
1152
|
devtools = browser_obj[:devtools]
|
|
1151
|
-
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
|
1153
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state) || {}
|
|
1154
|
+
breakpoint_arr = debugger_state[:breakpoints] || []
|
|
1152
1155
|
|
|
1153
1156
|
method = nil
|
|
1154
1157
|
case action
|
|
1155
1158
|
when :enable
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1159
|
+
devtools.dom.enable
|
|
1160
|
+
devtools.log.disable
|
|
1161
|
+
devtools.network.disable
|
|
1162
|
+
devtools.page.disable
|
|
1163
|
+
devtools.runtime.disable
|
|
1164
|
+
|
|
1165
|
+
method = 'Debugger.scriptParsed'
|
|
1166
|
+
callbacks_to_delete = devtools.callbacks.keys.reject { |k| k == 'Target.atta`chedToTarget' }
|
|
1167
|
+
# until devtools.callbacks.keys.include?(method) && breakpoint_arr.any?
|
|
1168
|
+
until breakpoint_arr.any?
|
|
1169
|
+
callbacks_to_delete.each { |method| devtools.callbacks.delete(method) }
|
|
1170
|
+
breakpoint_set = false
|
|
1171
|
+
# devtools.dom.disable
|
|
1172
|
+
devtools.debugger.disable
|
|
1173
|
+
devtools.debugger.on(:script_parsed) do |params|
|
|
1174
|
+
url = params['url']
|
|
1175
|
+
next if breakpoint_set || url.include?('devtools://') || url.empty?
|
|
1176
|
+
|
|
1177
|
+
breakpoint_set = true
|
|
1178
|
+
puts url
|
|
1179
|
+
bcmd = 'Debugger.setBreakpoint'
|
|
1180
|
+
script_id = params['scriptId']
|
|
1181
|
+
line = params['startLine']
|
|
1182
|
+
column = params['startColumn']
|
|
1183
|
+
location = { scriptId: script_id, lineNumber: line, columnNumber: column }
|
|
1184
|
+
breakpoint = devtools.send_cmd(bcmd, location: location)
|
|
1185
|
+
breakpoint['result']['breakpointId'] = "#{bcmd}.#{script_id}.#{line}.#{column}.#{SecureRandom.uuid}"
|
|
1186
|
+
breakpoint['id'] = breakpoint['id'].to_s
|
|
1187
|
+
breakpoint['url'] = url
|
|
1188
|
+
breakpoint['caught'] = false
|
|
1189
|
+
breakpoint_arr.push(breakpoint)
|
|
1190
|
+
debugger_state[:breakpoints] = breakpoint_arr
|
|
1191
|
+
devtools.instance_variable_set(:@debugger_state, debugger_state)
|
|
1192
|
+
|
|
1193
|
+
puts "Breakpoint set in #{url} at line #{line}, column #{column}: #{breakpoint}"
|
|
1194
|
+
puts params.inspect
|
|
1161
1195
|
end
|
|
1162
|
-
debugger_state = {}
|
|
1163
|
-
breakpoint_arr = []
|
|
1164
|
-
|
|
1165
1196
|
devtools.debugger.enable
|
|
1166
|
-
ws_msg = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1167
|
-
method = ws_msg['method']
|
|
1168
|
-
|
|
1169
|
-
bcmd = 'EventBreakpoints.setInstrumentationBreakpoint'
|
|
1170
|
-
event = 'load'
|
|
1171
|
-
breakpoint = devtools.send_cmd(bcmd, eventName: event)
|
|
1172
|
-
breakpoint['result']['breakpointId'] = "#{bcmd}.#{event}.#{SecureRandom.uuid}"
|
|
1173
|
-
# bcmd = 'Debugger.setInstrumentationBreakpoint'
|
|
1174
|
-
# instrumentation = 'beforeScriptExecution'
|
|
1175
|
-
# breakpoint = devtools.send_cmd(bcmd, instrumentation: instrumentation)
|
|
1176
|
-
# breakpoint['result']['breakpointId'] = "#{bcmd}.#{instrumentation}.#{SecureRandom.uuid}"
|
|
1177
|
-
breakpoint_arr.push(breakpoint)
|
|
1178
|
-
debugger_state[:breakpoints] = breakpoint_arr
|
|
1179
|
-
|
|
1180
|
-
devtools.runtime.disable
|
|
1181
|
-
devtools.log.disable
|
|
1182
|
-
devtools.network.disable
|
|
1183
|
-
devtools.page.disable
|
|
1184
|
-
puts debugger_state.inspect
|
|
1185
1197
|
end
|
|
1198
|
+
devtools.callbacks.delete(method)
|
|
1199
|
+
method = 'Debugger.enabled'
|
|
1186
1200
|
when :pause
|
|
1187
|
-
|
|
1188
|
-
|
|
1201
|
+
method = 'Debugger.paused'
|
|
1202
|
+
callbacks_to_delete = devtools.callbacks.keys.reject { |k| k == 'Target.attachedToTarget' }
|
|
1203
|
+
Timeout.timeout(30) { browser_obj[:browser].refresh }
|
|
1204
|
+
until devtools.callbacks.keys.include?(method) && breakpoint_arr.any? { |bp| bp['caught'] == true }
|
|
1205
|
+
callbacks_to_delete.each { |method| devtools.callbacks.delete(method) }
|
|
1206
|
+
devtools.debugger.on(:paused) do |params|
|
|
1207
|
+
breakpoint_id_caught = params['callFrames'].first['location']['scriptId']
|
|
1208
|
+
breakpoint_arr.each_with_index do |bp, idx|
|
|
1209
|
+
next unless bp['id'] == breakpoint_id_caught
|
|
1210
|
+
|
|
1211
|
+
bp['caught'] = true
|
|
1212
|
+
breakpoint_arr[idx] = bp
|
|
1213
|
+
debugger_state[:breakpoints] = breakpoint_arr
|
|
1214
|
+
devtools.instance_variable_set(:@debugger_state, debugger_state)
|
|
1215
|
+
end
|
|
1216
|
+
puts "TARGET BREAKPOINTS: #{breakpoint_arr.inspect}"
|
|
1217
|
+
puts "PARAMS Observerd: #{params.inspect}"
|
|
1218
|
+
end
|
|
1189
1219
|
devtools.debugger.pause
|
|
1190
|
-
|
|
1191
|
-
|
|
1220
|
+
# browser_obj[:browser].refresh
|
|
1221
|
+
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
|
1222
|
+
breakpoint_arr = debugger_state[:breakpoints]
|
|
1192
1223
|
end
|
|
1224
|
+
devtools.callbacks.delete(method)
|
|
1193
1225
|
when :resume
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
end
|
|
1226
|
+
method = 'Debugger.resumed'
|
|
1227
|
+
callbacks_to_delete = devtools.callbacks.keys.reject { |k| k == 'Target.attachedToTarget' }
|
|
1228
|
+
callbacks_to_delete.each { |method| devtools.callbacks.delete(method) }
|
|
1229
|
+
devtools.debugger.resume until devtools.callbacks.keys.include?(method)
|
|
1199
1230
|
when :disable
|
|
1200
|
-
|
|
1201
|
-
|
|
1231
|
+
callbacks_to_delete = devtools.callbacks.keys.reject { |k| k == 'Target.attachedToTarget' }
|
|
1232
|
+
callbacks_to_delete.each { |method| devtools.callbacks.delete(method) }
|
|
1202
1233
|
devtools.debugger.disable
|
|
1234
|
+
method = 'Debugger.disabled'
|
|
1203
1235
|
end
|
|
1204
1236
|
|
|
1205
|
-
debugger_state[:method] = method
|
|
1206
|
-
devtools.instance_variable_set(:@debugger_state, debugger_state) if debugger_state.is_a?(Hash)
|
|
1207
|
-
devtools
|
|
1208
|
-
rescue Timeout::Error
|
|
1209
1237
|
devtools
|
|
1210
1238
|
rescue Selenium::WebDriver::Error::WebDriverError => e
|
|
1211
1239
|
puts e.message
|
|
1212
1240
|
rescue StandardError => e
|
|
1213
1241
|
raise e
|
|
1242
|
+
ensure
|
|
1243
|
+
debugger_state[:method] = method
|
|
1244
|
+
devtools.instance_variable_set(:@debugger_state, debugger_state) if debugger_state.is_a?(Hash)
|
|
1245
|
+
end
|
|
1246
|
+
|
|
1247
|
+
# Supported Method Parameters::
|
|
1248
|
+
# page_state_arr = PWN::Plugins::TransparentBrowser.get_targets(
|
|
1249
|
+
# browser_obj: 'required - browser_obj returned from #open method)'
|
|
1250
|
+
# )
|
|
1251
|
+
|
|
1252
|
+
public_class_method def self.get_targets(opts = {})
|
|
1253
|
+
browser_obj = opts[:browser_obj]
|
|
1254
|
+
supported = %i[chrome headless_chrome]
|
|
1255
|
+
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
|
1256
|
+
puts 'This browser is not supported for DevTools operations.' unless verified
|
|
1257
|
+
return unless verified
|
|
1258
|
+
|
|
1259
|
+
devtools = browser_obj[:devtools]
|
|
1260
|
+
bcmd = 'Target.getTargets'
|
|
1261
|
+
devtools.send_cmd(bcmd)
|
|
1262
|
+
rescue StandardError => e
|
|
1263
|
+
raise e
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
# Supported Method Parameters::
|
|
1267
|
+
# page_state_arr = PWN::Plugins::TransparentBrowser.breakpoint_locations(
|
|
1268
|
+
# browser_obj: 'required - browser_obj returned from #open method)'
|
|
1269
|
+
# )
|
|
1270
|
+
|
|
1271
|
+
public_class_method def self.breakpoint_locations(opts = {})
|
|
1272
|
+
browser_obj = opts[:browser_obj]
|
|
1273
|
+
supported = %i[chrome headless_chrome]
|
|
1274
|
+
verified = verify_devtools_browser(browser_obj: browser_obj, supported: supported)
|
|
1275
|
+
puts 'This browser is not supported for DevTools operations.' unless verified
|
|
1276
|
+
return unless verified
|
|
1277
|
+
|
|
1278
|
+
valid_methods = %w[Debugger.scriptParsed Debugger.paused Debugger.resumed]
|
|
1279
|
+
devtools = browser_obj[:devtools]
|
|
1280
|
+
ws_msg = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1281
|
+
method = ws_msg['method']
|
|
1282
|
+
raise "ERROR: Unsupported method: #{method}" unless valid_methods.include?(method)
|
|
1283
|
+
|
|
1284
|
+
case method
|
|
1285
|
+
when 'Debugger.resumed', 'Debugger.paused'
|
|
1286
|
+
script_id = ws_msg['params']['callFrames'].first['location']['scriptId'].to_s
|
|
1287
|
+
when 'Debugger.scriptParsed'
|
|
1288
|
+
script_id = ws_msg['params']['scriptId'].to_s
|
|
1289
|
+
end
|
|
1290
|
+
|
|
1291
|
+
puts "Method: #{method}"
|
|
1292
|
+
puts "Fetching possible breakpoints for script ID: #{script_id}..."
|
|
1293
|
+
bcmd = 'Debugger.getPossibleBreakpoints'
|
|
1294
|
+
devtools.send_cmd(bcmd, start: { scriptId: script_id, lineNumber: 0, columnNumber: 0 })
|
|
1295
|
+
rescue StandardError => e
|
|
1296
|
+
raise e
|
|
1214
1297
|
end
|
|
1215
1298
|
|
|
1216
1299
|
# Supported Method Parameters::
|
|
@@ -1236,119 +1319,116 @@ module PWN
|
|
|
1236
1319
|
steps = 1 if steps.zero? || steps.negative?
|
|
1237
1320
|
|
|
1238
1321
|
devtools = browser_obj[:devtools]
|
|
1322
|
+
ws_msg = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1323
|
+
method = ws_msg['method']
|
|
1324
|
+
|
|
1239
1325
|
debugger_state = devtools.instance_variable_get(:@debugger_state)
|
|
1240
|
-
method =
|
|
1241
|
-
|
|
1242
|
-
puts 'The debugger must be paused before stepping. Pausing now...'
|
|
1243
|
-
return devtools
|
|
1244
|
-
end
|
|
1326
|
+
debugger_state[:method] = method
|
|
1327
|
+
devtools.instance_variable_set(:@debugger_state, debugger_state)
|
|
1245
1328
|
|
|
1246
|
-
|
|
1329
|
+
valid_methods = %w[Debugger.scriptParsed Debugger.paused Debugger.resumed]
|
|
1330
|
+
devtools = browser_obj[:devtools]
|
|
1331
|
+
ws_msg = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1332
|
+
method = ws_msg['method']
|
|
1333
|
+
raise "ERROR: Unsupported method: #{method}" unless valid_methods.include?(method)
|
|
1247
1334
|
|
|
1248
|
-
|
|
1335
|
+
steps_arr = []
|
|
1336
|
+
cursor_termination_chars = %w[; , . ( ) { } = |]
|
|
1249
1337
|
steps.times do |s|
|
|
1250
1338
|
step_num = s + 1
|
|
1251
1339
|
puts "Stepping #{action} (step #{step_num}/#{steps})..."
|
|
1252
1340
|
|
|
1253
|
-
|
|
1254
|
-
# puts before.inspect
|
|
1255
|
-
before = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1256
|
-
method = before['method']
|
|
1257
|
-
# puts before
|
|
1258
|
-
puts "\n"
|
|
1259
|
-
|
|
1260
|
-
if method == 'Debugger.paused'
|
|
1261
|
-
before_location = before['params']['callFrames'].first['location']
|
|
1262
|
-
start_location = before['params']['callFrames'].first['scopeChain'].first['startLocation']
|
|
1263
|
-
before_script_id = start_location['scriptId']
|
|
1264
|
-
from_line_num = start_location['lineNumber']
|
|
1265
|
-
from_column_num = start_location['columnNumber']
|
|
1266
|
-
|
|
1267
|
-
end_location = before['params']['callFrames'].first['scopeChain'].first['endLocation']
|
|
1268
|
-
to_line_num = end_location['lineNumber']
|
|
1269
|
-
to_column_num = end_location['columnNumber']
|
|
1270
|
-
|
|
1271
|
-
source_obj = devtools.debugger.get_script_source(script_id: before_script_id)
|
|
1272
|
-
source_code = source_obj['result']['scriptSource']
|
|
1273
|
-
# puts source_code
|
|
1274
|
-
# gets
|
|
1275
|
-
|
|
1276
|
-
source_lines = source_code.split("\n")
|
|
1277
|
-
source_lines_str = source_lines[from_line_num..to_line_num].join("\n")
|
|
1278
|
-
source_to_review = source_lines_str[from_column_num..to_column_num]
|
|
1279
|
-
source_before = source_to_review.dup
|
|
1280
|
-
|
|
1281
|
-
if source_to_review.length.positive?
|
|
1282
|
-
puts source_to_review
|
|
1283
|
-
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
1284
|
-
system_role_content: system_role_content,
|
|
1285
|
-
request: source_to_review
|
|
1286
|
-
)
|
|
1287
|
-
puts "^^^ #{ai_analysis}" unless ai_analysis.nil?
|
|
1288
|
-
# gets
|
|
1289
|
-
end
|
|
1290
|
-
end
|
|
1291
|
-
|
|
1341
|
+
method = 'Debugger.resumed'
|
|
1292
1342
|
case action
|
|
1293
1343
|
when :into
|
|
1294
|
-
devtools.debugger.step_into
|
|
1344
|
+
devtools.debugger.step_into until devtools.callbacks.keys.include?(method)
|
|
1295
1345
|
when :out
|
|
1296
|
-
devtools.debugger.step_out
|
|
1346
|
+
devtools.debugger.step_out until devtools.callbacks.keys.include?(method)
|
|
1297
1347
|
when :over
|
|
1298
|
-
devtools.debugger.step_over
|
|
1348
|
+
devtools.debugger.step_over until devtools.callbacks.keys.include?(method)
|
|
1299
1349
|
end
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1350
|
+
devtools.callbacks.delete(method)
|
|
1351
|
+
|
|
1352
|
+
method = 'Debugger.paused'
|
|
1353
|
+
devtools.debugger.pause until devtools.callbacks.keys.include?(method)
|
|
1354
|
+
devtools.callbacks.delete(method)
|
|
1355
|
+
|
|
1356
|
+
ws_msg = devtools_websocket_messages(browser_obj: browser_obj)
|
|
1357
|
+
ws_msg_params = ws_msg['params']
|
|
1358
|
+
ws_msg_call_frames = ws_msg_params['callFrames'].first
|
|
1359
|
+
ws_msg_scope_chain_local = ws_msg_call_frames['scopeChain'].find { |scope| scope['type'] == 'local' }
|
|
1360
|
+
next unless ws_msg_scope_chain_local.is_a?(Hash)
|
|
1361
|
+
|
|
1362
|
+
ws_msg_scope_chain_block = ws_msg_call_frames['scopeChain'].find { |scope| scope['type'] == 'block' }
|
|
1363
|
+
|
|
1364
|
+
cursor_location = ws_msg_call_frames['location']
|
|
1365
|
+
cursor_line_num = cursor_location['lineNumber']
|
|
1366
|
+
cursor_column_num = cursor_location['columnNumber']
|
|
1367
|
+
|
|
1368
|
+
script_id = cursor_location['scriptId']
|
|
1369
|
+
|
|
1370
|
+
start_location = ws_msg_scope_chain_local['startLocation']
|
|
1371
|
+
start_line_num = start_location['lineNumber']
|
|
1372
|
+
start_column_num = start_location['columnNumber']
|
|
1373
|
+
|
|
1374
|
+
end_location = ws_msg_scope_chain_local['endLocation']
|
|
1375
|
+
# end_location_block = ws_msg_scope_chain_block['endLocation']
|
|
1376
|
+
# puts "TEST: #{end_location - end_location_block}"
|
|
1377
|
+
end_line_num = end_location['lineNumber']
|
|
1378
|
+
end_column_num = end_location['columnNumber']
|
|
1379
|
+
|
|
1380
|
+
source_obj = devtools.debugger.get_script_source(script_id: script_id)
|
|
1381
|
+
full_source_code = source_obj['result']['scriptSource']
|
|
1382
|
+
|
|
1383
|
+
source_lines = full_source_code.split("\n")
|
|
1384
|
+
# puts source_lines.inspect
|
|
1385
|
+
source_lines_range = source_lines[start_line_num..end_line_num]
|
|
1386
|
+
next if source_lines_range.nil?
|
|
1387
|
+
|
|
1388
|
+
source_lines_str = source_lines_range.join("\n")
|
|
1389
|
+
source_to_review = source_lines_str[start_column_num..end_column_num]
|
|
1390
|
+
current_step = source_lines_str[cursor_column_num..end_column_num]
|
|
1391
|
+
|
|
1392
|
+
# TODO: leverage ANSI escape codes to highlight current_step to red
|
|
1393
|
+
# puts ws_msg.inspect
|
|
1394
|
+
# puts "\n"
|
|
1395
|
+
# puts ws_msg_call_frames['scopeChain'].inspect
|
|
1396
|
+
# puts "\n"
|
|
1397
|
+
cursor_terminated = false
|
|
1398
|
+
source_to_review.each_char.with_index do |char, idx|
|
|
1399
|
+
cursor_start_offset = cursor_column_num - start_column_num
|
|
1400
|
+
cursor_end_offset = end_column_num - start_column_num
|
|
1401
|
+
|
|
1402
|
+
if idx >= cursor_start_offset && !cursor_terminated
|
|
1403
|
+
cursor_terminated = true if cursor_termination_chars.include?(char)
|
|
1404
|
+
print char if cursor_terminated
|
|
1405
|
+
print "\001\e[31m\002#{char}\001\e[0m\002" unless cursor_terminated
|
|
1406
|
+
else
|
|
1407
|
+
print char
|
|
1336
1408
|
end
|
|
1337
1409
|
end
|
|
1338
|
-
puts "\n" * 6
|
|
1339
1410
|
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1411
|
+
if current_step.length.positive?
|
|
1412
|
+
system_role_content = "Being an expert penetration tester skilled in code analysis, debugging, and exploitation while stepping through JavaScript in a Chrome DevTools debugging session: 1. Your sole purpose is to analyze each JavaScript step and generate an Exploit Prediction Scoring System (EPSS) score between 0% - 100%. The step currently resides in this block of JavaScript:\n```\n#{source_to_review}\n```\n2. If the score is >= 75%, generate a JavaScript proof-of-concept that would allow a threat actor to directly exploit or target a user for exploitation (i.e. no self-exploit). 3. If the EPSS score is >= 75% also provide a code fix. *** If the EPSS score is < 75%, no explanations or summaries - just the EPSS score."
|
|
1413
|
+
|
|
1414
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
1415
|
+
system_role_content: system_role_content,
|
|
1416
|
+
request: current_step
|
|
1417
|
+
)
|
|
1418
|
+
puts "^^^ #{ai_analysis}" unless ai_analysis.nil?
|
|
1419
|
+
end
|
|
1420
|
+
puts "\n" * 3
|
|
1421
|
+
|
|
1422
|
+
step_hash = {
|
|
1423
|
+
step: step_num,
|
|
1424
|
+
action: action,
|
|
1425
|
+
source: current_step
|
|
1426
|
+
}
|
|
1347
1427
|
|
|
1348
|
-
|
|
1428
|
+
steps_arr.push(step_hash)
|
|
1349
1429
|
end
|
|
1350
1430
|
|
|
1351
|
-
|
|
1431
|
+
steps_arr
|
|
1352
1432
|
rescue Selenium::WebDriver::Error::WebDriverError
|
|
1353
1433
|
devtools
|
|
1354
1434
|
rescue StandardError => e
|
data/lib/pwn/version.rb
CHANGED
data/lib/pwn/www/hacker_one.rb
CHANGED
|
@@ -131,9 +131,18 @@ module PWN
|
|
|
131
131
|
cursor = page_info[:endCursor]
|
|
132
132
|
break unless page_info[:hasNextPage]
|
|
133
133
|
end
|
|
134
|
+
puts "\n"
|
|
134
135
|
|
|
135
136
|
programs_arr.sort_by! { |p| -p[:min_payout].gsub('$', '').gsub(',', '').to_f }
|
|
136
137
|
|
|
138
|
+
system_role_content = 'Suggest an optimal bug bounty program to target on HackerOne to maximize potential earnings based on values within `min_payout` and publicly known vulnerabilities that have surfaced for the `name` of the program.'
|
|
139
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
140
|
+
request: programs_arr.to_json,
|
|
141
|
+
system_role_content: system_role_content,
|
|
142
|
+
spinner: true
|
|
143
|
+
)
|
|
144
|
+
puts "\n\n#{ai_analysis}" unless ai_analysis.nil?
|
|
145
|
+
|
|
137
146
|
programs_arr
|
|
138
147
|
rescue RestClient::ExceptionWithResponse => e
|
|
139
148
|
if e.response
|
|
@@ -270,6 +279,16 @@ module PWN
|
|
|
270
279
|
name: program_name,
|
|
271
280
|
scope_details: json_resp_hash
|
|
272
281
|
}
|
|
282
|
+
|
|
283
|
+
system_role_content = 'Analyze the scope details for the given bug bounty program on HackerOne. Identify key areas of interest, potential vulnerabilities, and any patterns that could inform a targeted security assessment based on the provided scope information.'
|
|
284
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
285
|
+
request: json_resp.to_json,
|
|
286
|
+
system_role_content: system_role_content,
|
|
287
|
+
spinner: true
|
|
288
|
+
)
|
|
289
|
+
puts "\n\n#{ai_analysis}" unless ai_analysis.nil?
|
|
290
|
+
|
|
291
|
+
json_resp
|
|
273
292
|
rescue RestClient::ExceptionWithResponse => e
|
|
274
293
|
if e.response
|
|
275
294
|
puts "HTTP RESPONSE CODE: #{e.response.code}"
|
|
@@ -408,6 +427,16 @@ module PWN
|
|
|
408
427
|
name: program_name,
|
|
409
428
|
hacktivity: json_resp_hash
|
|
410
429
|
}
|
|
430
|
+
|
|
431
|
+
system_role_content = 'Analyze the hacktivity details for the given bug bounty program on HackerOne. Identify significant disclosed reports, common vulnerability types, and any trends that could inform future security assessments based on the provided hacktivity information.'
|
|
432
|
+
ai_analysis = PWN::AI::Introspection.reflect_on(
|
|
433
|
+
request: json_resp.to_json,
|
|
434
|
+
system_role_content: system_role_content,
|
|
435
|
+
spinner: true
|
|
436
|
+
)
|
|
437
|
+
puts "\n\n#{ai_analysis}" unless ai_analysis.nil?
|
|
438
|
+
|
|
439
|
+
json_resp
|
|
411
440
|
rescue RestClient::ExceptionWithResponse => e
|
|
412
441
|
if e.response
|
|
413
442
|
puts "HTTP RESPONSE CODE: #{e.response.code}"
|
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.495
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 0day Inc.
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "<"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 8.1.
|
|
18
|
+
version: 8.1.1
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "<"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 8.1.
|
|
25
|
+
version: 8.1.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: anemone
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -113,14 +113,14 @@ dependencies:
|
|
|
113
113
|
requirements:
|
|
114
114
|
- - '='
|
|
115
115
|
- !ruby/object:Gem::Version
|
|
116
|
-
version: 7.1.
|
|
116
|
+
version: 7.1.1
|
|
117
117
|
type: :runtime
|
|
118
118
|
prerelease: false
|
|
119
119
|
version_requirements: !ruby/object:Gem::Requirement
|
|
120
120
|
requirements:
|
|
121
121
|
- - '='
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
|
-
version: 7.1.
|
|
123
|
+
version: 7.1.1
|
|
124
124
|
- !ruby/object:Gem::Dependency
|
|
125
125
|
name: bson
|
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -827,14 +827,14 @@ dependencies:
|
|
|
827
827
|
requirements:
|
|
828
828
|
- - '='
|
|
829
829
|
- !ruby/object:Gem::Version
|
|
830
|
-
version: 13.3.
|
|
830
|
+
version: 13.3.1
|
|
831
831
|
type: :development
|
|
832
832
|
prerelease: false
|
|
833
833
|
version_requirements: !ruby/object:Gem::Requirement
|
|
834
834
|
requirements:
|
|
835
835
|
- - '='
|
|
836
836
|
- !ruby/object:Gem::Version
|
|
837
|
-
version: 13.3.
|
|
837
|
+
version: 13.3.1
|
|
838
838
|
- !ruby/object:Gem::Dependency
|
|
839
839
|
name: rb-readline
|
|
840
840
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -869,14 +869,14 @@ dependencies:
|
|
|
869
869
|
requirements:
|
|
870
870
|
- - '='
|
|
871
871
|
- !ruby/object:Gem::Version
|
|
872
|
-
version: 6.15.
|
|
872
|
+
version: 6.15.1
|
|
873
873
|
type: :development
|
|
874
874
|
prerelease: false
|
|
875
875
|
version_requirements: !ruby/object:Gem::Requirement
|
|
876
876
|
requirements:
|
|
877
877
|
- - '='
|
|
878
878
|
- !ruby/object:Gem::Version
|
|
879
|
-
version: 6.15.
|
|
879
|
+
version: 6.15.1
|
|
880
880
|
- !ruby/object:Gem::Dependency
|
|
881
881
|
name: rest-client
|
|
882
882
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -967,14 +967,14 @@ dependencies:
|
|
|
967
967
|
requirements:
|
|
968
968
|
- - '='
|
|
969
969
|
- !ruby/object:Gem::Version
|
|
970
|
-
version: 1.81.
|
|
970
|
+
version: 1.81.7
|
|
971
971
|
type: :runtime
|
|
972
972
|
prerelease: false
|
|
973
973
|
version_requirements: !ruby/object:Gem::Requirement
|
|
974
974
|
requirements:
|
|
975
975
|
- - '='
|
|
976
976
|
- !ruby/object:Gem::Version
|
|
977
|
-
version: 1.81.
|
|
977
|
+
version: 1.81.7
|
|
978
978
|
- !ruby/object:Gem::Dependency
|
|
979
979
|
name: rubocop-rake
|
|
980
980
|
requirement: !ruby/object:Gem::Requirement
|