pwn 0.5.154 → 0.5.156

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdc176de7f592b5c19650942854e4efa7d0158c835e89ace9f40af31a5a92f90
4
- data.tar.gz: 3f756b2f5deb2589c2e9d30068d13b1e460b0e7091cdeae6a0097fa3947e98ce
3
+ metadata.gz: 47f160c73c391cf48bd0a847d0031d342ef79b77575e86872153105905072141
4
+ data.tar.gz: 7c71dc97fd8e8e4e99584ab8bbb97363d46a2edd6786f2bb8e4ee9bd7c0b16cb
5
5
  SHA512:
6
- metadata.gz: 7a6437ab3cb220bd0c374b9672848646bace31fd6ba283e717a67db97a7826a397a9e8a68d0339f209cffebb55d8e63c918ebd211335b9406961822b2136c715
7
- data.tar.gz: 7ece6c1aeb18b7a16d772552717708c0df8b30483547e4080f2f2699173e52b1207b2a2b55ab3856cd077a958e065e89f32bf274d58894799db53b55db6a1939
6
+ metadata.gz: 55c9643d11b525ef375396f51354e2356363567de4ca1b9e0d9ea9281ff2af58698bd819a38f1e8b0c7212b03012403257c5e4622ae16e7ee018a36e1d66c7e1
7
+ data.tar.gz: c67b6fe7fbf5966d2630c4a0e99f254e58e6b09a6b15cad13a79897f9ab42c0f2efb7147547c70b4663e0f830af672d72859abc50e64e54b51ad999c4a33220b
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.154]:001 >>> PWN.help
40
+ pwn[v0.5.156]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
@@ -52,7 +52,7 @@ $ rvm use ruby-3.3.1@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.154]:001 >>> PWN.help
55
+ pwn[v0.5.156]: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.3.1@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.154]:001 >>> PWN.help
65
+ pwn[v0.5.156]: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/bin/pwn_sast CHANGED
@@ -117,7 +117,7 @@ begin
117
117
  TypeScriptTypeJuggling
118
118
  Version
119
119
  WindowLocationHash
120
- ]
120
+ ].sort.uniq
121
121
  end
122
122
 
123
123
  if list_test_cases
@@ -46,12 +46,30 @@ module PWN
46
46
  raise e
47
47
  end
48
48
 
49
+ # Supported Method Parameters::
50
+ # is_rfc1918 = PWN::Plugins::IPInfo.check_rfc1918(
51
+ # ip: 'required - IP to check'
52
+ # )
53
+ public_class_method def self.check_rfc1918(opts = {})
54
+ ip = opts[:ip].to_s.scrub.strip.chomp
55
+ ip_obj = IPAddress.valid?(ip) ? IPAddress.parse(ip) : nil
56
+
57
+ rfc1918_ranges = [
58
+ IPAddress('10.0.0.0/8'), # 10.0.0.0 - 10.255.255.255
59
+ IPAddress('172.16.0.0/12'), # 172.16.0.0 - 172.31.255.255
60
+ IPAddress('192.168.0.0/16') # 192.168.0.0 - 192.168.255.255
61
+ ]
62
+
63
+ rfc1918_ranges.any? { |range| range.include?(ip_obj) }
64
+ end
65
+
49
66
  # Supported Method Parameters::
50
67
  # ip_info_struc = PWN::Plugins::IPInfo.get(
51
68
  # target: 'required - IP or Host to lookup',
52
69
  # proxy: 'optional - use a proxy',
53
70
  # tls_port: 'optional port to check cert for Domain Name (default: 443). Will not execute if proxy parameter is set.',
54
- # skip_api: 'optional - skip the API call'
71
+ # skip_api: 'optional - skip the API call',
72
+ # dns_server: 'optional - DNS server to use for lookup (default: your default DNS server)'
55
73
  # )
56
74
 
57
75
  public_class_method def self.get(opts = {})
@@ -63,19 +81,29 @@ module PWN
63
81
  ip_info_resp = []
64
82
  ip_resp_hash = {}
65
83
  is_ip = IPAddress.valid?(target)
66
-
67
- begin
68
- ip_resp_hash[:hostname] = target
69
- target = Resolv.getaddress(target) unless is_ip
70
- rescue Resolv::ResolvError
71
- target = nil
84
+ hostname = '' if is_ip
85
+
86
+ unless is_ip
87
+ begin
88
+ hostname = target
89
+ dns_server = opts[:dns_server]
90
+ dns_resolver = Resolv::DNS.new(nameserver: [dns_server]) if dns_server
91
+ dns_resolver ||= Resolv::DNS.new
92
+ target = dns_resolver.getaddress(target).to_s
93
+ rescue Resolv::ResolvError
94
+ target = nil
95
+ end
72
96
  end
73
97
 
74
98
  ip_resp_hash = ip_info_rest_call(ip: target, proxy: proxy) unless skip_api
99
+ is_rfc1918 = check_rfc1918(ip: target)
75
100
  ip_resp_hash[:ip] = target
101
+ ip_resp_hash[:is_rfc1918] = is_rfc1918
102
+ ip_resp_hash[:hostname] = hostname
103
+
76
104
  ip_info_resp.push(ip_resp_hash) unless target.nil?
77
105
 
78
- if proxy.nil? && is_ip
106
+ if proxy.nil?
79
107
  ip_info_resp.each do |ip_resp|
80
108
  tls_port_avail = PWN::Plugins::Sock.check_port_in_use(
81
109
  server_ip: target,
@@ -128,7 +156,7 @@ module PWN
128
156
  # PWN::Plugins::IPInfo.bruteforce_subdomains(
129
157
  # parent_domain: 'required - Parent Domain to brute force',
130
158
  # dictionary: 'required - Dictionary to use for subdomain brute force',
131
- # max_threads: 'optional - Maximum number of threads to use (default: 10)',
159
+ # max_threads: 'optional - Maximum number of threads to use (default: 9)',
132
160
  # proxy: 'optional - use a proxy',
133
161
  # tls_port: 'optional port to check cert for Domain Name (default: 443). Will not execute if proxy parameter is set.',
134
162
  # results_file: 'optional - File to write results to (default: /tmp/parent_domain-timestamp-pwn_bruteforce_subdomains.txt)'
@@ -141,15 +169,14 @@ module PWN
141
169
  dictionary = opts[:dictionary] ||= default_dictionary
142
170
  raise "ERROR: Dictionary file not found: #{dictionary}" unless File.exist?(dictionary)
143
171
 
144
- max_threads = opts[:max_threads].to_i
145
- max_threads = 8 unless max_threads.positive?
172
+ max_threads = opts[:max_threads]
146
173
 
147
174
  proxy = opts[:proxy]
148
175
  tls_port = opts[:tls_port]
149
176
  timestamp = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
150
177
  results_file = opts[:results_file] ||= "/tmp/SUBS.#{parent_domain}-#{timestamp}-pwn_bruteforce_subdomains.txt"
151
178
 
152
- File.write(results_file, '[')
179
+ File.write(results_file, "[\n")
153
180
 
154
181
  # Break up dictonary file into sublines and process each subline in a thread
155
182
  dict_lines = File.readlines(dictionary).shuffle
@@ -158,17 +185,16 @@ module PWN
158
185
  enumerable_array: dict_lines,
159
186
  max_threads: max_threads
160
187
  ) do |subline|
188
+ print '.'
161
189
  subdomain = subline.to_s.scrub.strip.chomp
162
190
  target = parent_domain if subdomain.empty?
163
- target = "#{subdomain}.#{parent_domain}"
191
+ target = "#{subdomain}.#{parent_domain}" unless subdomain.empty?
164
192
  ip_info_resp = get(
165
193
  target: target,
166
194
  proxy: proxy,
167
195
  tls_port: tls_port,
168
196
  skip_api: true
169
197
  )
170
- puts "SUBD: #{target} RESP: #{ip_info_resp}" if ip_info_resp.empty?
171
- puts "SUBD: #{target} RESP:\n#{ip_info_resp}" if ip_info_resp.any?
172
198
 
173
199
  mutex.synchronize do
174
200
  File.open(results_file, 'a') do |file|
@@ -185,8 +211,11 @@ module PWN
185
211
  raise e
186
212
  ensure
187
213
  # Strip trailing comma and close JSON array
188
- File.readlines(results_file)[-1].chomp!(',')
189
- File.append(results_file, ']')
214
+ final_results = File.readlines(results_file)
215
+ # Strip trailing comma from last line
216
+ last_line = final_results[-1][0..-2]
217
+ final_results[-1] = last_line
218
+ File.write(results_file, "#{final_results.join}\n]")
190
219
  end
191
220
 
192
221
  # Author(s):: 0day Inc. <support@0dayinc.com>
@@ -201,17 +230,22 @@ module PWN
201
230
 
202
231
  public_class_method def self.help
203
232
  puts "USAGE:
233
+ is_rfc1918 = #{self}.check_rfc1918(
234
+ ip: 'required - IP to check'
235
+ )
236
+
204
237
  ip_info_struc = #{self}.get(
205
238
  target: 'required - IP or Host to lookup',
206
239
  proxy: 'optional - use a proxy',
207
240
  tls_port: 'optional port to check cert for Domain Name (default: 443). Will not execute if proxy parameter is set.',
208
- skip_api: 'optional - skip the API call'
241
+ skip_api: 'optional - skip the API call',
242
+ dns_server: 'optional - DNS server to use for lookup (default: your default DNS server)'
209
243
  )
210
244
 
211
245
  #{self}.bruteforce_subdomains(
212
246
  parent_domain: 'required - Parent Domain to brute force',
213
247
  dictionary: 'required - Dictionary to use for subdomain brute force',
214
- max_threads: 'optional - Maximum number of threads to use (default: 10)',
248
+ max_threads: 'optional - Maximum number of threads to use (default: 9)',
215
249
  proxy: 'optional - use a proxy',
216
250
  tls_port: 'optional port to check cert for Domain Name (default: 443). Will not execute if proxy parameter is set.',
217
251
  results_file: 'optional - File to write results to (default: /tmp/parent_domain-timestamp-pwn_bruteforce_subdomains.txt)'
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'concurrent-ruby'
4
+
3
5
  module PWN
4
6
  module Plugins
5
7
  # This plugin makes the creation of a thread pool much simpler.
@@ -27,34 +29,54 @@ module PWN
27
29
  detach = opts[:detach] ||= false
28
30
 
29
31
  puts "Initiating Thread Pool of #{max_threads} Worker Threads...."
30
- queue = SizedQueue.new(max_threads)
31
- threads = Array.new(max_threads) do
32
- Thread.new do
33
- until (this_thread = queue.pop) == :POOL_EXHAUSTED
34
- yield this_thread
35
- end
36
- end
37
- end
38
-
39
- enumerable_array.uniq.sort.each do |this_thread|
40
- queue << this_thread
41
- end
32
+ pool = Concurrent::FixedThreadPool.new(max_threads)
42
33
 
43
- max_threads.times do
44
- queue << :POOL_EXHAUSTED
34
+ enumerable_array.each do |this_thread|
35
+ pool.post do
36
+ yield this_thread
37
+ end
45
38
  end
46
39
 
47
- if detach
48
- puts 'Detaching from thread pool...'
49
- else
50
- threads.each(&:join)
51
- end
40
+ pool.shutdown
41
+ pool.wait_for_termination unless detach
52
42
  rescue Interrupt
53
43
  puts "\nGoodbye."
54
44
  rescue StandardError => e
45
+ puts e.backtrace
55
46
  raise e
56
47
  end
57
48
 
49
+ # public_class_method def self.fill(opts = {})
50
+ # enumerable_array = opts[:enumerable_array]
51
+ # max_threads = opts[:max_threads].to_i
52
+ # max_threads = 9 if max_threads.zero?
53
+ # detach = opts[:detach] ||= false
54
+
55
+ # puts "Initiating Thread Pool of #{max_threads} Worker Threads...."
56
+ # queue = SizedQueue.new(max_threads)
57
+ # threads = Array.new(max_threads) do
58
+ # Thread.new do
59
+ # until (this_thread = queue.pop) == :POOL_EXHAUSTED
60
+ # yield this_thread
61
+ # end
62
+ # end
63
+ # end
64
+
65
+ # enumerable_array.uniq.each do |this_thread|
66
+ # queue << this_thread
67
+ # end
68
+
69
+ # max_threads.times do
70
+ # queue << :POOL_EXHAUSTED
71
+ # end
72
+
73
+ # threads.each(&:join) unless detach
74
+ # rescue Interrupt
75
+ # puts "\nGoodbye."
76
+ # rescue StandardError => e
77
+ # raise e
78
+ # end
79
+
58
80
  # Author(s):: 0day Inc. <support@0dayinc.com>
59
81
 
60
82
  public_class_method def self.authors
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.154'
4
+ VERSION = '0.5.156'
5
5
  end
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.5.154
4
+ version: 0.5.156
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-04 00:00:00.000000000 Z
11
+ date: 2024-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport