Class: Wmap::DnsBruter
Overview
Class to discover valid hosts through either zone transfer or DNS brute-force methods
Constant Summary
Constants included from Utils::UrlMagic
Utils::UrlMagic::Max_http_timeout, Utils::UrlMagic::User_agent
Constants included from Utils::DomainRoot
Utils::DomainRoot::File_ccsld, Utils::DomainRoot::File_cctld, Utils::DomainRoot::File_gtld, Utils::DomainRoot::File_tld
Instance Attribute Summary collapse
-
#data_dir ⇒ Object
Returns the value of attribute data_dir.
-
#discovered_hosts_from_dns_bruter ⇒ Object
readonly
Returns the value of attribute discovered_hosts_from_dns_bruter.
-
#fail_domain_cnt ⇒ Object
readonly
Returns the value of attribute fail_domain_cnt.
-
#file_hosts ⇒ Object
Returns the value of attribute file_hosts.
-
#hosts_dict ⇒ Object
Returns the value of attribute hosts_dict.
-
#max_parallel ⇒ Object
Returns the value of attribute max_parallel.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Instance Method Summary collapse
-
#brute_all(num = @max_parallel) ⇒ Object
Parallel DNS brute-force all existing domains.
-
#brute_force_dns(host) ⇒ Object
Return a list of valid hosts by brute-forcing the name servers.
-
#dns_brute_domains(targets, num = @max_parallel) ⇒ Object
Parallel DNS brute-forcer operating on the trusted domains - by utilizing fork manager to spawn multiple child processes on multiple sub_domain domains from the local hosts table simultaneously.
-
#dns_brute_file(file_target, num = @max_parallel) ⇒ Object
Parallel DNS brute-forcer operating on target domain file - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously.
-
#dns_brute_worker(host) ⇒ Object
(also: #query, #brute)
Main worker to perform the brute-forcing on an Internet domain.
-
#dns_brute_workers(list, num = @max_parallel) ⇒ Object
(also: #queries, #brutes)
Parallel DNS brute-forcer operating on target domain list - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously.
-
#get_vulnerable_ns(domain) ⇒ Object
Test the DNS server if zone transfer is allowed.
-
#hostname_mutation(host) ⇒ Object
(also: #mutation)
Return a list of hosts in the mutation form from the original, i.e.
-
#initialize(params = {}) ⇒ DnsBruter
constructor
Set default instance variables.
-
#print_discovered_hosts_from_bruter ⇒ Object
(also: #print)
Print summary report of found hosts from the brute force attacks.
-
#zone_transfer(domain) ⇒ Object
Perform zone transfer on a domain, return found host entries in an array.
Methods included from Utils
#cidr_2_ips, #file_2_hash, #file_2_list, #get_nameserver, #get_nameservers, #host_2_ip, #host_2_ips, #is_cidr?, #is_fqdn?, #is_ip?, #list_2_file, #reverse_dns_lookup, #sort_ips, #valid_dns_record?, #zone_transferable?
Methods included from Utils::Logger
Methods included from Utils::UrlMagic
#create_absolute_url_from_base, #create_absolute_url_from_context, #host_2_url, #is_site?, #is_ssl?, #is_url?, #landing_location, #make_absolute, #normalize_url, #open_page, #redirect_location, #response_code, #response_headers, #url_2_host, #url_2_path, #url_2_port, #url_2_site, #urls_on_same_domain?
Methods included from Utils::DomainRoot
#get_domain_root, #get_domain_root_by_ccsld, #get_domain_root_by_cctld, #get_domain_root_by_tlds, #get_sub_domain, #is_domain_root?, #print_ccsld, #print_cctld, #print_gtld
Constructor Details
#initialize(params = {}) ⇒ DnsBruter
Set default instance variables
20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/wmap/dns_bruter.rb', line 20 def initialize (params = {}) # Change to your brute-force dictionary file here if necessary @data_dir=params.fetch(:data_dir, File.dirname(__FILE__)+'/../../data/') Dir.mkdir(@data_dir) unless Dir.exist?(@data_dir) @file_hosts = @data_dir + 'hosts' @verbose=params.fetch(:verbose, false) @discovered_hosts_from_dns_bruter=Hash.new @hosts_dict=params.fetch(:hosts_dict, File.dirname(__FILE__)+'/../../dicts/hostnames-dict.txt') @max_parallel=params.fetch(:max_parallel, 30) @fail_domain_cnt=Hash.new end |
Instance Attribute Details
#data_dir ⇒ Object
Returns the value of attribute data_dir.
16 17 18 |
# File 'lib/wmap/dns_bruter.rb', line 16 def data_dir @data_dir end |
#discovered_hosts_from_dns_bruter ⇒ Object (readonly)
Returns the value of attribute discovered_hosts_from_dns_bruter.
17 18 19 |
# File 'lib/wmap/dns_bruter.rb', line 17 def discovered_hosts_from_dns_bruter @discovered_hosts_from_dns_bruter end |
#fail_domain_cnt ⇒ Object (readonly)
Returns the value of attribute fail_domain_cnt.
17 18 19 |
# File 'lib/wmap/dns_bruter.rb', line 17 def fail_domain_cnt @fail_domain_cnt end |
#file_hosts ⇒ Object
Returns the value of attribute file_hosts.
16 17 18 |
# File 'lib/wmap/dns_bruter.rb', line 16 def file_hosts @file_hosts end |
#hosts_dict ⇒ Object
Returns the value of attribute hosts_dict.
16 17 18 |
# File 'lib/wmap/dns_bruter.rb', line 16 def hosts_dict @hosts_dict end |
#max_parallel ⇒ Object
Returns the value of attribute max_parallel.
16 17 18 |
# File 'lib/wmap/dns_bruter.rb', line 16 def max_parallel @max_parallel end |
#verbose ⇒ Object
Returns the value of attribute verbose.
16 17 18 |
# File 'lib/wmap/dns_bruter.rb', line 16 def verbose @verbose end |
Instance Method Details
#brute_all(num = @max_parallel) ⇒ Object
Parallel DNS brute-force all existing domains
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/wmap/dns_bruter.rb', line 245 def brute_all(num=@max_parallel) puts "Start the parallel brute-forcing all domains with maximum child processes: #{num}" begin hosts=Array.new my_dis=Wmap::HostTracker.instance my_dis.data_dir=@data_dir known_domains=my_dis.dump_root_domains hosts=dns_brute_domains(num, known_domains) my_dis.adds(hosts) my_dis.save! my_dis=nil hosts rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose end end |
#brute_force_dns(host) ⇒ Object
Return a list of valid hosts by brute-forcing the name servers
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/wmap/dns_bruter.rb', line 159 def brute_force_dns (host) puts "Start dictionary attacks on the DNS server for: #{host}" if @verbose begin host=host.strip valid_hosts = Array.new my_host_tracker = Wmap::HostTracker.instance my_host_tracker.data_dir=@data_dir # build the host dictionary for the brute force method dict = Array.new if File.exists?(@hosts_dict) dict = file_2_list(@hosts_dict) elsif File.exists?(@file_hosts) dict = my_host_tracker.top_hostname(200) my_host_tracker.list_2_file(dict,@hosts_dict) else abort "Error: Non-existing common hosts dictionary file - #{@host_dict} or hosts file #{@file_hosts}. Please check your file path and name setting again." end domain=String.new unless is_root_domain?(host) or my_host_tracker.sub_domain_known?(host) my_hosts=hostname_mutation(host).map {|x| x.split('.')[0]} dict+=my_hosts unless my_hosts.empty? end if is_domain?(host) or my_host_tracker.sub_domain_known?(host) domain=host elsif array_h=host.split('.') array_h.shift domain=array_h.join('.') puts "Domain for #{host}: #{domain}" if @verbose end dict+=[host.split(".")[0],""] puts "Choose Brute-force Dictionary: #{dict}" if @verbose cnt=0 dict.each do |x| # 10/09/2013 add logic to skip brute-forcing the domain in case of experiencing more than 2 Dnsruby::ServFail conditions if @fail_domain_cnt.key?(domain) if @fail_domain_cnt[domain]>2 puts "Error! Multiple ServFail conditions detected in method #{__method__}. Now skip remaining works on: #{sub_domain}" if @verbose return valid_hosts end end cnt=cnt+1 if x.nil? next elsif x.empty? host=domain else host=[x,".",domain].join.downcase end valid_hosts.push(host) if valid_dns_record?(host) # Logic to detecting the bluff if the DNS server return hostname we threw to it if cnt==10 && valid_hosts.size>=10 valid_hosts=[host] puts "Brute force method fail, as the DNS server response to every host-name threw at it!" break end end puts "Found DNS records on domain #{host}: #{valid_hosts}" if @verbose @discovered_hosts_from_dns_bruter[host] = valid_hosts my_host_tracker = nil return valid_hosts.uniq rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose end end |
#dns_brute_domains(targets, num = @max_parallel) ⇒ Object
Parallel DNS brute-forcer operating on the trusted domains - by utilizing fork manager to spawn multiple child processes on multiple sub_domain domains from the local hosts table simultaneously
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/wmap/dns_bruter.rb', line 226 def dns_brute_domains(targets,num=@max_parallel) puts "Start the parallel brute-forcing with multiple child processes: #{num}" begin hosts=Array.new # Sliced to chunks of 1,000 domains for each process time, to avoid potential overflow of large array ? puts "Brute-forcing the following domain: #{targets}" if @verbose targets.each_slice(1000).to_a.map do |slice| hosts_new=dns_brute_workers(slice,num) hosts << hosts_new end puts "Parallel bruting result: #{hosts.flatten}" if @verbose return hosts.flatten rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose return hosts.flatten end end |
#dns_brute_file(file_target, num = @max_parallel) ⇒ Object
Parallel DNS brute-forcer operating on target domain file - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/wmap/dns_bruter.rb', line 87 def dns_brute_file(file_target,num=@max_parallel) puts "Start the parallel brute-forcing with multiple child processes on target file #{file_target}: #{num}" begin hosts=Array.new targets=file_2_list(file_target) hosts=dns_brute_workers(targets,num) return hosts rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose return hosts end end |
#dns_brute_worker(host) ⇒ Object Also known as: query, brute
Main worker to perform the brute-forcing on an Internet domain
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/wmap/dns_bruter.rb', line 33 def dns_brute_worker(host) puts "Start DNS brute forcer on: #{host}" results=Hash.new domain=get_domain_root(host) begin host=host.strip.downcase raise "Invalid internet host format: #{host}" unless is_fqdn?(host) domain=get_domain_root(host) # If we can do the zone transfer, then the brute-force process can be skipped. if zone_transferable?(domain) hosts=zone_transfer(domain) else hosts=brute_force_dns(host) end results[domain]=hosts puts "Finish discovery on #{host}: #{results}" return results rescue Exception=>ee puts "Exception on method #{__method__}: #{ee}" if @verbose return results end end |
#dns_brute_workers(list, num = @max_parallel) ⇒ Object Also known as: queries, brutes
Parallel DNS brute-forcer operating on target domain list - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/wmap/dns_bruter.rb', line 59 def dns_brute_workers(list,num=@max_parallel) puts "Start the parallel engine one the domain list: #{list} \nMaximum brute-forcing session: #{num} " begin targets=list.uniq.keep_if { |x| is_fqdn?(x) } results=Hash.new Parallel.map(targets, :in_processes => num) { |target| dns_brute_worker(target) }.each do |process| if process.nil? next elsif process.empty? #do nothing in case of thrown an empty array else #domain=get_domain_root(process.first).downcase results.merge!(process) end end puts "Parallel DNS brute-force results: #{results}" if @verbose @discovered_hosts_from_dns_bruter.merge!(results) return results rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose end end |
#get_vulnerable_ns(domain) ⇒ Object
Test the DNS server if zone transfer is allowed. If allowed, save the found hosts into the class variable.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/wmap/dns_bruter.rb', line 138 def get_vulnerable_ns(domain) puts "Identify the vulnerable DNS servers if zone transfer is allowed." domain=domain.strip.downcase vuln=Array.new begin nameservers = get_nameservers(domain) nameservers.each do |nssrv| zt = Dnsruby::ZoneTransfer.new zt.server=nssrv unless nssrv.empty? records = zt.transfer(domain) unless records==nil vuln.push(nssrv) end end return vuln rescue Exception=>ee puts "Exception on method #{__method__}: #{ee}" if @verbose end end |
#hostname_mutation(host) ⇒ Object Also known as: mutation
Return a list of hosts in the mutation form from the original, i.e. “ww1.example.com” => [“ww1,example.com”,“ww2.example.com”,…]
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/wmap/dns_bruter.rb', line 263 def hostname_mutation(host) puts "Start host mutation emulation on: #{host}" if @verbose begin hosts=Array.new host=host.strip.downcase raise "Invalid host format: #{host}" unless is_fqdn?(host) unless is_domain_root?(host) hostname=host.split('.')[0] hosts.push(host) case hostname when /\d+/ #first form of mutation, i.e. "ww1" => ["ww1","ww2",...] hostname.scan(/\d+/).map do |x| y=x.to_i 5.times do |i| z=y+i+1 w=(y-i-1).abs mut1=host.sub_domain(x,z.to_s) mut2=host.sub_domain(x,w.to_s) hosts.push(mut1,mut2) end end else puts "No mutation found for: #{host}" if @verbose end end puts "Host mutation found: #{hosts.uniq}" if @verbose return hosts.uniq rescue Exception => ee puts "Exception on method #{__method__}: #{ee}" if @verbose return hosts # fail-safe end end |
#print_discovered_hosts_from_bruter ⇒ Object Also known as: print
Print summary report of found hosts from the brute force attacks
299 300 301 302 303 304 305 306 307 |
# File 'lib/wmap/dns_bruter.rb', line 299 def print_discovered_hosts_from_bruter puts "\nSummary Report of the Discovered Hosts:" @discovered_hosts_from_dns_bruter.each do |domain,hosts| puts "Domain: #{domain}" puts "Found hosts:" puts @discovered_hosts_from_dns_bruter[domain]['hosts'] end puts "End of the summary" end |
#zone_transfer(domain) ⇒ Object
Perform zone transfer on a domain, return found host entries in an array
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/wmap/dns_bruter.rb', line 101 def zone_transfer(domain) puts "Perform zone transfer on zone: #{domain}" domain=domain.downcase nameservers = get_nameservers(domain) hosts=Array.new puts "Retrieved name servers: #{nameservers}" if @verbose nameservers.each do |nssrv| begin puts "Attempt zone transfer on name server: #{nssrv}" if nssrv.nil? abort "Method input variable error: no name server found!" if @verbose next end zt = Dnsruby::ZoneTransfer.new zt.server=nssrv unless nssrv.empty? records = zt.transfer(domain) if records==nil puts "Zone transfer failed for zone #{domain} on: #{nssrv}" next else puts "Zone transfer successfully for zone #{domain} on the name server: #{nssrv}" records = records.delete_if {|x| not x.to_s=~/(\s+|\t+)IN/ } records.each { |line| puts line.to_s } if @verbose hosts=records.collect {|x| x.to_s.split(/\.(\s+|\t+)/).first} hosts=hosts.sort!.uniq! puts "Found hosts: #{hosts}" if @verbose @discovered_hosts_from_dns_bruter[domain] = hosts return hosts end rescue Exception=>ee puts "Exception on method #{__method__}: #{ee}" if @verbose end end return hosts end |