Class: Aquatone::Commands::Scan
Instance Attribute Summary
#options
Instance Method Summary
collapse
#initialize, run
Instance Method Details
#execute! ⇒ Object
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# File 'lib/aquatone/commands/scan.rb', line 4
def execute!
if !options[:domain]
output("Please specify a domain to assess\n")
exit 1
end
@assessment = Aquatone::Assessment.new(options[:domain])
@tasks = []
@host_dictionary = {}
@results = {}
@urls = []
banner("Scan")
prepare_host_dictionary
scan_ports
write_open_ports_file
write_urls_file
end
|
#output_open_port(host, port) ⇒ Object
98
99
100
101
102
103
104
105
|
# File 'lib/aquatone/commands/scan.rb', line 98
def output_open_port(host, port)
if (@host_dictionary[host].count > 3)
domains = @host_dictionary[host].shuffle.take(3).join(", ") + " and #{@host_dictionary[host].count - 3} more"
else
domains = @host_dictionary[host].take(3).join(", ")
end
output("#{green((port.to_s + '/tcp').ljust(9))} #{host.ljust(15)} #{domains}\n")
end
|
#output_progress ⇒ Object
92
93
94
95
96
|
# File 'lib/aquatone/commands/scan.rb', line 92
def output_progress
output("Stats: #{seconds_to_time(Time.now.to_i - @start_time)} elapsed; " \
"#{@task_count} out of #{@tasks.count} ports checked (#{@ports_open} open); " \
"#{(@task_count.to_f / @tasks.count.to_f * 100.00).round(1)}% done\n")
end
|
#port_open?(host, port) ⇒ Boolean
83
84
85
86
87
88
89
90
|
# File 'lib/aquatone/commands/scan.rb', line 83
def port_open?(host, port)
Timeout::timeout(options[:timeout]) do
TCPSocket.new(host, port).close
true
end
rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, SocketError
false
end
|
#prepare_host_dictionary ⇒ Object
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/aquatone/commands/scan.rb', line 23
def prepare_host_dictionary
if !@assessment.has_file?("hosts.json")
output(red("#{@assessment.path} does not contain hosts.json file\n\n"))
output("Did you run aquatone-discover first?\n")
exit 1
end
hosts = JSON.parse(@assessment.read_file("hosts.json"))
output("Loaded #{bold(hosts.count)} hosts from #{bold(File.join(@assessment.path, 'hosts.json'))}\n\n")
hosts.each_pair do |domain, ip|
if !@host_dictionary.key?(ip)
@host_dictionary[ip] = [domain]
options[:ports].each do |port|
@tasks << [ip, port]
end
else
@host_dictionary[ip] << domain
end
end
end
|
#scan_ports ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# File 'lib/aquatone/commands/scan.rb', line 43
def scan_ports
pool = thread_pool
@task_count = 1
@ports_open = 0
@start_time = Time.now.to_i
output("Probing #{bold(@tasks.count)} ports...\n")
@tasks.shuffle.each do |task|
host, port = task
pool.schedule do
output_progress if asked_for_progress?
if port_open?(host, port)
output_open_port(host, port)
@ports_open += 1
@results[host] ||= []
@results[host] << port
@host_dictionary[host].each do |hostname|
@urls << Aquatone::UrlMaker.make(hostname, port)
end
end
jitter_sleep
@task_count += 1
end
end
pool.shutdown
end
|
#write_open_ports_file ⇒ Object
69
70
71
72
73
74
75
76
|
# File 'lib/aquatone/commands/scan.rb', line 69
def write_open_ports_file
contents = []
@results.each_pair do |host, ports|
contents << "#{host},#{ports.join(',')}"
end
@assessment.write_file("open_ports.txt", contents.sort.join("\n"))
output("\nWrote open ports to #{bold('file://' + File.join(@assessment.path, 'open_ports.txt'))}\n")
end
|
#write_urls_file ⇒ Object
78
79
80
81
|
# File 'lib/aquatone/commands/scan.rb', line 78
def write_urls_file
@assessment.write_file("urls.txt", @urls.uniq.sort.join("\n"))
output("Wrote URLs to #{bold('file://' + File.join(@assessment.path, 'urls.txt'))}\n")
end
|