pwn 0.4.700 → 0.4.702

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG_BETWEEN_TAGS.txt +492 -108
  3. data/README.md +2 -2
  4. data/bin/pwn_burp_suite_pro_active_scan +2 -1
  5. data/bin/pwn_domain_reversewhois +8 -7
  6. data/bin/pwn_owasp_zap_active_scan +3 -2
  7. data/bin/pwn_pastebin_sample_filter +6 -4
  8. data/bin/pwn_web_cache_deception +11 -8
  9. data/bin/pwn_www_checkip +6 -5
  10. data/bin/pwn_www_uri_buster +5 -4
  11. data/bin/pwn_xss_dom_vectors +12 -9
  12. data/lib/pwn/plugins/baresip.rb +3 -2
  13. data/lib/pwn/plugins/beef.rb +5 -2
  14. data/lib/pwn/plugins/burp_suite.rb +7 -5
  15. data/lib/pwn/plugins/defect_dojo.rb +5 -3
  16. data/lib/pwn/plugins/github.rb +2 -1
  17. data/lib/pwn/plugins/hacker_one.rb +4 -2
  18. data/lib/pwn/plugins/ibm_appscan.rb +13 -6
  19. data/lib/pwn/plugins/ip_info.rb +4 -2
  20. data/lib/pwn/plugins/jira_server.rb +2 -1
  21. data/lib/pwn/plugins/nessus_cloud.rb +2 -1
  22. data/lib/pwn/plugins/open_ai.rb +3 -1
  23. data/lib/pwn/plugins/owasp_zap.rb +2 -1
  24. data/lib/pwn/plugins/shodan.rb +2 -1
  25. data/lib/pwn/plugins/transparent_browser.rb +26 -36
  26. data/lib/pwn/plugins/twitter_api.rb +5 -2
  27. data/lib/pwn/plugins/vsphere.rb +1 -2
  28. data/lib/pwn/version.rb +1 -1
  29. data/lib/pwn/www/app_cobalt_io.rb +19 -13
  30. data/lib/pwn/www/bing.rb +9 -6
  31. data/lib/pwn/www/bug_crowd.rb +19 -13
  32. data/lib/pwn/www/checkip.rb +7 -5
  33. data/lib/pwn/www/coinbase_pro.rb +18 -12
  34. data/lib/pwn/www/duckduckgo.rb +15 -8
  35. data/lib/pwn/www/facebook.rb +16 -10
  36. data/lib/pwn/www/google.rb +12 -8
  37. data/lib/pwn/www/hacker_one.rb +16 -10
  38. data/lib/pwn/www/linkedin.rb +16 -10
  39. data/lib/pwn/www/pandora.rb +16 -10
  40. data/lib/pwn/www/pastebin.rb +9 -5
  41. data/lib/pwn/www/paypal.rb +36 -28
  42. data/lib/pwn/www/synack.rb +19 -13
  43. data/lib/pwn/www/torch.rb +12 -7
  44. data/lib/pwn/www/trading_view.rb +19 -13
  45. data/lib/pwn/www/twitter.rb +20 -12
  46. data/lib/pwn/www/uber.rb +16 -10
  47. data/lib/pwn/www/upwork.rb +16 -10
  48. data/lib/pwn/www/youtube.rb +9 -6
  49. metadata +2 -6
  50. data/bin/pwn_arachni +0 -157
  51. data/bin/pwn_arachni_rest +0 -174
@@ -9,13 +9,14 @@ module PWN
9
9
  # Supported Method Parameters::
10
10
  # browser_obj = PWN::WWW::Twitter.open(
11
11
  # browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
12
- # proxy: 'optional - scheme://proxy_host:port || :tor'
12
+ # proxy: 'optional - scheme://proxy_host:port || tor'
13
13
  # )
14
14
 
15
15
  public_class_method def self.open(opts = {})
16
16
  browser_obj = PWN::Plugins::TransparentBrowser.open(opts)
17
17
 
18
- browser_obj.goto('https://twitter.com')
18
+ browser = browser_obj[:browser]
19
+ browser.goto('https://twitter.com')
19
20
 
20
21
  browser_obj
21
22
  rescue StandardError => e
@@ -35,6 +36,8 @@ module PWN
35
36
  username = opts[:username].to_s.scrub.strip.chomp
36
37
  password = opts[:password]
37
38
 
39
+ browser = browser_obj[:browser]
40
+
38
41
  if password.nil?
39
42
  password = PWN::Plugins::AuthenticationHelper.mask_password
40
43
  else
@@ -44,14 +47,16 @@ module PWN
44
47
 
45
48
  browser_obj.goto('https://twitter.com/login')
46
49
 
47
- browser_obj.text_field(index: 2).wait_until(&:present?).set(username)
48
- browser_obj.text_field(index: 3).wait_until(&:present?).set(password)
49
- browser_obj.button(index: 1).click!
50
+ browser.text_field(index: 2).wait_until(&:present?).set(username)
51
+ browser.text_field(index: 3).wait_until(&:present?).set(password)
52
+ browser.button(index: 1).click!
50
53
 
51
54
  if mfa
52
- until browser_obj.url == 'https://twitter.com/' || browser_obj.url == 'https://twitter.com/home'
53
- browser_obj.text_field(id: 'challenge_response').wait_until(&:present?).set(PWN::Plugins::AuthenticationHelper.mfa(prompt: 'enter mfa token'))
54
- browser_obj.button(id: 'email_challenge_submit').click!
55
+ until browser.url == 'https://twitter.com/' ||
56
+ browser.url == 'https://twitter.com/home'
57
+
58
+ browser.text_field(id: 'challenge_response').wait_until(&:present?).set(PWN::Plugins::AuthenticationHelper.mfa(prompt: 'enter mfa token'))
59
+ browser.button(id: 'email_challenge_submit').click!
55
60
  sleep 3
56
61
  end
57
62
  print "\n"
@@ -69,8 +74,10 @@ module PWN
69
74
 
70
75
  public_class_method def self.logout(opts = {})
71
76
  browser_obj = opts[:browser_obj]
72
- browser_obj.li(id: 'user-dropdown').wait_until(&:present?).click!
73
- browser_obj.button(text: 'Log out').wait_until(&:present?).click!
77
+
78
+ browser = browser_obj[:browser]
79
+ browser.li(id: 'user-dropdown').wait_until(&:present?).click!
80
+ browser.button(text: 'Log out').wait_until(&:present?).click!
74
81
 
75
82
  browser_obj
76
83
  rescue StandardError => e
@@ -105,9 +112,10 @@ module PWN
105
112
  puts "USAGE:
106
113
  browser_obj = #{self}.open(
107
114
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
108
- proxy: 'optional - scheme://proxy_host:port || :tor'
115
+ proxy: 'optional - scheme://proxy_host:port || tor'
109
116
  )
110
- puts browser_obj.public_methods
117
+ browser = browser_obj[:browser]
118
+ puts browser.public_methods
111
119
 
112
120
  browser_obj = #{self}.login(
113
121
  browser_obj: 'required - browser_obj returned from #open method',
data/lib/pwn/www/uber.rb CHANGED
@@ -9,13 +9,14 @@ module PWN
9
9
  # Supported Method Parameters::
10
10
  # browser_obj = PWN::WWW::Uber.open(
11
11
  # browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
12
- # proxy: 'optional - scheme://proxy_host:port || :tor'
12
+ # proxy: 'optional - scheme://proxy_host:port || tor'
13
13
  # )
14
14
 
15
15
  public_class_method def self.open(opts = {})
16
16
  browser_obj = PWN::Plugins::TransparentBrowser.open(opts)
17
17
 
18
- browser_obj.goto('https://www.uber.com')
18
+ browser = browser_obj[:browser]
19
+ browser.goto('https://www.uber.com')
19
20
 
20
21
  browser_obj
21
22
  rescue StandardError => e
@@ -34,17 +35,19 @@ module PWN
34
35
  username = opts[:username].to_s.scrub.strip.chomp
35
36
  password = opts[:password]
36
37
 
38
+ browser = browser_obj[:browser]
39
+
37
40
  if password.nil?
38
41
  password = PWN::Plugins::AuthenticationHelper.mask_password
39
42
  else
40
43
  password = opts[:password].to_s.scrub.strip.chomp
41
44
  end
42
45
 
43
- browser_obj.goto('https://login.uber.com/login')
46
+ browser.goto('https://login.uber.com/login')
44
47
 
45
- browser_obj.text_field(id: 'email').wait_until(&:present?).set(username)
46
- browser_obj.text_field(id: 'password').wait_until(&:present?).set(password)
47
- browser_obj.button(id: 'login-submit-btn').click!
48
+ browser.text_field(id: 'email').wait_until(&:present?).set(username)
49
+ browser.text_field(id: 'password').wait_until(&:present?).set(password)
50
+ browser.button(id: 'login-submit-btn').click!
48
51
 
49
52
  browser_obj
50
53
  rescue StandardError => e
@@ -58,8 +61,10 @@ module PWN
58
61
 
59
62
  public_class_method def self.logout(opts = {})
60
63
  browser_obj = opts[:browser_obj]
61
- browser_obj.span(index: 5).wait_until(&:present?).hover
62
- browser_obj.link(index: 13).wait_until(&:present?).click!
64
+
65
+ browser = browser_obj[:browser]
66
+ browser.span(index: 5).wait_until(&:present?).hover
67
+ browser.link(index: 13).wait_until(&:present?).click!
63
68
 
64
69
  browser_obj
65
70
  rescue StandardError => e
@@ -94,9 +99,10 @@ module PWN
94
99
  puts "USAGE:
95
100
  browser_obj = #{self}.open(
96
101
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
97
- proxy: 'optional - scheme://proxy_host:port || :tor'
102
+ proxy: 'optional - scheme://proxy_host:port || tor'
98
103
  )
99
- puts browser_obj.public_methods
104
+ browser = browser_obj[:browser]
105
+ puts browser.public_methods
100
106
 
101
107
  browser_obj = #{self}.login(
102
108
  browser_obj: 'required - browser_obj returned from #open method',
@@ -9,13 +9,14 @@ module PWN
9
9
  # Supported Method Parameters::
10
10
  # browser_obj = PWN::WWW::Upwork.open(
11
11
  # browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
12
- # proxy: 'optional - scheme://proxy_host:port || :tor'
12
+ # proxy: 'optional - scheme://proxy_host:port || tor'
13
13
  # )
14
14
 
15
15
  public_class_method def self.open(opts = {})
16
16
  browser_obj = PWN::Plugins::TransparentBrowser.open(opts)
17
17
 
18
- browser_obj.goto('https://www.upwork.com')
18
+ browser = browser_obj[:browser]
19
+ browser.goto('https://www.upwork.com')
19
20
 
20
21
  browser_obj
21
22
  rescue StandardError => e
@@ -34,17 +35,19 @@ module PWN
34
35
  username = opts[:username].to_s.scrub.strip.chomp
35
36
  password = opts[:password]
36
37
 
38
+ browser = browser_obj[:browser]
39
+
37
40
  if password.nil?
38
41
  password = PWN::Plugins::AuthenticationHelper.mask_password
39
42
  else
40
43
  password = opts[:password].to_s.scrub.strip.chomp
41
44
  end
42
45
 
43
- browser_obj.goto('https://www.upwork.com/ab/account-security/login')
46
+ browser.goto('https://www.upwork.com/ab/account-security/login')
44
47
 
45
- browser_obj.text_field(id: 'login_username').wait_until(&:present?).set(username)
46
- browser_obj.text_field(id: 'login_password').wait_until(&:present?).set(password)
47
- browser_obj.button(text: 'Log In').click!
48
+ browser.text_field(id: 'login_username').wait_until(&:present?).set(username)
49
+ browser.text_field(id: 'login_password').wait_until(&:present?).set(password)
50
+ browser.button(text: 'Log In').click!
48
51
 
49
52
  browser_obj
50
53
  rescue StandardError => e
@@ -58,8 +61,10 @@ module PWN
58
61
 
59
62
  public_class_method def self.logout(opts = {})
60
63
  browser_obj = opts[:browser_obj]
61
- browser_obj.span(class: 'organization-selector').wait_until(&:present?).click!
62
- browser_obj.link(index: 39).wait_until(&:present?).click!
64
+
65
+ browser = browser_obj[:browser]
66
+ browser.span(class: 'organization-selector').wait_until(&:present?).click!
67
+ browser.link(index: 39).wait_until(&:present?).click!
63
68
 
64
69
  browser_obj
65
70
  rescue StandardError => e
@@ -94,9 +99,10 @@ module PWN
94
99
  puts "USAGE:
95
100
  browser_obj = #{self}.open(
96
101
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
97
- proxy: 'optional - scheme://proxy_host:port || :tor'
102
+ proxy: 'optional - scheme://proxy_host:port || tor'
98
103
  )
99
- puts browser_obj.public_methods
104
+ browser = browser_obj[:browser]
105
+ puts browser.public_methods
100
106
 
101
107
  browser_obj = #{self}.login(
102
108
  browser_obj: 'required - browser_obj returned from #open method',
@@ -7,13 +7,14 @@ module PWN
7
7
  # Supported Method Parameters::
8
8
  # browser_obj = PWN::WWW::Youtube.open(
9
9
  # browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
10
- # proxy: 'optional - scheme://proxy_host:port || :tor'
10
+ # proxy: 'optional - scheme://proxy_host:port || tor'
11
11
  # )
12
12
 
13
13
  public_class_method def self.open(opts = {})
14
14
  browser_obj = PWN::Plugins::TransparentBrowser.open(opts)
15
15
 
16
- browser_obj.goto('https://www.youtube.com')
16
+ browser = browser_obj[:browser]
17
+ browser.goto('https://www.youtube.com')
17
18
 
18
19
  browser_obj
19
20
  rescue StandardError => e
@@ -30,8 +31,9 @@ module PWN
30
31
  browser_obj = opts[:browser_obj]
31
32
  q = opts[:q].to_s
32
33
 
33
- browser_obj.text_field(name: 'search_query').wait_until(&:present?).set(q)
34
- browser_obj.button(id: 'search-btn').click!
34
+ browser = browser_obj[:browser]
35
+ browser.text_field(name: 'search_query').wait_until(&:present?).set(q)
36
+ browser.button(id: 'search-btn').click!
35
37
 
36
38
  browser_obj
37
39
  rescue StandardError => e
@@ -66,9 +68,10 @@ module PWN
66
68
  puts "USAGE:
67
69
  browser_obj =#{self}.open(
68
70
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
69
- proxy: 'optional - scheme://proxy_host:port || :tor'
71
+ proxy: 'optional - scheme://proxy_host:port || tor'
70
72
  )
71
- puts 'browser_obj.public_methods'
73
+ browser = browser_obj[:browser]
74
+ puts 'browser.public_methods'
72
75
 
73
76
  browser_obj =#{self}.search(
74
77
  browser_obj: 'required - browser_obj returned from #open method',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.700
4
+ version: 0.4.702
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-16 00:00:00.000000000 Z
11
+ date: 2023-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -1150,8 +1150,6 @@ email:
1150
1150
  executables:
1151
1151
  - pwn
1152
1152
  - pwn_android_war_dialer
1153
- - pwn_arachni
1154
- - pwn_arachni_rest
1155
1153
  - pwn_autoinc_version
1156
1154
  - pwn_aws_describe_resources
1157
1155
  - pwn_burp_suite_pro_active_scan
@@ -1217,8 +1215,6 @@ files:
1217
1215
  - Vagrantfile
1218
1216
  - bin/pwn
1219
1217
  - bin/pwn_android_war_dialer
1220
- - bin/pwn_arachni
1221
- - bin/pwn_arachni_rest
1222
1218
  - bin/pwn_autoinc_version
1223
1219
  - bin/pwn_aws_describe_resources
1224
1220
  - bin/pwn_burp_suite_pro_active_scan
data/bin/pwn_arachni DELETED
@@ -1,157 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'pwn'
5
- require 'optparse'
6
-
7
- opts = {}
8
- OptionParser.new do |options|
9
- options.banner = "USAGE:
10
- #{$PROGRAM_NAME} [opts]
11
- "
12
-
13
- options.on('-tTARGET', '--target_url=TARGET', '<Required - Target URI to Scan>') do |t|
14
- opts[:target_url] = t
15
- end
16
-
17
- options.on('-oDIR', '--report_output_dir=DIR', '<Required - Output Directory for Results Generation>') do |o|
18
- opts[:output_dir] = o
19
- end
20
-
21
- options.on('-bTYPE', '--browser_type=TYPE', '<Optional - Browser Type <firefox|chrome|headless> (Defaults to chrome)>') do |b|
22
- opts[:browser_type] = b
23
- end
24
-
25
- options.on('-IINST', '--navigation_instruct=INST', '<Optional - Path to Navigation Instructions (e.g. Auth w/ Target - see /pwn/etc/arachni/navigation.instruct.EXAMPLE)>') do |i|
26
- opts[:navigation_instruct] = i
27
- end
28
-
29
- options.on('-pPROXY', '--proxy=PROXY', '<Optional - Proxy SCHEME://ADDRESS:PORT>') do |p|
30
- opts[:proxy] = p
31
- end
32
-
33
- options.on('-xTYPE', '--proxy-type=TYPE', '<Optional - Proxy Type (See arachni --help)>') do |x|
34
- opts[:proxy_type] = x
35
- end
36
-
37
- options.on('-ePATTERN', '--exclude-pattern=PATTERN', '<Optional - Exclude comma-delimited resources whose URL matches pattern>') do |e|
38
- opts[:exclude_pattern] = e
39
- end
40
-
41
- options.on('-d', '--[no-]deep', '<Optional - Enable Deep Scanning (Much Longer to Complete)>') do |d|
42
- opts[:deep_scan] = d
43
- end
44
- end.parse!
45
-
46
- if opts.empty?
47
- puts `#{$PROGRAM_NAME} --help`
48
- exit 1
49
- end
50
-
51
- begin
52
- logger = PWN::Plugins::PWNLogger.create
53
-
54
- target_url = opts[:target_url].to_s.scrub
55
- output_dir = opts[:output_dir].to_s.scrub if Dir.exist?(opts[:output_dir].to_s.scrub)
56
- if opts[:browser_type].nil?
57
- browser_type = :chrome
58
- else
59
- browser_type = opts[:browser_type].to_s.strip.chomp.scrub.to_sym
60
- end
61
- navigation_instruct = opts[:navigation_instruct].to_s.strip.chomp.scrub if File.exist?(opts[:navigation_instruct].to_s.strip.chomp.scrub)
62
- proxy = opts[:proxy]
63
- proxy_type = opts[:proxy_type]
64
- exclude_pattern = opts[:exclude_pattern]
65
- deep_scan = opts[:deep_scan]
66
-
67
- raise 'ERROR: please use pwn_arachni_rest for REST Scanning.' if browser_type == :rest
68
-
69
- browser = PWN::Plugins::TransparentBrowser.open(
70
- browser_type: browser_type,
71
- proxy: proxy
72
- )
73
-
74
- browser.goto(target_url)
75
-
76
- if navigation_instruct
77
- File.read(navigation_instruct).each_line do |instruction|
78
- browser.instance_eval(instruction.to_s.scrub.strip.chomp)
79
- end
80
-
81
- # We should have an authenticated session by now in our browser object...
82
- http_cookie_header = ''
83
- browser.cookies.to_a.each_with_index do |this_symbolized_cookie_hash, index|
84
- # Need to convert symbolized key names in browser.cookies.to_a[index]
85
- # to strings for proper CGI::Cookie consumption
86
- this_cookie = {}
87
- this_symbolized_cookie_hash.each do |key, val|
88
- this_cookie[key.to_s] = val
89
- end
90
-
91
- cgi_cookie_str = CGI::Cookie.new(this_cookie).to_s
92
-
93
- if index.zero?
94
- http_cookie_header = cgi_cookie_str
95
- else
96
- http_cookie_header = "#{http_cookie_header}, #{cgi_cookie_str}"
97
- end
98
- end
99
- end
100
-
101
- arachni_cmd_str = "arachni #{target_url} --audit-parameter-names"
102
- arachni_cmd_str = "#{arachni_cmd_str} --output-debug"
103
- arachni_cmd_str = "#{arachni_cmd_str} --checks=*"
104
- arachni_cmd_str = "#{arachni_cmd_str} --audit-ui-inputs --audit-ui-forms"
105
- arachni_cmd_str = "#{arachni_cmd_str} --audit-jsons --audit-xmls"
106
- arachni_cmd_str = "#{arachni_cmd_str} --audit-links --audit-forms --audit-cookies"
107
- arachni_cmd_str = "#{arachni_cmd_str} --report-save-path=#{output_dir}/arachni_results.afr"
108
- arachni_cmd_str = "#{arachni_cmd_str} --http-proxy #{proxy}" if proxy
109
- arachni_cmd_str = "#{arachni_cmd_str} --http-proxy-type #{proxy_type}" if proxy_type
110
- arachni_cmd_str = "#{arachni_cmd_str} --http-cookie-string='#{http_cookie_header}'" if navigation_instruct
111
- arachni_cmd_str = "#{arachni_cmd_str} --audit-headers --audit-with-both-methods --audit-cookies-extensively" if deep_scan
112
-
113
- if exclude_pattern
114
- exclude_pattern.to_s.split(',').each do |exclude_entry|
115
- arachni_cmd_str = "#{arachni_cmd_str} --scope-exclude-pattern #{exclude_entry}"
116
- end
117
- end
118
-
119
- # Kick off scan as defined by pwn_arachni flags
120
- system(
121
- 'sudo',
122
- '/bin/bash',
123
- '--login',
124
- '-c',
125
- arachni_cmd_str
126
- )
127
-
128
- # Report Scan Results
129
- system(
130
- 'sudo',
131
- '/bin/bash',
132
- '--login',
133
- '-c',
134
- "arachni_reporter #{output_dir}/arachni_results.afr --reporter=html:outfile=#{output_dir}/arachni_results.html.zip"
135
- )
136
-
137
- system(
138
- 'sudo',
139
- '/bin/bash',
140
- '--login',
141
- '-c',
142
- "arachni_reporter #{output_dir}/arachni_results.afr --reporter=json:outfile=#{output_dir}/arachni_results.json"
143
- )
144
-
145
- # Unzip Results in Output Dir
146
- system(
147
- 'sudo',
148
- '/bin/bash',
149
- '--login',
150
- '-c',
151
- "cd #{output_dir} && unzip -o arachni_results.html.zip"
152
- )
153
- rescue StandardError, SystemExit, Interrupt => e
154
- raise e
155
- ensure
156
- browser = PWN::Plugins::TransparentBrowser.close(browser_obj: browser) unless browser.nil?
157
- end
data/bin/pwn_arachni_rest DELETED
@@ -1,174 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'pwn'
5
- require 'optparse'
6
- require 'securerandom'
7
- require 'pty'
8
- require 'json'
9
-
10
- opts = {}
11
- OptionParser.new do |options|
12
- options.banner = "USAGE:
13
- #{$PROGRAM_NAME} [opts]
14
- "
15
-
16
- options.on('-tTARGET', '--target_url=TARGET', '<Required - Target URI to Scan>') do |t|
17
- opts[:target_url] = t
18
- end
19
-
20
- options.on('-oDIR', '--report_output_dir=DIR', '<Required - Output Directory for Results Generation>') do |o|
21
- opts[:output_dir] = o
22
- end
23
-
24
- options.on('-IINST', '--navigation_instruct=INST', '<Required - Path to Navigation Instructions (e.g. Auth w/ Target - see /pwn/etc/arachni/navigation-REST.instruct.EXAMPLE)>') do |i|
25
- opts[:navigation_instruct] = i
26
- end
27
-
28
- options.on('-pPROXY', '--proxy=PROXY', '<Optional - Proxy SCHEME://ADDRESS:PORT>') do |p|
29
- opts[:proxy] = p
30
- end
31
-
32
- options.on('-xTYPE', '--proxy-type=TYPE', '<Optional - Proxy Type (See arachni --help)>') do |x|
33
- opts[:proxy_type] = x
34
- end
35
-
36
- options.on('-ePATTERN', '--exclude-pattern=PATTERN', '<Optional - Exclude comma-delimited resources whose URL matches pattern>') do |e|
37
- opts[:exclude_pattern] = e
38
- end
39
-
40
- options.on('-d', '--[no-]deep', '<Optional - Enable Deep Scanning (Much Longer to Complete)>') do |d|
41
- opts[:deep_scan] = d
42
- end
43
- end.parse!
44
-
45
- if opts.empty?
46
- puts `#{$PROGRAM_NAME} --help`
47
- exit 1
48
- end
49
-
50
- logger = PWN::Plugins::PWNLogger.create
51
-
52
- target_url = opts[:target_url].to_s.scrub
53
- output_dir = opts[:output_dir].to_s.scrub if Dir.exist?(opts[:output_dir].to_s.scrub)
54
- navigation_instruct = opts[:navigation_instruct].to_s.strip.chomp.scrub if File.exist?(opts[:navigation_instruct].to_s.strip.chomp.scrub)
55
- proxy = opts[:proxy]
56
- proxy_type = opts[:proxy_type]
57
- exclude_pattern = opts[:exclude_pattern]
58
- deep_scan = opts[:deep_scan]
59
-
60
- # Proxy defaults to 127.0.0.1:8282
61
- arachni_cmd_str = 'arachni --plugin=proxy:address=127.0.0.1,port=8282'
62
- arachni_cmd_str = "#{arachni_cmd_str} --output-debug"
63
- arachni_cmd_str = "#{arachni_cmd_str} --scope-page-limit=0"
64
- arachni_cmd_str = "#{arachni_cmd_str} --checks=*,-common_*,-backup*,-backdoors,-directory_listing,-csrf"
65
- arachni_cmd_str = "#{arachni_cmd_str} --report-save-path=#{output_dir}/arachni_results.afr"
66
- arachni_cmd_str = "#{arachni_cmd_str} --http-proxy #{proxy}" if proxy
67
- arachni_cmd_str = "#{arachni_cmd_str} --http-proxy-type #{proxy_type}" if proxy_type
68
- arachni_cmd_str = "#{arachni_cmd_str} --audit-jsons --audit-xmls --audit-forms --audit-links"
69
- arachni_cmd_str = "#{arachni_cmd_str} --audit-headers --audit-with-both-methods --audit-parameter-names" if deep_scan
70
- arachni_cmd_str = "#{arachni_cmd_str} #{target_url}"
71
-
72
- if exclude_pattern
73
- exclude_pattern.to_s.split(',').each do |exclude_entry|
74
- arachni_cmd_str = "#{arachni_cmd_str} --scope-exclude-pattern #{exclude_entry}"
75
- end
76
- end
77
-
78
- arachni_stdout_log_path = "/tmp/pwn_arachni_rest-#{SecureRandom.hex}.log"
79
- arachni_stdout_log = File.new(arachni_stdout_log_path, 'w')
80
- # Immediately writes all buffered data in IO to disk
81
- arachni_stdout_log.sync = true
82
- arachni_stdout_log.fsync
83
-
84
- trained_attack_vectors_yaml = ''
85
-
86
- # Kick off scan as defined by pwn_arachni_rest flags
87
- begin
88
- fork_pid = Process.fork do
89
- PTY.spawn(
90
- "sudo /bin/bash --login -c \"#{arachni_cmd_str}\""
91
- ) do |stdout, _stdin, _pid|
92
- stdout.each do |line|
93
- puts line
94
- arachni_stdout_log.puts line
95
- end
96
- end
97
- end
98
- Process.detach(fork_pid)
99
- puts 'Arachni proxy plugin process exiting...'
100
- rescue StandardError => e
101
- puts 'ERROR: Arachni proxy plugin process exiting...'
102
- raise e
103
- rescue Interrupt
104
- puts 'CTRL+C Detected - goodbye.'
105
- exit 1
106
- ensure
107
- Process.kill('TERM', fork_pid) if fork_pid
108
- File.unlink(arachni_stdout_log_path)
109
- File.unlink(trained_attack_vectors_yaml)
110
- end
111
-
112
- # Watch for Arachni proxy plugin to intialize prior to invoking navigation-REST.instruct
113
- return_pattern = 'Proxy: The scan will resume once you visit the shutdown URL.'
114
- loop do
115
- if File.exist?(arachni_stdout_log_path) &&
116
- File.read(arachni_stdout_log_path).include?(return_pattern)
117
-
118
- print 'Proxy started...sleeping for 9s. '
119
- sleep 9
120
- puts 'Ready to proceed.'
121
- break
122
- end
123
- sleep 3
124
- end
125
-
126
- # Initiate rest_client object to pump requests through Arachni proxy plugin.
127
- rest_client = PWN::Plugins::TransparentBrowser.open(
128
- browser_type: :rest,
129
- proxy: 'http://127.0.0.1:8282'
130
- )::Request
131
-
132
- # Now that the proxy is up, we can run the navigation-REST.instruct through the Arachni
133
- # proxy plugin (http://127.0.0.1:8282) to train arachni how to interact w/ the API.
134
- puts "Initialize REST API Training: #{navigation_instruct}"
135
- pwn_arachni_rest_custom_http_header = instance_eval(File.read(navigation_instruct), navigation_instruct)
136
- puts "REST API Training Complete: #{navigation_instruct}"
137
- puts 'Sleeping for 9s prior to proceeding...'
138
- sleep 9
139
-
140
- # Close rest_client used for training Arachni
141
- PWN::Plugins::TransparentBrowser.close(browser_obj: rest_client)
142
-
143
- trained_attack_vectors_yaml = "#{File.dirname(arachni_stdout_log_path)}/#{File.basename(arachni_stdout_log_path, File.extname(arachni_stdout_log_path))}.yml"
144
-
145
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
146
- system("/bin/bash --login -c \"http_proxy=http://127.0.0.1:8282 curl http://arachni.proxy/panel/vectors.yml -o #{trained_attack_vectors_yaml}\"")
147
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
148
- system('/bin/bash --login -c "http_proxy=http://127.0.0.1:8282 curl http://arachni.proxy/shutdown"')
149
- fork_pid = nil
150
-
151
- arachni_trained_cmd_str = "arachni --plugin=vector_feed:yaml_file=#{trained_attack_vectors_yaml}"
152
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --output-debug"
153
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --scope-page-limit=0"
154
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --checks=*,-common_*,-backup*,-backdoors,-directory_listing,-csrf"
155
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --http-request-header='#{pwn_arachni_rest_custom_http_header}'" if pwn_arachni_rest_custom_http_header != ''
156
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --report-save-path=#{output_dir}/arachni_results.afr"
157
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --http-proxy #{proxy}" if proxy
158
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --http-proxy-type #{proxy_type}" if proxy_type
159
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --audit-jsons --audit-xmls --audit-forms --audit-links"
160
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} --audit-headers --audit-with-both-methods --audit-parameter-names" if deep_scan
161
- arachni_trained_cmd_str = "#{arachni_trained_cmd_str} #{target_url}"
162
-
163
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
164
- system("sudo /bin/bash --login -c \"#{arachni_trained_cmd_str}\"")
165
-
166
- # Report Scan Results
167
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
168
- system("sudo /bin/bash --login -c \"arachni_reporter #{output_dir}/arachni_results.afr --reporter=html:outfile=#{output_dir}/arachni_results.html.zip\"")
169
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
170
- system("sudo /bin/bash --login -c \"arachni_reporter #{output_dir}/arachni_results.afr --reporter=json:outfile=#{output_dir}/arachni_results.json\"")
171
-
172
- # Unzip Results in Output Dir
173
- # TODO: Use Process.spawn instead of system to capture pid for proper cleanup
174
- system("sudo /bin/bash --login -c \"cd #{output_dir} && unzip -o arachni_results.html.zip\"")