pwn 0.4.666 → 0.4.668
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/Gemfile +1 -1
- data/README.md +2 -2
- data/bin/pwn +0 -1
- data/bin/pwn_diff_csv_files_w_column_exclude +54 -34
- data/bin/pwn_domain_reversewhois +6 -10
- data/bin/pwn_nessus_cloud_vulnscan +1 -3
- data/bin/pwn_pastebin_sample_filter +2 -8
- data/bin/pwn_web_cache_deception +9 -30
- data/bin/pwn_www_checkip +6 -10
- data/bin/pwn_xss_dom_vectors +5 -18
- data/lib/pwn/plugins/nessus_cloud.rb +4 -3
- data/lib/pwn/plugins/owasp_zap.rb +4 -9
- data/lib/pwn/plugins/tor.rb +221 -0
- data/lib/pwn/plugins/transparent_browser.rb +40 -21
- data/lib/pwn/plugins.rb +1 -0
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/app_cobalt_io.rb +2 -4
- data/lib/pwn/www/bing.rb +2 -4
- data/lib/pwn/www/bug_crowd.rb +2 -4
- data/lib/pwn/www/checkip.rb +2 -4
- data/lib/pwn/www/coinbase_pro.rb +2 -4
- data/lib/pwn/www/duckduckgo.rb +2 -4
- data/lib/pwn/www/facebook.rb +2 -4
- data/lib/pwn/www/google.rb +2 -4
- data/lib/pwn/www/hacker_one.rb +2 -4
- data/lib/pwn/www/linkedin.rb +2 -4
- data/lib/pwn/www/pandora.rb +2 -4
- data/lib/pwn/www/pastebin.rb +2 -4
- data/lib/pwn/www/paypal.rb +2 -4
- data/lib/pwn/www/synack.rb +2 -4
- data/lib/pwn/www/torch.rb +2 -4
- data/lib/pwn/www/trading_view.rb +2 -4
- data/lib/pwn/www/twitter.rb +2 -4
- data/lib/pwn/www/uber.rb +2 -4
- data/lib/pwn/www/upwork.rb +2 -4
- data/lib/pwn/www/youtube.rb +2 -4
- data/spec/lib/pwn/plugins/tor_spec.rb +15 -0
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 81bb385ebabab222a3d4da59c7eda736aaac086600e3c9710d6680428e05c023
|
|
4
|
+
data.tar.gz: 3227d1e76969e9b89ed2b5ce7090f8f2407288f89aa157b2af33dd4138855e38
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 262b94064b575f5200f500c4ea41e42bde4050d82f95ce8675ea3166c2ee4370126bcdb7222b3e261496e283dd04d85b80b040d939587817a8606f6e3be15559
|
|
7
|
+
data.tar.gz: c2cfd0bc37664e45aca472b1f4682962ad675262fc39363e6830caf05ffaf2e34b27795efdf7b7395cd383e6edd5bcb9a19518162aa7a5de87337335dce83043
|
data/Gemfile
CHANGED
|
@@ -72,7 +72,7 @@ gem 'ruby-nmap', '1.0.1'
|
|
|
72
72
|
gem 'ruby-saml', '1.15.0'
|
|
73
73
|
gem 'rvm', '1.11.3.9'
|
|
74
74
|
gem 'savon', '2.14.0'
|
|
75
|
-
gem 'selenium-devtools', '0.
|
|
75
|
+
gem 'selenium-devtools', '0.113.0'
|
|
76
76
|
gem 'serialport', '1.3.2'
|
|
77
77
|
gem 'sinatra', '3.0.6'
|
|
78
78
|
gem 'slack-ruby-client', '2.1.0'
|
data/README.md
CHANGED
|
@@ -37,7 +37,7 @@ $ rvm use ruby-3.2.2@pwn
|
|
|
37
37
|
$ rvm list gemsets
|
|
38
38
|
$ gem install --verbose pwn
|
|
39
39
|
$ pwn
|
|
40
|
-
pwn[v0.4.
|
|
40
|
+
pwn[v0.4.668]:001 >>> PWN.help
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
[](https://youtu.be/G7iLUY4FzsI)
|
|
@@ -52,7 +52,7 @@ $ rvm use ruby-3.2.2@pwn
|
|
|
52
52
|
$ gem uninstall --all --executables pwn
|
|
53
53
|
$ gem install --verbose pwn
|
|
54
54
|
$ pwn
|
|
55
|
-
pwn[v0.4.
|
|
55
|
+
pwn[v0.4.668]:001 >>> PWN.help
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
|
data/bin/pwn
CHANGED
|
@@ -43,15 +43,33 @@ if opts.empty?
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def csv_diff(opts = {})
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
c1_path = opts[:c1_path]
|
|
47
|
+
c2_path = opts[:c2_path]
|
|
48
48
|
diff_path = opts[:diff_path]
|
|
49
|
-
|
|
50
|
-
column_names_to_exclude = opts[:column_names_to_exclude]
|
|
49
|
+
no_headers = opts[:no_headers]
|
|
50
|
+
column_names_to_exclude = opts[:column_names_to_exclude].to_s.split(',')
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
csv1 = CSV.read(c1_path)
|
|
53
|
+
csv2 = CSV.read(c2_path)
|
|
54
|
+
|
|
55
|
+
if csv1.length >= csv2.length
|
|
56
|
+
larger_csv = csv1
|
|
57
|
+
larger_csv_orig = CSV.read(c1_path)
|
|
58
|
+
|
|
59
|
+
smaller_csv = csv2
|
|
60
|
+
smaller_csv_orig = CSV.read(c2_path)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if csv2.length >= csv1.length
|
|
64
|
+
larger_csv = csv2
|
|
65
|
+
larger_csv_orig = CSV.read(c2_path)
|
|
66
|
+
|
|
67
|
+
smaller_csv = csv1
|
|
68
|
+
smaller_csv_orig = CSV.read(c1_path)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Exclude the column values for diff to ensure the same rows
|
|
72
|
+
# with for example different timestamps aren't included.
|
|
55
73
|
columns_index_arr = []
|
|
56
74
|
column_names_to_exclude&.each do |column_name|
|
|
57
75
|
column_index = smaller_csv.first.find_index(column_name)
|
|
@@ -72,44 +90,46 @@ def csv_diff(opts = {})
|
|
|
72
90
|
end
|
|
73
91
|
end
|
|
74
92
|
|
|
75
|
-
|
|
93
|
+
# Write diff with redacted columns (to find differences we care about)
|
|
76
94
|
File.open(diff_path, 'w') do |f|
|
|
77
|
-
f.puts csv_headers if include_csv_headers
|
|
78
95
|
larger_csv.each do |line_arr|
|
|
79
96
|
line = line_arr.join(',')
|
|
80
97
|
f.puts line unless smaller_csv.include?(line_arr)
|
|
81
98
|
end
|
|
82
99
|
end
|
|
100
|
+
diff_csv = CSV.read(diff_path)
|
|
101
|
+
|
|
102
|
+
# Write diff again with all columns.
|
|
103
|
+
csv_headers_orig = larger_csv_orig.first.join(',')
|
|
104
|
+
File.open(diff_path, 'w') do |f|
|
|
105
|
+
if no_headers
|
|
106
|
+
larger_csv_orig.each do |line_arr|
|
|
107
|
+
line = line_arr.join(',')
|
|
108
|
+
f.puts line if diff_csv.include?(line_arr)
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
f.puts csv_headers_orig
|
|
112
|
+
larger_csv_orig(1..-1).each do |line_arr|
|
|
113
|
+
line = line_arr.join(',')
|
|
114
|
+
f.puts line if diff_csv.include?(line_arr)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
83
118
|
end
|
|
84
119
|
|
|
85
120
|
c1_path = opts[:c1_path]
|
|
86
|
-
csv1 = CSV.read(c1_path)
|
|
87
|
-
|
|
88
121
|
c2_path = opts[:c2_path]
|
|
89
|
-
csv2 = CSV.read(c2_path)
|
|
90
|
-
|
|
91
122
|
diff_path = opts[:diff_path]
|
|
123
|
+
column_names_to_exclude = opts[:column_names_to_exclude]
|
|
92
124
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
include_csv_headers = false if opts[:no_headers]
|
|
96
|
-
include_csv_headers ||= true
|
|
125
|
+
no_headers = true if opts[:no_headers]
|
|
126
|
+
no_headers ||= false
|
|
97
127
|
|
|
98
128
|
# Compare which two is larger
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)
|
|
107
|
-
else
|
|
108
|
-
csv_diff(
|
|
109
|
-
larger_csv: csv2,
|
|
110
|
-
smaller_csv: csv1,
|
|
111
|
-
diff_path: diff_path,
|
|
112
|
-
include_csv_headers: include_csv_headers,
|
|
113
|
-
column_names_to_exclude: column_names_to_exclude
|
|
114
|
-
)
|
|
115
|
-
end
|
|
129
|
+
csv_diff(
|
|
130
|
+
c1_path: c1_path,
|
|
131
|
+
c2_path: c2_path,
|
|
132
|
+
diff_path: diff_path,
|
|
133
|
+
no_headers: no_headers,
|
|
134
|
+
column_names_to_exclude: column_names_to_exclude
|
|
135
|
+
)
|
data/bin/pwn_domain_reversewhois
CHANGED
|
@@ -20,13 +20,9 @@ OptionParser.new do |options|
|
|
|
20
20
|
opts[:output_results] = o
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy>') do |p|
|
|
23
|
+
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy || :tor>') do |p|
|
|
24
24
|
opts[:proxy] = p
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
options.on('-T', '--[no-]with-tor', '<Optional - Proxy w/ TOR (Defaults to false)>') do |w|
|
|
28
|
-
opts[:with_tor] = w
|
|
29
|
-
end
|
|
30
26
|
end.parse!
|
|
31
27
|
|
|
32
28
|
if opts.empty?
|
|
@@ -37,13 +33,13 @@ end
|
|
|
37
33
|
registrant_filter = opts[:registrant_filter].to_s.strip.chomp.scrub
|
|
38
34
|
output_results = opts[:output_results].to_s.strip.chomp.scrub
|
|
39
35
|
proxy = opts[:proxy].to_s.scrub.strip.chomp unless opts[:proxy].nil?
|
|
40
|
-
with_tor = opts[:with_tor]
|
|
41
36
|
|
|
42
37
|
begin
|
|
43
|
-
if proxy
|
|
44
|
-
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
if proxy
|
|
39
|
+
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
40
|
+
browser_type: :headless,
|
|
41
|
+
proxy: proxy
|
|
42
|
+
)
|
|
47
43
|
else
|
|
48
44
|
browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :headless)
|
|
49
45
|
end
|
|
@@ -77,12 +77,10 @@ begin
|
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
scan_status = scan_status_resp[:status]
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
break if scan_status == 'completed'
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# raise "Scan status reached an unexpected condition: #{scan_status}. Re-verify the scan config for, '#{scan_name}' and try again." unless scan_status == 'completed'
|
|
85
|
-
|
|
86
84
|
puts 'scan complete.'
|
|
87
85
|
|
|
88
86
|
print "Exporting results to #{path_to_export}..."
|
|
@@ -14,13 +14,9 @@ OptionParser.new do |options|
|
|
|
14
14
|
opts[:regex] = r
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy>') do |p|
|
|
17
|
+
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy || :tor>') do |p|
|
|
18
18
|
opts[:proxy] = p
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
options.on('-T', '--[no-]with-tor', '<Optional - Proxy w/ TOR (Defaults to false)>') do |w|
|
|
22
|
-
opts[:with_tor] = w
|
|
23
|
-
end
|
|
24
20
|
end.parse!
|
|
25
21
|
|
|
26
22
|
if opts.empty?
|
|
@@ -29,13 +25,11 @@ if opts.empty?
|
|
|
29
25
|
end
|
|
30
26
|
|
|
31
27
|
proxy = opts[:proxy]
|
|
32
|
-
with_tor = opts[:with_tor]
|
|
33
28
|
regex = opts[:regex]
|
|
34
29
|
|
|
35
30
|
browser_obj = PWN::WWW::Pastebin.open(
|
|
36
31
|
browser_type: :headless,
|
|
37
|
-
proxy: proxy
|
|
38
|
-
with_tor: with_tor
|
|
32
|
+
proxy: proxy
|
|
39
33
|
)
|
|
40
34
|
|
|
41
35
|
begin
|
data/bin/pwn_web_cache_deception
CHANGED
|
@@ -38,13 +38,9 @@ OptionParser.new do |options|
|
|
|
38
38
|
opts[:mfa] = f
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy>') do |p|
|
|
41
|
+
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy || :tor>') do |p|
|
|
42
42
|
opts[:proxy] = p
|
|
43
43
|
end
|
|
44
|
-
|
|
45
|
-
options.on('-T', '--[no-]with-tor', '<Optional - Proxy w/ TOR (Defaults to false)>') do |w|
|
|
46
|
-
opts[:with_tor] = w
|
|
47
|
-
end
|
|
48
44
|
end.parse!
|
|
49
45
|
|
|
50
46
|
if opts.empty?
|
|
@@ -88,7 +84,6 @@ else
|
|
|
88
84
|
end
|
|
89
85
|
|
|
90
86
|
proxy = opts[:proxy].to_s.scrub.strip.chomp unless opts[:proxy].nil?
|
|
91
|
-
with_tor = opts[:with_tor]
|
|
92
87
|
|
|
93
88
|
begin
|
|
94
89
|
def get_web_cache_deception(opts = {})
|
|
@@ -157,18 +152,10 @@ begin
|
|
|
157
152
|
|
|
158
153
|
puts "#{@green}Leveraging PWN::WWW::#{pwn_www_mod_str} to Obtain a Post AuhN State...#{@end_of_color}"
|
|
159
154
|
if proxy
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
with_tor: true
|
|
165
|
-
)
|
|
166
|
-
else
|
|
167
|
-
browser_obj = pwn_www_mod.open(
|
|
168
|
-
browser_type: :chrome,
|
|
169
|
-
proxy: proxy
|
|
170
|
-
)
|
|
171
|
-
end
|
|
155
|
+
browser_obj = pwn_www_mod.open(
|
|
156
|
+
browser_type: :chrome,
|
|
157
|
+
proxy: proxy
|
|
158
|
+
)
|
|
172
159
|
else
|
|
173
160
|
browser_obj = pwn_www_mod.open(browser_type: :chrome)
|
|
174
161
|
end
|
|
@@ -181,18 +168,10 @@ begin
|
|
|
181
168
|
)
|
|
182
169
|
puts "#{@green}complete.#{@end_of_color}\n\n\n"
|
|
183
170
|
elsif pwn_www_mod_str == '' && proxy
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
with_tor: true
|
|
189
|
-
)
|
|
190
|
-
else
|
|
191
|
-
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
192
|
-
browser_type: :chrome,
|
|
193
|
-
proxy: proxy
|
|
194
|
-
)
|
|
195
|
-
end
|
|
171
|
+
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
172
|
+
browser_type: :chrome,
|
|
173
|
+
proxy: proxy
|
|
174
|
+
)
|
|
196
175
|
else
|
|
197
176
|
browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :chrome)
|
|
198
177
|
end
|
data/bin/pwn_www_checkip
CHANGED
|
@@ -10,28 +10,24 @@ OptionParser.new do |options|
|
|
|
10
10
|
#{$PROGRAM_NAME} [opts]
|
|
11
11
|
"
|
|
12
12
|
|
|
13
|
-
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy>') do |p|
|
|
13
|
+
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy || :tor>') do |p|
|
|
14
14
|
opts[:proxy] = p
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
options.on('-T', '--[no-]with-tor', '<Optional - Proxy w/ TOR (Defaults to false)>') do |w|
|
|
18
|
-
opts[:with_tor] = w
|
|
19
|
-
end
|
|
20
|
-
|
|
21
17
|
options.on('-i', '--[no-]ipinfo', '<Optional - Return Details about Public IP Returned from CheckIP>') do |i|
|
|
22
18
|
opts[:ipinfo] = i
|
|
23
19
|
end
|
|
24
20
|
end.parse!
|
|
25
21
|
|
|
26
22
|
proxy = opts[:proxy].to_s.scrub.strip.chomp unless opts[:proxy].nil?
|
|
27
|
-
with_tor = opts[:with_tor]
|
|
28
23
|
ipinfo = opts[:ipinfo]
|
|
29
24
|
|
|
30
25
|
begin
|
|
31
|
-
if proxy
|
|
32
|
-
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
if proxy
|
|
27
|
+
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
28
|
+
browser_type: :rest,
|
|
29
|
+
proxy: proxy
|
|
30
|
+
)::Request
|
|
35
31
|
else
|
|
36
32
|
browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: :rest)::Request
|
|
37
33
|
end
|
data/bin/pwn_xss_dom_vectors
CHANGED
|
@@ -26,14 +26,10 @@ OptionParser.new do |options|
|
|
|
26
26
|
opts[:browser_type] = b
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy>') do |p|
|
|
29
|
+
options.on('-pPROXY', '--proxy=PROXY', '<Optional - HTTP or Socks Proxy || :tor>') do |p|
|
|
30
30
|
opts[:proxy] = p
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
options.on('-T', '--[no-]with-tor', '<Optional - Proxy w/ TOR (Defaults to false)>') do |w|
|
|
34
|
-
opts[:with_tor] = w
|
|
35
|
-
end
|
|
36
|
-
|
|
37
33
|
options.on('-S', '--[no-]spider-fqdn', '<Optional - Spider Target FQDN>') do |s|
|
|
38
34
|
opts[:spider] = s
|
|
39
35
|
end
|
|
@@ -56,7 +52,6 @@ else
|
|
|
56
52
|
end
|
|
57
53
|
|
|
58
54
|
proxy = opts[:proxy].to_s.scrub.strip.chomp unless opts[:proxy].nil?
|
|
59
|
-
with_tor = opts[:with_tor]
|
|
60
55
|
|
|
61
56
|
if opts[:spider]
|
|
62
57
|
spider = true
|
|
@@ -109,18 +104,10 @@ begin
|
|
|
109
104
|
end
|
|
110
105
|
|
|
111
106
|
if proxy
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
with_tor: true
|
|
117
|
-
)
|
|
118
|
-
else
|
|
119
|
-
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
120
|
-
browser_type: browser_type,
|
|
121
|
-
proxy: proxy
|
|
122
|
-
)
|
|
123
|
-
end
|
|
107
|
+
browser_obj = PWN::Plugins::TransparentBrowser.open(
|
|
108
|
+
browser_type: browser_type,
|
|
109
|
+
proxy: proxy
|
|
110
|
+
)
|
|
124
111
|
else
|
|
125
112
|
browser_obj = PWN::Plugins::TransparentBrowser.open(browser_type: browser_type)
|
|
126
113
|
end
|
|
@@ -80,9 +80,10 @@ module PWN
|
|
|
80
80
|
|
|
81
81
|
response
|
|
82
82
|
rescue RestClient::ExceptionWithResponse => e
|
|
83
|
-
puts "#{base_nessus_cloud_api_uri}/#{rest_call}"
|
|
84
|
-
puts params
|
|
85
|
-
puts http_body
|
|
83
|
+
puts "URI: #{base_nessus_cloud_api_uri}/#{rest_call}"
|
|
84
|
+
puts "Params: #{params.inspect}"
|
|
85
|
+
puts "HTTP POST Body: #{http_body}"
|
|
86
|
+
|
|
86
87
|
raise e
|
|
87
88
|
rescue StandardError, SystemExit, Interrupt => e
|
|
88
89
|
raise e
|
|
@@ -71,7 +71,7 @@ module PWN
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
# Supported Method Parameters::
|
|
74
|
-
# PWN::Plugins::OwaspZap.start(
|
|
74
|
+
# zap_obj = PWN::Plugins::OwaspZap.start(
|
|
75
75
|
# api_key: 'required - api key for API authorization',
|
|
76
76
|
# zap_bin_path: 'optional - path to zap.sh file'
|
|
77
77
|
# headless: 'optional - run zap headless if set to true',
|
|
@@ -467,17 +467,12 @@ module PWN
|
|
|
467
467
|
|
|
468
468
|
# Supported Method Parameters::
|
|
469
469
|
# PWN::Plugins::OwaspZap.stop(
|
|
470
|
-
# :zap_obj => 'required - zap_obj returned from #
|
|
470
|
+
# :zap_obj => 'required - zap_obj returned from #start method'
|
|
471
471
|
# )
|
|
472
472
|
|
|
473
473
|
public_class_method def self.stop(opts = {})
|
|
474
474
|
zap_obj = opts[:zap_obj]
|
|
475
|
-
unless zap_obj.nil?
|
|
476
|
-
pid = zap_obj[:pid]
|
|
477
|
-
# File.unlink(zap_obj[:stdout_log]) if File.exist?(zap_obj[:stdout_log])
|
|
478
|
-
|
|
479
|
-
Process.kill('TERM', pid)
|
|
480
|
-
end
|
|
475
|
+
Process.kill('TERM', zab_obj[:pid]) unless zap_obj.nil?
|
|
481
476
|
rescue StandardError => e
|
|
482
477
|
raise e
|
|
483
478
|
end
|
|
@@ -538,7 +533,7 @@ module PWN
|
|
|
538
533
|
)
|
|
539
534
|
|
|
540
535
|
#{self}.stop(
|
|
541
|
-
zap_obj: 'required - zap_obj returned from #
|
|
536
|
+
zap_obj: 'required - zap_obj returned from #start method'
|
|
542
537
|
)
|
|
543
538
|
|
|
544
539
|
#{self}.authors
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pty'
|
|
4
|
+
|
|
5
|
+
module PWN
|
|
6
|
+
module Plugins
|
|
7
|
+
# This plugin processes images into readable text
|
|
8
|
+
module Tor
|
|
9
|
+
# Supported Method Parameters::
|
|
10
|
+
# tor_ctrl_cmd(
|
|
11
|
+
# tor_obj: 'required - tor_obj returned from #start method'
|
|
12
|
+
# cmd: 'required - Tor control command to execute',
|
|
13
|
+
# response_timeout: 'optional - float in seconds to timeout (default: 3.0)'
|
|
14
|
+
# )
|
|
15
|
+
|
|
16
|
+
private_class_method def self.tor_control_cmd(opts = {})
|
|
17
|
+
tor_obj = opts[:tor_obj]
|
|
18
|
+
cmd = opts[:cmd]
|
|
19
|
+
response_timeout = opts[:response_timeout]
|
|
20
|
+
response_timeout ||= 3.0
|
|
21
|
+
|
|
22
|
+
ctrl_ip = tor_obj[:ip]
|
|
23
|
+
ctrl_port = tor_obj[:ctrl_port]
|
|
24
|
+
cookie_authn = tor_obj[:cookie_authn]
|
|
25
|
+
|
|
26
|
+
sock_obj = PWN::Plugins::Sock.connect(
|
|
27
|
+
target: ctrl_ip,
|
|
28
|
+
port: ctrl_port
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
cmd_hist_arr = []
|
|
32
|
+
cmd_hash = { cmd: "AUTHENTICATE #{cookie_authn}\r\n" }
|
|
33
|
+
sock_obj.write(cmd_hash[:cmd])
|
|
34
|
+
does_respond = sock_obj.wait_readable(response_timeout)
|
|
35
|
+
if does_respond
|
|
36
|
+
response = sock_obj.readline.chomp
|
|
37
|
+
cmd_hash[:resp] = response
|
|
38
|
+
cmd_hist_arr.push(cmd_hash)
|
|
39
|
+
if response == '250 OK'
|
|
40
|
+
cmd_hash = { cmd: "#{cmd}\r\n" }
|
|
41
|
+
sock_obj.write(cmd_hash[:cmd])
|
|
42
|
+
does_respond = sock_obj.wait_readable(response_timeout)
|
|
43
|
+
if does_respond
|
|
44
|
+
response = sock_obj.readline.chomp
|
|
45
|
+
cmd_hash[:resp] = response
|
|
46
|
+
cmd_hist_arr.push(cmd_hash)
|
|
47
|
+
if response == '250 OK'
|
|
48
|
+
cmd_hash = { cmd: "QUIT\r\n" }
|
|
49
|
+
sock_obj.write(cmd_hash[:cmd])
|
|
50
|
+
does_respond = sock_obj.wait_readable(response_timeout)
|
|
51
|
+
if does_respond
|
|
52
|
+
response = sock_obj.readline.chomp
|
|
53
|
+
else
|
|
54
|
+
response = '900 NO CMD RESPONSE'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
else
|
|
58
|
+
response = '900 NO CMD RESPONSE'
|
|
59
|
+
end
|
|
60
|
+
cmd_hash[:resp] = response
|
|
61
|
+
cmd_hist_arr.push(cmd_hash)
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
response = '700 NO AUTHENTICATE RESPONSE'
|
|
65
|
+
cmd_hash[:resp] = response
|
|
66
|
+
cmd_hist_arr.push(cmd_hash)
|
|
67
|
+
end
|
|
68
|
+
sock_obj = PWN::Plugins::Sock.disconnect(sock_obj: sock_obj)
|
|
69
|
+
|
|
70
|
+
cmd_hist_arr
|
|
71
|
+
rescue StandardError => e
|
|
72
|
+
stop(tor_obj: tor_obj)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Supported Method Parameters::
|
|
76
|
+
# tor_obj = PWN::Plugins::Tor.start(
|
|
77
|
+
# ip: 'optional - IP address to listen (default: 127.0.0.1)',
|
|
78
|
+
# port: 'optional - socks port to listen (default: 1024-65535)',
|
|
79
|
+
# ctrl_port: 'optional - tor control port to listen (default: 1024-65535)',
|
|
80
|
+
# data_dir: 'optional - directory to keep tor session data (default: /tmp/tor_pwn-TIMESTAMP)'
|
|
81
|
+
# )
|
|
82
|
+
|
|
83
|
+
public_class_method def self.start(opts = {})
|
|
84
|
+
ip = opts[:ip]
|
|
85
|
+
ip ||= '127.0.0.1'
|
|
86
|
+
port = opts[:port].to_i
|
|
87
|
+
port = PWN::Plugins::Sock.get_random_unused_port if port.zero?
|
|
88
|
+
ctrl_port = opts[:ctrl_port].to_i
|
|
89
|
+
if ctrl_port.zero?
|
|
90
|
+
loop do
|
|
91
|
+
ctrl_port = PWN::Plugins::Sock.get_random_unused_port
|
|
92
|
+
break if ctrl_port != port
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
timestamp = Time.now.strftime('%Y-%m-%d_%H-%M-%S.%N%z')
|
|
96
|
+
data_dir = opts[:data_dir]
|
|
97
|
+
data_dir ||= "/tmp/tor_pwn-#{timestamp}"
|
|
98
|
+
FileUtils.mkdir_p(data_dir)
|
|
99
|
+
|
|
100
|
+
socks_proxy = "#{ip}:#{port}"
|
|
101
|
+
pid_file = "#{data_dir}/tor.pid"
|
|
102
|
+
cookie_authn_file = "#{data_dir}/control_auth_cookie"
|
|
103
|
+
session_log_path = "#{data_dir}/stdout-session.log"
|
|
104
|
+
session_log = File.new(session_log_path, 'w')
|
|
105
|
+
session_log.sync = true
|
|
106
|
+
session_log.fsync
|
|
107
|
+
|
|
108
|
+
fork_pid = Process.fork do
|
|
109
|
+
pty = PTY.spawn(
|
|
110
|
+
'tor',
|
|
111
|
+
'DataDirectory',
|
|
112
|
+
data_dir,
|
|
113
|
+
'SocksPort',
|
|
114
|
+
socks_proxy,
|
|
115
|
+
'ControlPort',
|
|
116
|
+
ctrl_port.to_s,
|
|
117
|
+
'CookieAuthentication',
|
|
118
|
+
'1'
|
|
119
|
+
) do |stdout, _stdin, pid|
|
|
120
|
+
File.write(pid_file, pid)
|
|
121
|
+
stdout.each do |line|
|
|
122
|
+
session_log.puts line
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
rescue StandardError => e
|
|
126
|
+
puts 'Tor exiting with errors...'
|
|
127
|
+
FileUtils.rm_rf(data_dir)
|
|
128
|
+
raise e
|
|
129
|
+
end
|
|
130
|
+
Process.detach(fork_pid)
|
|
131
|
+
|
|
132
|
+
loop do
|
|
133
|
+
pid_ready = File.exist?(pid_file)
|
|
134
|
+
cookie_authn_ready = File.exist?(cookie_authn_file)
|
|
135
|
+
sleep 0.1
|
|
136
|
+
break if pid_ready && cookie_authn_ready
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
cookie_authn = `hexdump -e '32/1 "%02x"' #{cookie_authn_file}`
|
|
140
|
+
tor_obj = {
|
|
141
|
+
parent_pid: fork_pid,
|
|
142
|
+
child_pid: File.read(pid_file).to_i,
|
|
143
|
+
ip: ip,
|
|
144
|
+
port: port,
|
|
145
|
+
ctrl_port: ctrl_port,
|
|
146
|
+
data_dir: data_dir,
|
|
147
|
+
cookie_authn: cookie_authn
|
|
148
|
+
}
|
|
149
|
+
rescue StandardError, SystemExit => e
|
|
150
|
+
stop(tor_obj) unless tor_obj.nil?
|
|
151
|
+
raise e
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Supported Method Parameters::
|
|
155
|
+
# PWN::Plugins::Tor.switch_exit_node(
|
|
156
|
+
# tor_obj: 'required - tor_obj returned from #start method',
|
|
157
|
+
# response_timeout: 'optional - float in seconds to timeout (default: 3.0)'
|
|
158
|
+
# )
|
|
159
|
+
|
|
160
|
+
public_class_method def self.switch_exit_node(opts = {})
|
|
161
|
+
tor_obj = opts[:tor_obj]
|
|
162
|
+
response_timeout = opts[:response_timeout]
|
|
163
|
+
tor_control_cmd(
|
|
164
|
+
tor_obj: tor_obj,
|
|
165
|
+
cmd: 'SIGNAL NEWNYM',
|
|
166
|
+
response_timeout: response_timeout
|
|
167
|
+
)
|
|
168
|
+
rescue StandardError => e
|
|
169
|
+
raise e
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Supported Method Parameters::
|
|
173
|
+
# PWN::Plugins::Tor.stop(
|
|
174
|
+
# tor_obj: 'required - tor_obj returned from #start method'
|
|
175
|
+
# )
|
|
176
|
+
|
|
177
|
+
public_class_method def self.stop(opts = {})
|
|
178
|
+
tor_obj = opts[:tor_obj]
|
|
179
|
+
unless tor_obj.nil?
|
|
180
|
+
FileUtils.rm_rf(tor_obj[:data_dir])
|
|
181
|
+
Process.kill('TERM', tor_obj[:child_pid])
|
|
182
|
+
Process.kill('TERM', tor_obj[:parent_pid])
|
|
183
|
+
end
|
|
184
|
+
rescue StandardError => e
|
|
185
|
+
raise e
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Author(s):: 0day Inc. <request.pentest@0dayinc.com>
|
|
189
|
+
|
|
190
|
+
public_class_method def self.authors
|
|
191
|
+
"AUTHOR(S):
|
|
192
|
+
0day Inc. <request.pentest@0dayinc.com>
|
|
193
|
+
"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Display Usage for this Module
|
|
197
|
+
|
|
198
|
+
public_class_method def self.help
|
|
199
|
+
puts "USAGE:
|
|
200
|
+
tor_obj = #{self}.start(
|
|
201
|
+
ip: 'optional - IP address to listen (default: 127.0.0.1)',
|
|
202
|
+
port: 'optional - socks port to listen (default: 9050)',
|
|
203
|
+
ctrl_port: 'optional - tor control port to listen (default: 9051)',
|
|
204
|
+
data_dir: 'optional - directory to keep tor session data (default: /tmp/tor_pwn-TIMESTAMP)'
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
#{self}.switch_exit_node(
|
|
208
|
+
tor_obj: 'required - tor_obj returned from #start method',
|
|
209
|
+
response_timeout: 'optional - float in seconds to timeout (default: 3.0)'
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
#{self}.stop(
|
|
213
|
+
tor_obj: 'required - tor_obj returned from #start method'
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
#{self}.authors
|
|
217
|
+
"
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|