class Aquatone::Commands::Discover
Public Instance Methods
execute!()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 4 def execute! if !options[:domain] output("Please specify a domain to assess\n") exit 1 end @domain = Aquatone::Domain.new(options[:domain]) @assessment = Aquatone::Assessment.new(options[:domain]) @hosts = [options[:domain]] @host_dictionary = {} banner("Discover") setup_resolver identify_wildcard_ips run_collectors resolve_hosts output_summary write_to_hosts_file rescue Aquatone::Domain::UnresolvableDomain => e output(red("Error: #{e.message}\n")) end
Private Instance Methods
broadcast_ip?(ip)
click to toggle source
# File lib/aquatone/commands/discover.rb, line 173 def broadcast_ip?(ip) ip == "255.255.255.255" end
exclude_ip?(ip)
click to toggle source
# File lib/aquatone/commands/discover.rb, line 161 def exclude_ip?(ip) wildcard_ip?(ip) || (options[:ignore_private] && private_ip?(ip)) || broadcast_ip?(ip) end
find_subnets()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 131 def find_subnets subnets = {} @host_dictionary.values.each do |ip| subnet = ip.split(".")[0..2].join(".") if subnets.key?(subnet) subnets[subnet] += 1 else subnets[subnet] = 1 end end Hash[subnets.sort_by{|k, v| v}.reverse] end
identify_wildcard_ips()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 54 def identify_wildcard_ips output("Checking for wildcard DNS... ") @wildcard_ips = [] wildcard_domain = "#{random_string}.#{@domain.name}" if @resolver.resolve(wildcard_domain).nil? output("Done\n") return end output(yellow("Wildcard detected!\n")) output("Identifying wildcard IPs... ") 20.times do wildcard_domain = "#{random_string}.#{@domain.name}" if wildcard_ip = @resolver.resolve(wildcard_domain) @wildcard_ips << wildcard_ip unless @wildcard_ips.include?(wildcard_ip) end end output("Done\n") output("Filtering out hosts resolving to wildcard IPs\n") end
output_summary()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 118 def output_summary subnets = find_subnets if !subnets.keys.count.zero? output("Found subnets:\n\n") subnets.each_pair do |subnet, count| next if count == 1 subnet = "#{subnet}.0-255" output(" - #{subnet.ljust(17)} : #{count} hosts\n") end end output("\n") end
private_ip?(ip)
click to toggle source
# File lib/aquatone/commands/discover.rb, line 169 def private_ip?(ip) ip =~ /(\A127\.)|(\A10\.)|(\A172\.1[6-9]\.)|(\A172\.2[0-9]\.)|(\A172\.3[0-1]\.)|(\A192\.168\.)/ end
random_string()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 156 def random_string %w(a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9).shuffle.take(10).join end
resolve_hosts()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 97 def resolve_hosts output("\nResolving #{bold(@hosts.count)} unique hosts...\n") task_count = 0 @start_time = Time.now.to_i @hosts.each do |host| if asked_for_progress? output("Stats: #{seconds_to_time(Time.now.to_i - @start_time)} elapsed; " \ "#{task_count} out of #{@hosts.count} hosts checked (#{@host_dictionary.keys.count} discovered); " \ "#{(task_count.to_f / @hosts.count.to_f * 100.00).round(1)}% done\n") end if ip = @resolver.resolve(host) next if exclude_ip?(ip) @host_dictionary[host] = ip output("#{ip.ljust(15)} #{bold(host)}\n") end jitter_sleep task_count += 1 end output("\n", true) end
run_collectors()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 74 def run_collectors output("\n") Aquatone::Collector.descendants.each do |collector| next if skip_collector?(collector) output("Running collector: #{bold(collector.meta[:name])}... ") begin collector_instance = collector.new(@domain, options) hosts = collector_instance.execute! output("Done (#{hosts.count} #{hosts.count == 1 ? 'host' : 'hosts'})\n") @hosts += hosts rescue Aquatone::Collector::MissingKeyRequirement => e output(yellow("Skipped\n")) output(yellow(" -> #{e.message}\n")) rescue Timeout::Error output(red("Timed out\n")) rescue => e output(red("Error\n")) output(red(" -> #{e.message}\n")) end end @hosts = @hosts.sort.uniq end
setup_resolver()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 28 def setup_resolver if options[:nameservers] nameservers = options[:nameservers] else output("Identifying nameservers for #{@domain.name}... ") nameservers = @domain.nameservers output("Done\n") if nameservers.empty? output(yellow("#{@domain.name} has no nameservers. Using fallback nameservers.\n\n")) nameservers = [] end end if !nameservers.empty? output("Using nameservers:\n\n") nameservers.each do |ns| output(" - #{ns}\n") end output("\n") end @resolver = Aquatone::Resolver.new( :nameservers => nameservers, :fallback_nameservers => options[:fallback_nameservers] ) end
skip_collector?(collector)
click to toggle source
# File lib/aquatone/commands/discover.rb, line 177 def skip_collector?(collector) if options[:only_collectors] if options[:only_collectors].include?(collector.sluggified_name) false else true end elsif options[:disable_collectors] if options[:disable_collectors].include?(collector.sluggified_name) true else false end else false end end
wildcard_ip?(ip)
click to toggle source
# File lib/aquatone/commands/discover.rb, line 165 def wildcard_ip?(ip) @wildcard_ips.include?(ip) end
write_to_hosts_file()
click to toggle source
# File lib/aquatone/commands/discover.rb, line 144 def write_to_hosts_file @hosts_file_contents = "" @host_dictionary.each_pair do |host, ip| @hosts_file_contents += "#{host},#{ip}\n" end @assessment.write_file("hosts.txt", @hosts_file_contents) @assessment.write_file("hosts.json", @host_dictionary.to_json) output("Wrote #{bold(@host_dictionary.keys.count)} hosts to:\n\n") output(" - #{bold('file://' + File.join(@assessment.path, 'hosts.txt'))}\n") output(" - #{bold('file://' + File.join(@assessment.path, 'hosts.json'))}\n") end