wmap 2.5.5 → 2.5.6

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: 9b7418c10fec65599e729f381e47814776b8e9641a3e1d27d5b11084e2d87f3d
4
- data.tar.gz: 8534aa535bbba34f58fab3edd1e73cad1b85d2c95d294d2e6bbd894960c1f885
3
+ metadata.gz: 6afbdfcdf343c39f15a1af467762bffe90bc12f05b7a7eb1341ef2cacf7e561f
4
+ data.tar.gz: 95e039be31be2277fcc8e225106c365b1b7b1694d4db372a6f211d552c3d1162
5
5
  SHA512:
6
- metadata.gz: 8992d8b673bf2fddfb5a1097b26a947fb109fb68bccf677310fee4b7e4530358ef48da75eb128f70c0f8e609914c91f3c5f0348de9417d38683db1ed1de1fd3e
7
- data.tar.gz: c8664f0216f971f48f454bdced1a5566cb0feaa699c2a366fd34e72f84b6744e54e623d3c959e1369d2aea751eb5cbbd92e2d3bf78dc621821d5f5b953e2dd7f
6
+ metadata.gz: b522ee4f4830ed50fb4dac0760cf6b15d84d8b791bd6c1593cdc51042747d002b14f46b1173a40fef7c952fb1256c019b118ec47b6c691c3b4fd27f5f0d3d4b3
7
+ data.tar.gz: 5f0bd019eac486a744dd96c9d36928d27ba2607cfe1d9e6834189d756f85e08b4deec09b45b89bfc7e779e385f44ec862f6e516d04e98b4f3e31b09c458ea76e
@@ -1,32 +1,38 @@
1
- = OWASP WebMapper Ruby API README
1
+ [<img src='/wmap_logo.jpg' width='350' height='350'>](https://github.com/yangsec888/wmap)
2
+ =====================
2
3
 
4
+ - [What's this program for?](#whats-this-program-for)
5
+ - [WMAP in Motion](#wmap-in-motion)
6
+ - [Installation](#installation)
7
+ - [Before Using This Program](#before-using-this-program)
8
+ - [More Document(s)](#more-documents)
9
+ - [Program Version](#program-version)
10
+ - [Author Contact](#author-contact)
11
+ - [Bug Report or Feature Request](#bug-report-or-feature-request)
12
+ - [Legal Disclaimer](#legal-disclaimer)
3
13
 
4
- == What's this program for?
14
+ # OWASP Web Mapper README
15
+
16
+
17
+ ## What's this program for?
5
18
  This program is designed for the web application asset discovery and tracking. It was originally developed to
6
19
  to cover the gaps of a similar commercial product. Over the time it grows to be a more capable and complete replacement (IMHO).
7
20
 
8
21
 
9
- == WMAP in Motion
22
+ ## WMAP in Motion
10
23
  Use the demo web app build on top of wmap gem: http://wmap.io
11
24
 
12
25
 
13
- == Program Version
14
- The latest release is version 2.4.5. as of fall 2018. Please refer to the CHANGELOG.md for the program's history information.
15
-
16
-
17
- == Author Contact
18
- This program is designed and developed by Yang Li. You can reach him by Email: <yang.li@owasp.org>
19
-
20
-
21
- == Installation
26
+ ## Installation
22
27
  To take full power of this program, you would need an *nix flavor machine with direct Internet access. I have installed it successfully on both Mac and Linux machines. You'll also need the Ruby environment being setup properly. The easiest way to install OWASP Web Mapper is by using Ruby Gems. You can install it from command line:
23
-
28
+ ```sh
24
29
  gem install wmap
30
+ ```
25
31
 
26
- == Specific Installation Problem with Nokogiri
32
+ ### Specific Installation Problem with Nokogiri
27
33
  Nokogiri is a native xml/html parser used by the project. It's fast and powerful. However, it comes with pitfall of installation problem around building native extension for your environment. Please refer to this page for trouble-shooting tip (http://www.nokogiri.org/tutorials/installing_nokogiri.html).
28
34
 
29
- == Dependency
35
+ ### Dependency
30
36
  You need the Ruby 2.1.0 or above in order to use this program. In my test environment, I was able to set it up with <a href="https://rvm.io/">RVM</a>. Please refer to this page for more installation information: https://www.ruby-lang.org/en/documentation/installation/
31
37
 
32
38
  In addition, the following Ruby GEM dependency are needed by different components of this software. The should be installed automatically:
@@ -48,31 +54,32 @@ In case you want to install the above gems separately, use the command below:
48
54
 
49
55
  gem install dnsruby geoip minitest net-ping netaddr nokogiri css_parser open_uri_redirections openssl parallel whois httpclient
50
56
 
51
- == Ruby-whois Gem Patches
57
+ ### Ruby-whois Gem Patches
52
58
  This software depends on a patched version of Ruby gem ruby-whois (http://www.ruby-whois.org/) for the domain whois lookup feature. For better result, you could manually add the patches into your local whois gem installation directory as shown below:
53
-
59
+ ```sh
54
60
  cp whois_patches/* [Your_ruby_whois_gem_path]/whois/lib/whois/record/parser/
61
+ ```
55
62
 
56
63
  Or you can directly download the branched whois gem from this repository - https://github.com/yangsec888/whois
57
64
 
58
65
 
59
- == Before Using This Program
66
+ ### Before Using This Program
60
67
  You need to define a scope for the program to run successful. The scope includes both your legitimate Internet domain, and your public
61
68
  network block in the CIDR format.
62
69
 
63
70
  To add your Internet domain into the scope, use the build-in shell command below:
64
-
71
+ ```sh
65
72
  trust XYZ.COM
66
-
73
+ ```
67
74
  To add your public network block into the scope (note current support of IPv4 only):
68
-
75
+ ```sh
69
76
  trust x.x.x.x/x
77
+ ```
70
78
 
71
-
72
- == Automatic Discovery and Tracking
73
-
79
+ ### Automatic Discovery and Tracking
80
+ ```sh
74
81
  wmap <seed file | target host | target url | target IP or network cidr>
75
-
82
+ ```
76
83
  The above utility is intelligent enough to take argument as either a seed file, or a string such as a host, an IP, a network block, or a URL. The new discoveries will be automatically tracked in the data file 'lib/wmap/data/target_sites'.
77
84
  Note: seed file - mix of url, cidr and domain seed, one entry per line.
78
85
  url seed - known URL(s) for further discovery via the web crawler.
@@ -80,26 +87,33 @@ The above utility is intelligent enough to take argument as either a seed file,
80
87
  domain seed - validated internet domain to be used for DNS record brute-forcing; it is also used to validate the ownership of found web service.
81
88
 
82
89
 
83
- == Dump Out Discovery Database
90
+ ### Dump Out Discovery Database
84
91
  You can dump out the program output by using the build-in utility 'wdump' as shown below:
85
-
92
+ ```sh
86
93
  wdump [output file name from you]
87
-
94
+ ```
88
95
  The above utility will dump out the discovery database into a single file as program output. Currently, the supported file format is Comma-separated Value (.csv) and Extensible Markup Language (.xml)
89
96
 
90
97
 
91
- == More Usage Cases:
98
+ ### More Usage Cases:
92
99
  There are more examples under the 'demos' folder of this package. The examples show how to use the 'wmap' API to get your job done easily. Please check out the code - they should be easy and straightforward to be understood.
93
100
 
94
101
 
95
- == More Document(s):
102
+ ## More Document(s):
96
103
  The software comes with the Ruby doc during your installation as shown above. For your convenience, the Ruby doc is also distributed with this software. You can navigate to the 'doc' folder of your local installation, and click the 'index.html' to open the start page in your favorite browser. You can also download the wmap-x.x.x.rdoc.zip documentation package alone from GitHub, unzip and open the doc/index.html in your browser.
97
104
 
98
105
  If you need additional documentation / information other than this README file and the Ruby document package, please be patient - as I'm still working on it :)
99
106
 
100
- == How do I report the bugs, or maybe require some new features?
101
- Contact the author Sam Li directly at email 'yang.li@owasp.org'.
107
+
108
+ ## Program Version
109
+ The latest release is version [2.5.5+](version.txt). as of fall 2018. Please refer to the [CHANGELOG.md](CHANGELOG.md) for more history information.
110
+
111
+
112
+ ## Author Contact
113
+ This program is designed and developed by Yang Li. You can reach him by Email: <yang.li@owasp.org>
114
+ ## Bug Report or Feature Request?
115
+ Contact the author Sam (Yang) Li directly at email 'yang.li@owasp.org'.
102
116
 
103
117
 
104
- == Legal Disclaimer:
118
+ ## Legal Disclaimer:
105
119
  This software is provided strictly 'as-if' without any implied warranty. You're free to copy or modify the codes anyway you want - a reference back to this software will be appreciated. Please refer to the 'LICENSE.txt' file for more information.
data/bin/wmap CHANGED
@@ -5,22 +5,25 @@
5
5
  # Usage: wmap <Target Host | URL | IP | CIDR | or a seed file with any of the above combo> <Optional Discovery Result Directory>
6
6
  require "wmap"
7
7
 
8
+ # program helper
8
9
  def print_usage
9
10
  abort "Program to perform website asset discovery and tracking. \nUsage: wmap <Target Host | URL | IP | CIDR | or a seed file with any of the above combo> <Optional Discovery Result Directory>"
10
11
  end
11
-
12
- # preparing - spit out the program banner
12
+ # print program banner
13
13
  puts Wmap.banner
14
+
15
+ # Preparing - check out the working logs directory
14
16
  if ARGV.length == 2
15
17
  # Log to the instance running directory
16
- Log_dir=File.dirname(__FILE__)+'/../logs/'+ARGV[1]
18
+ Log_dir = Pathname.new(ARGV[1]).join('logs')
17
19
  else
18
20
  # Log the command entry
19
- Log_dir=File.dirname(__FILE__)+'/../logs/'
21
+ Log_dir=Pathname.new(Gem.loaded_specs['wmap'].full_gem_path).join('logs')
20
22
  end
21
23
  Dir.mkdir(Log_dir) unless Dir.exist?(Log_dir)
22
24
 
23
- Wmap.wlog("Execute the command: wmap #{ARGV[0]}","wmap",Log_dir+"wmap.log")
25
+ # Start wmap logging
26
+ Wmap.wlog("Execute the command: wmap #{ARGV[0]}","wmap",Log_dir.join("wmap.log").to_s)
24
27
  print_usage unless (ARGV.length==1 or ARGV.length==2)
25
28
  urls = Array.new
26
29
  # first step - construct the host list
@@ -64,38 +67,16 @@ else
64
67
  print_usage
65
68
  end
66
69
 
67
- # second step - update the hosts repository
68
- if ARGV.length == 1
69
- puts puts "Invoke the HostTracker."
70
- host_tracker = Wmap::HostTracker.instance
71
- host_tracker.verbose=true
72
- elsif ARGV.length == 2
73
- puts "Invoke the HostTracker with optional directory setter."
74
- host_tracker = Wmap::HostTracker.instance
75
- host_tracker.verbose=true
76
- host_tracker.data_dir = ARGV[1]
77
- else
78
- aborts "Error firing up HostTracker instance!"
79
- end
80
- hosts.uniq!
81
- if hosts.size > 0
82
- hostnames=hosts.dup.delete_if { |h| host_tracker.is_ip?(h) }
83
- if hostnames.size > 0
84
- puts "Update the local hosts data repository."
85
- new_hosts=host_tracker.adds(hostnames)
86
- host_tracker.save! if new_hosts.size>0
87
- end
88
- end
89
- host_tracker=nil
90
70
 
91
- # third step - port discovery on the above host list, and to build the URL seeds
71
+ # second step - port discovery on the above host list, and to build the URL seeds
92
72
  puts "Build up URL list for the web crawler ..."
93
73
  urls0=scanner.scans(hosts)
94
74
  urls+=urls0
95
75
  urls.uniq!
96
76
  scanner=nil
97
77
 
98
- # fourth step - crawling on the URL seeds
78
+
79
+ # third step - crawling on the URL seeds
99
80
  if ARGV.length == 1
100
81
  puts "Fire up the crawler."
101
82
  crawler = Wmap::UrlCrawler.new(:verbose=>false)
@@ -125,14 +106,16 @@ else
125
106
  dis_sites.keys.map {|x| puts x}
126
107
  end
127
108
 
128
- # fifth step - trace the discovery results into a local log file for debugging and other purposes
109
+
110
+ # fourth step - trace the discovery results into a local log file for debugging and other purposes
129
111
  Wmap.wlog(dis_urls.keys, "wmap", Log_dir+"discovered_urls.log") unless dis_urls.empty?
130
112
  Wmap.wlog(dis_sites.keys, "wmap", Log_dir+"discovered_sites.log") unless dis_sites.empty?
131
113
  #crawler.wlog(c_start.keys,Log_dir+"crawler.log")
132
114
  #crawler.wlog(c_done.keys,Log_dir+"crawler.log")
133
115
  crawler=nil
134
116
 
135
- # sixth step - save discovery results into the inventory data repository
117
+
118
+ # fifth step - save discovery results into the inventory data repository
136
119
  case dis_sites.keys
137
120
  when nil,[]
138
121
  puts "No new site found. There is no change to the site tracking data repository. "
@@ -145,6 +128,8 @@ else
145
128
  puts "Start the SiteTracker with the optional directory setter. "
146
129
  inventory=Wmap::SiteTracker.instance
147
130
  inventory.data_dir = ARGV[1]
131
+ inventory.sites_file = inventory.data_dir + "sites"
132
+ inventory.load_site_stores_from_file
148
133
  else
149
134
  aborts "Error firing up SiteTracker instance!"
150
135
  end
@@ -153,3 +138,32 @@ else
153
138
  inventory=nil
154
139
  puts "Done! New found sites are successfully saved. " if new_sites.size > 0
155
140
  end
141
+
142
+
143
+ # seventh step - update the hosts repository
144
+ if ARGV.length == 1
145
+ puts puts "Invoke the HostTracker."
146
+ host_tracker = Wmap::HostTracker.instance
147
+ host_tracker.verbose=true
148
+ elsif ARGV.length == 2
149
+ puts "Invoke the HostTracker with optional directory setter."
150
+ host_tracker = Wmap::HostTracker.instance
151
+ host_tracker.verbose=true
152
+ host_tracker.data_dir = ARGV[1]
153
+ host_tracker.hosts_file = host_tracker.data_dir + "hosts"
154
+ host_tracker.load_known_hosts_from_file
155
+ else
156
+ aborts "Error firing up HostTracker instance!"
157
+ end
158
+ new_hosts = dis_sites.keys.map {|x| host_tracker.url_2_host(x)}
159
+ hosts += new_hosts
160
+ hosts.uniq!
161
+ if hosts.size > 0
162
+ hostnames=hosts.dup.delete_if { |h| host_tracker.is_ip?(h) }
163
+ if hostnames.size > 0
164
+ puts "Update the local hosts data repository with: #{hostnames}"
165
+ new_hosts=host_tracker.adds(hostnames)
166
+ host_tracker.save! if new_hosts.size>0
167
+ end
168
+ end
169
+ host_tracker=nil
@@ -17,8 +17,7 @@ class SubDomain < Wmap::DomainTracker
17
17
  include Wmap::Utils
18
18
  include Singleton
19
19
 
20
- attr_accessor :verbose, :domains_file, :max_parallel, :data_dir
21
- attr_reader :known_internet_sub_domains
20
+ attr_accessor :verbose, :sub_domains_file, :max_parallel, :data_dir, :known_internet_sub_domains
22
21
 
23
22
  # Set default instance variables
24
23
  def initialize (params = {})
@@ -26,111 +25,102 @@ class SubDomain < Wmap::DomainTracker
26
25
  @data_dir=params.fetch(:data_dir, File.dirname(__FILE__)+'/../../../data/')
27
26
  @max_parallel=params.fetch(:max_parallel, 40)
28
27
  # Hash table to hold the trusted domains
29
- @file_sub_domains=@data_dir + 'sub_domains'
30
- File.write(@file_sub_domains, "") unless File.exist?(@file_sub_domains)
31
- @known_internet_sub_domains=load_domains_from_file(@file_sub_domains) #unless @known_internet_sub_domains.size>0
32
- end
28
+ @sub_domains_file=params.fetch(:sub_domains_file, @data_dir + 'sub_domains')
29
+ File.write(@sub_domains_file, "") unless File.exist?(@sub_domains_file)
30
+ @known_internet_sub_domains=load_domains_from_file(@sub_domains_file) #unless @known_internet_sub_domains.size>0
31
+ end
33
32
 
34
33
  # 'setter' to add sub-domain entry to the cache one at a time
35
34
  def add(sub)
36
35
  puts "Add entry to the local sub domain cache table: #{sub}" if @verbose
37
- begin
38
- record=Hash.new
39
- sub=sub.strip.downcase
40
- if @known_internet_sub_domains.key?(sub)
41
- puts "Skip on known sub-domain: #{sub}" if @verbose
42
- return nil
43
- end
44
- if zone_transferable?(sub)
45
- record[sub]=true
46
- else
47
- record[sub]=false
48
- end
49
- puts "Adding new record into the data store: #{record}" if @verbose
50
- @known_internet_sub_domains.merge!(record)
51
- return record
52
- rescue => ee
53
- puts "Exception on method #{__method__} for #{sub}: #{ee}" if @verbose
36
+ record=Hash.new
37
+ sub=sub.strip.downcase
38
+ if @known_internet_sub_domains.key?(sub)
39
+ puts "Skip on known sub-domain: #{sub}" if @verbose
40
+ return nil
54
41
  end
42
+ if zone_transferable?(sub)
43
+ record[sub]=true
44
+ else
45
+ record[sub]=false
46
+ end
47
+ puts "Adding new record into the data store: #{record}" if @verbose
48
+ @known_internet_sub_domains.merge!(record)
49
+ return record
50
+ rescue => ee
51
+ puts "Exception on method #{__method__} for #{sub}: #{ee}" if @verbose
55
52
  end
56
53
 
57
54
  # 'setter' to add domain entry to the cache in batch (from a list)
58
55
  def bulk_add(list, num=@max_parallel)
59
56
  puts "Add entries to the local domains cache table from list: #{list}" if @verbose
60
- begin
61
- results=Hash.new
62
- domains=list
63
- if domains.size > 0
64
- Parallel.map(list, :in_processes => num) { |target|
65
- add(target)
66
- }.each do |process|
67
- if process.nil?
68
- next
69
- elsif process.empty?
70
- #do nothing
71
- else
72
- results.merge!(process)
73
- end
57
+ results=Hash.new
58
+ domains=list
59
+ if domains.size > 0
60
+ Parallel.map(list, :in_processes => num) { |target|
61
+ add(target)
62
+ }.each do |process|
63
+ if process.nil?
64
+ next
65
+ elsif process.empty?
66
+ #do nothing
67
+ else
68
+ results.merge!(process)
74
69
  end
75
- @known_internet_sub_domains.merge!(results)
76
- puts "Done loading entries."
77
- return results
78
- else
79
- puts "Error: no entry is loaded. Please check your list and try again."
80
70
  end
71
+ @known_internet_sub_domains.merge!(results)
72
+ puts "Done loading entries."
81
73
  return results
82
- rescue => ee
83
- puts "Exception on method #{__method__}: #{ee}" if @verbose
74
+ else
75
+ puts "Error: no entry is loaded. Please check your list and try again."
84
76
  end
77
+ return results
78
+ rescue => ee
79
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
85
80
  end
86
81
  alias_method :adds, :bulk_add
87
82
 
88
83
  # Procedures to identify sub-domain from the hosts store
89
84
  def update_from_host_store!
90
85
  puts "Invoke internal procedures to update the sub-domain list from the host store."
91
- begin
92
- # Step 1 - obtain the latest sub-domains
93
- my_tracker = Wmap::HostTracker.instance
94
- my_tracker.data_dir=@data_dir
95
- subs = my_tracker.dump_sub_domains - [nil,""]
96
- my_tracker = nil
97
- # Step 2 - update the sub-domain list
98
- unless subs.empty?
99
- #subs.map { |x| self.add(x) unless domain_known?(x) }
100
- self.bulk_add(subs,@max_parallel)
101
- end
102
- puts "Update discovered sub-domains into the store: #{@known_internet_sub_domains}"
103
- self.save!(file_domains=@file_sub_domains, domains=@known_internet_sub_domains)
104
- rescue Exception => ee
105
- puts "Exception on method #{__method__}: #{ee}" if @verbose
106
- return nil
86
+ # Step 1 - obtain the latest sub-domains
87
+ my_tracker = Wmap::HostTracker.instance
88
+ my_tracker.data_dir=@data_dir
89
+ subs = my_tracker.dump_sub_domains - [nil,""]
90
+ my_tracker = nil
91
+ # Step 2 - update the sub-domain list
92
+ unless subs.empty?
93
+ #subs.map { |x| self.add(x) unless domain_known?(x) }
94
+ self.bulk_add(subs,@max_parallel)
107
95
  end
96
+ puts "Update discovered sub-domains into the store: #{@known_internet_sub_domains}"
97
+ self.save!(file_domains=@file_sub_domains, domains=@known_internet_sub_domains)
98
+ rescue Exception => ee
99
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
100
+ return nil
108
101
  end
109
102
  alias_method :update!, :update_from_host_store!
110
103
 
111
104
  # Save the current domain hash table into a file
112
105
  def save_sub_domains_to_file!(file_domains=@file_sub_domains, domains=@known_internet_sub_domains)
113
106
  puts "Saving the current domains cache table from memory to file: #{file_domains} ..." if @verbose
114
- begin
115
- timestamp=Time.now
116
- f=File.open(file_domains, 'w')
117
- f.write "# Local domains file created by class #{self.class} method #{__method__} at: #{timestamp}\n"
118
- f.write "# domain name, free zone transfer detected?\n"
119
- domains.keys.sort.map do |key|
120
- if domains[key]
121
- f.write "#{key}, yes\n"
122
- else
123
- f.write "#{key}, no\n"
124
- end
107
+ timestamp=Time.now
108
+ f=File.open(file_domains, 'w')
109
+ f.write "# Local domains file created by class #{self.class} method #{__method__} at: #{timestamp}\n"
110
+ f.write "# domain name, free zone transfer detected?\n"
111
+ domains.keys.sort.map do |key|
112
+ if domains[key]
113
+ f.write "#{key}, yes\n"
114
+ else
115
+ f.write "#{key}, no\n"
125
116
  end
126
- f.close
127
- puts "Domain cache table is successfully saved: #{file_domains}"
128
- rescue => ee
129
- puts "Exception on method #{__method__}: #{ee}" if @verbose
130
117
  end
118
+ f.close
119
+ puts "Domain cache table is successfully saved: #{file_domains}"
120
+ rescue => ee
121
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
131
122
  end
132
123
  alias_method :save!, :save_sub_domains_to_file!
133
- end
134
124
 
135
125
  # Print summary report on all known / trust domains in the domain cache table
136
126
  def print_known_sub_domains
@@ -143,3 +133,4 @@ end
143
133
 
144
134
  end
145
135
  end
136
+ end