wmap 2.7.6 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/wmap +9 -1
- data/dicts/tlds.txt +9 -30
- data/lib/wmap.rb +1 -0
- data/lib/wmap/cidr_tracker.rb +3 -2
- data/lib/wmap/site_tracker/wp_tracker.rb +2 -226
- data/lib/wmap/url_crawler.rb +9 -21
- data/lib/wmap/utils/domain_root.rb +1 -1
- data/lib/wmap/utils/logger.rb +31 -34
- data/lib/wmap/utils/url_magic.rb +37 -4
- data/lib/wmap/utils/utils.rb +10 -12
- data/lib/wmap/utils/wp_detect.rb +358 -0
- data/test/cidr_tracker_test.rb +36 -0
- data/test/utils_test.rb +51 -46
- data/version.txt +2 -2
- data/wmap.gemspec +1 -1
- metadata +7 -9
- data/bin/RHPG +0 -107
- data/bin/wmaps +0 -23
- data/settings/tag_signatures +0 -6
data/lib/wmap/url_crawler.rb
CHANGED
@@ -17,7 +17,8 @@ require "parallel"
|
|
17
17
|
class Wmap::UrlCrawler
|
18
18
|
include Wmap::Utils
|
19
19
|
|
20
|
-
attr_accessor :http_timeout, :crawl_page_limit, :crawl_depth, :max_parallel,
|
20
|
+
attr_accessor :http_timeout, :crawl_page_limit, :crawl_depth, :max_parallel, \
|
21
|
+
:verbose, :data_dir, :user_agent
|
21
22
|
attr_reader :discovered_urls_by_crawler, :visited_urls_by_crawler, :crawl_start, :crawl_done
|
22
23
|
# Global variable used to store the combined result of all the forked child processes. Note that class variable
|
23
24
|
# would not be able to pass the result due the limitation of IO Pipe communication mechanism used by 'parallel' fork manager
|
@@ -35,13 +36,16 @@ class Wmap::UrlCrawler
|
|
35
36
|
@crawl_depth=params.fetch(:crawl_depth, 4)
|
36
37
|
@crawl_page_limit=params.fetch(:crawl_page_limit, 1000)
|
37
38
|
@max_parallel=params.fetch(:max_parallel, 40)
|
39
|
+
@user_agent=params.fetch(:user_agent, "OWASP WMAP Spider")
|
38
40
|
# Discovered data store
|
39
41
|
@discovered_urls_by_crawler=Hash.new
|
40
42
|
@visited_urls_by_crawler=Hash.new
|
41
43
|
@crawl_start=Hash.new
|
42
44
|
@crawl_done=Hash.new
|
43
45
|
Dir.mkdir(@data_dir) unless Dir.exist?(@data_dir)
|
44
|
-
@
|
46
|
+
@log_dir=@data_dir + "/logs/"
|
47
|
+
Dir.mkdir(@log_dir) unless Dir.exist?(@log_dir)
|
48
|
+
@log_file=@log_dir + "crawler.log"
|
45
49
|
end
|
46
50
|
|
47
51
|
# Pre-crawl profiler, to be used for network profiling to maximum the crawler performance.
|
@@ -216,14 +220,14 @@ class Wmap::UrlCrawler
|
|
216
220
|
alias_method :crawl_file, :crawl_workers_on_file
|
217
221
|
|
218
222
|
# Wrapper for the OpenURI open method - create an open_uri object and return the reference upon success
|
219
|
-
def open_url(url)
|
223
|
+
def open_url(url,user_agent=@user_agent)
|
220
224
|
puts "Open url #{url} by creating an open_uri object. Return the reference upon success." if @verbose
|
221
225
|
if url =~ /http\:/i
|
222
226
|
# patch for allow the 'un-safe' URL redirection i.e. https://www.example.com -> http://www.example.com
|
223
|
-
url_object = open(url, :allow_redirections=>:safe, :read_timeout=>Max_http_timeout/1000)
|
227
|
+
url_object = open(url, :allow_redirections=>:safe, :read_timeout=>Max_http_timeout/1000, "User-Agent"=>user_agent)
|
224
228
|
#url_object = open(url)
|
225
229
|
elsif url =~ /https\:/i
|
226
|
-
url_object = open(url
|
230
|
+
url_object = open(url, :ssl_verify_mode=>0, :allow_redirections=>:safe, :read_timeout=>Max_http_timeout/1000, "User-Agent"=>user_agent)
|
227
231
|
#url_object = open(url,:ssl_verify_mode => 0)
|
228
232
|
else
|
229
233
|
raise "Invalid URL format - please specify the protocol prefix http(s) in the URL: #{url}"
|
@@ -258,22 +262,6 @@ class Wmap::UrlCrawler
|
|
258
262
|
return nil
|
259
263
|
end
|
260
264
|
|
261
|
-
=begin
|
262
|
-
# Wrapper for the Nokogiri DOM parser
|
263
|
-
def parse_html(html_body)
|
264
|
-
begin
|
265
|
-
#puts "Parsing the html content: #{html_body}. Return DOM " if @verbose
|
266
|
-
doc = Nokogiri::HTML(html_body)
|
267
|
-
#puts "Successfully crawling the url: #{url_object.base_uri.to_s}" if @verbose
|
268
|
-
#puts "doc: #{doc}" if @verbose
|
269
|
-
return doc
|
270
|
-
rescue => ee
|
271
|
-
puts "Exception on method #{__method__}: #{ee}" if @verbose
|
272
|
-
return nil
|
273
|
-
end
|
274
|
-
end
|
275
|
-
=end
|
276
|
-
|
277
265
|
# Search 'current_url' and return found URLs under the same domain
|
278
266
|
def find_urls_on_page(doc, current_url)
|
279
267
|
puts "Search and return URLs within the doc: #{doc}" if @verbose
|
data/lib/wmap/utils/logger.rb
CHANGED
@@ -8,46 +8,43 @@
|
|
8
8
|
|
9
9
|
|
10
10
|
module Wmap
|
11
|
-
module Utils
|
11
|
+
module Utils
|
12
12
|
# Module to log debugging and other messages
|
13
|
-
module Logger
|
13
|
+
module Logger
|
14
14
|
extend self
|
15
15
|
# Append information into the log file for the trouble-shooting purpose
|
16
16
|
def wlog (obj, agent, file)
|
17
17
|
puts "Writing #{obj} into log file: #{file}" if @verbose
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
obj.map { |x| @@f.write " #{x}\n" }
|
28
|
-
puts "The list is successfully saved into the log file: #{file} " if @verbose
|
29
|
-
end
|
30
|
-
when Hash
|
31
|
-
if obj.length >= 0
|
32
|
-
@@f.write "#{timestamp}: #{agent}: \n"
|
33
|
-
obj.each_value { |value| @@f.write " #{value}\n" }
|
34
|
-
puts "The hash is successfully saved into the log file: #{file} " if @verbose
|
35
|
-
end
|
36
|
-
when String
|
37
|
-
@@f.write "#{timestamp}: #{agent}: #{obj}\n"
|
38
|
-
puts "The string is successfully saved into the log file: #{file} " if @verbose
|
39
|
-
else
|
40
|
-
#do nothing
|
41
|
-
puts "Un-handled exception on: #{obj}" if @verbose
|
18
|
+
return false if obj.nil?
|
19
|
+
@@f=File.open(file,'a')
|
20
|
+
timestamp=Time.now
|
21
|
+
case obj
|
22
|
+
when Array
|
23
|
+
if obj.size >= 0
|
24
|
+
@@f.write "#{timestamp}: #{agent}: \n"
|
25
|
+
obj.map { |x| @@f.write " #{x}\n" }
|
26
|
+
puts "The list is successfully saved into the log file: #{file} " if @verbose
|
42
27
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
28
|
+
when Hash
|
29
|
+
if obj.length >= 0
|
30
|
+
@@f.write "#{timestamp}: #{agent}: \n"
|
31
|
+
obj.each_value { |value| @@f.write " #{value}\n" }
|
32
|
+
puts "The hash is successfully saved into the log file: #{file} " if @verbose
|
33
|
+
end
|
34
|
+
when String
|
35
|
+
@@f.write "#{timestamp}: #{agent}: #{obj}\n"
|
36
|
+
puts "The string is successfully saved into the log file: #{file} " if @verbose
|
37
|
+
else
|
38
|
+
#do nothing
|
39
|
+
puts "Un-handled exception on: #{obj}" if @verbose
|
40
|
+
end
|
41
|
+
@@f.close
|
42
|
+
return true
|
43
|
+
rescue => ee
|
44
|
+
puts "Exception on method #{__method__}: #{ee}" if @verbose
|
45
|
+
return false
|
49
46
|
end
|
50
|
-
|
51
|
-
end
|
47
|
+
|
48
|
+
end
|
52
49
|
end
|
53
50
|
end
|
data/lib/wmap/utils/url_magic.rb
CHANGED
@@ -15,6 +15,7 @@ module Wmap
|
|
15
15
|
|
16
16
|
# set hard stop limit of http time-out to 8 seconds, in order to avoid severe performance penalty for certain 'weird' site(s)
|
17
17
|
Max_http_timeout=15000
|
18
|
+
User_agent = "OWASP WMAP Spider"
|
18
19
|
|
19
20
|
# Simple sanity check on a 'claimed' URL string.
|
20
21
|
def is_url?(url)
|
@@ -263,7 +264,7 @@ module Wmap
|
|
263
264
|
return absolute_url
|
264
265
|
rescue => ee
|
265
266
|
puts "Exception on method #{__method__}: #{ee}" if @verbose
|
266
|
-
|
267
|
+
return nil
|
267
268
|
end
|
268
269
|
|
269
270
|
# Normalize the URL to a consistent manner in order to determine if a link has been visited or cached before
|
@@ -292,7 +293,6 @@ module Wmap
|
|
292
293
|
return url
|
293
294
|
end
|
294
295
|
|
295
|
-
|
296
296
|
# Test the URL and return the response code
|
297
297
|
def response_code (url)
|
298
298
|
puts "Check the http response code on the url: #{url}" if @verbose
|
@@ -344,9 +344,42 @@ module Wmap
|
|
344
344
|
return code
|
345
345
|
end
|
346
346
|
|
347
|
+
# Test the URL and return the response headers
|
348
|
+
def response_headers (url)
|
349
|
+
puts "Check the http response headers on the url: #{url}" if @verbose
|
350
|
+
raise "Invalid url: #{url}" unless is_url?(url)
|
351
|
+
headers = Hash.new
|
352
|
+
url=url.strip.downcase
|
353
|
+
timeo = Max_http_timeout/1000.0
|
354
|
+
uri = URI.parse(url)
|
355
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
356
|
+
http.open_timeout = timeo
|
357
|
+
http.read_timeout = timeo
|
358
|
+
if (url =~ /https\:/i)
|
359
|
+
http.use_ssl = true
|
360
|
+
#http.ssl_version = :SSLv3
|
361
|
+
# Bypass the remote web server cert validation test
|
362
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
363
|
+
end
|
364
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
365
|
+
response = http.request(request)
|
366
|
+
puts "Server response the following: #{response}" if @verbose
|
367
|
+
response.each_header do |key,val|
|
368
|
+
puts "#{key} => #{val}" if @verbose
|
369
|
+
headers.merge!({key => val})
|
370
|
+
end
|
371
|
+
puts "Response headers on #{url}: #{headers}" if @verbose
|
372
|
+
return headers
|
373
|
+
rescue => ee
|
374
|
+
puts "Exception on method #{__method__}: #{ee}" if @verbose
|
375
|
+
return nil
|
376
|
+
end
|
377
|
+
|
378
|
+
|
347
379
|
# Given an URL, open the page, then return the DOM text from a normal user perspective
|
348
380
|
def open_page(url)
|
349
|
-
args = {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, allow_redirections: :safe,
|
381
|
+
args = {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, allow_redirections: :safe, \
|
382
|
+
read_timeout: Max_http_timeout/1000, "User-Agent"=>User_agent}
|
350
383
|
doc = Nokogiri::HTML(open(url, args))
|
351
384
|
if doc.text.include?("Please enable JavaScript to view the page content")
|
352
385
|
puts "Invoke headless chrome through webdriver ..." if @verbose
|
@@ -354,7 +387,7 @@ module Wmap
|
|
354
387
|
#driver = Selenium::WebDriver.for :chrome
|
355
388
|
# http://watir.com/guides/chrome/
|
356
389
|
args = ['--ignore-certificate-errors', '--disable-popup-blocking', '--disable-translate', '--disk-cache-size 8192']
|
357
|
-
browser = Watir::Browser.new :chrome, headless: true,
|
390
|
+
browser = Watir::Browser.new :chrome, headless: true, switches: %w[--user-agent=OWASP\ WMAP\ Spider]
|
358
391
|
browser.goto(url)
|
359
392
|
sleep(2) # wait for the loading
|
360
393
|
doc = Nokogiri::HTML(browser.html)
|
data/lib/wmap/utils/utils.rb
CHANGED
@@ -159,20 +159,18 @@ module Wmap
|
|
159
159
|
# Simple test a host string format. Return true if it contains a valid internet domain sub-string. Note: Don't be confused with another method 'valid_dns_record?', which is a stricter and time-consuming test on the DNS server for a resolvable internet host.
|
160
160
|
def is_fqdn? (host)
|
161
161
|
puts "Validate the host-name format is valid: #{host}" if @verbose
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
else
|
170
|
-
return false
|
171
|
-
end
|
172
|
-
rescue => ee
|
173
|
-
puts "Exception on method is_fqdn? for #{host}: #{ee}" if @verbose
|
162
|
+
return false if is_ip?(host) or is_url?(host)
|
163
|
+
domain=get_domain_root(host)
|
164
|
+
if domain.nil?
|
165
|
+
return false
|
166
|
+
elsif is_domain_root?(domain)
|
167
|
+
return true
|
168
|
+
else
|
174
169
|
return false
|
175
170
|
end
|
171
|
+
# rescue => ee
|
172
|
+
# puts "Exception on method is_fqdn? for #{host}: #{ee}" if @verbose
|
173
|
+
# return false
|
176
174
|
end
|
177
175
|
alias_method :is_host?, :is_fqdn?
|
178
176
|
|
@@ -0,0 +1,358 @@
|
|
1
|
+
#--
|
2
|
+
# Wmap
|
3
|
+
#
|
4
|
+
# A pure Ruby library for Internet web application discovery and tracking.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2012-2015 Yang Li <yang.li@owasp.org>
|
7
|
+
#++
|
8
|
+
|
9
|
+
# Utilities for wp_tracker class only; must use with other Utils modules.
|
10
|
+
module Wmap
|
11
|
+
module Utils
|
12
|
+
module WpDetect
|
13
|
+
extend self
|
14
|
+
|
15
|
+
# Main method to detect if it's a wordpress site
|
16
|
+
def is_wp?(url)
|
17
|
+
site=url_2_site(url)
|
18
|
+
if wp_readme?(site)
|
19
|
+
return true
|
20
|
+
elsif wp_css?(site)
|
21
|
+
return true
|
22
|
+
elsif wp_meta?(site)
|
23
|
+
return true
|
24
|
+
elsif wp_login?(site)
|
25
|
+
return true
|
26
|
+
elsif wp_rpc?(site)
|
27
|
+
return true
|
28
|
+
elsif wp_gen?(site)
|
29
|
+
return true
|
30
|
+
elsif wp_load_styles?(site)
|
31
|
+
return true
|
32
|
+
else
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
rescue => ee
|
36
|
+
puts "Exception on method #{__method__}: #{ee}: #{url}" if @verbose
|
37
|
+
end
|
38
|
+
|
39
|
+
# Main method to extract the WordPress version
|
40
|
+
def wp_ver(url)
|
41
|
+
if !wp_ver_readme(url).nil?
|
42
|
+
puts "WordPress version found by wp_ver_readme method. " if @verbose
|
43
|
+
return wp_ver_readme(url)
|
44
|
+
elsif !wp_ver_login(url,"login.min.css").nil?
|
45
|
+
puts "WordPress version found by login.min.css file. " if @verbose
|
46
|
+
return wp_ver_login(url,"login.min.css")
|
47
|
+
elsif !wp_ver_login(url,"buttons.min.css").nil?
|
48
|
+
puts "WordPress version found by buttons.min.css file. " if @verbose
|
49
|
+
return wp_ver_login(url,"buttons.min.css")
|
50
|
+
elsif !wp_ver_login(url,"wp-admin.min.css").nil?
|
51
|
+
puts "WordPress version found by wp-admin.min.css file. " if @verbose
|
52
|
+
return wp_ver_login(url,"wp-admin.min.css")
|
53
|
+
elsif !wp_ver_meta(url).nil?
|
54
|
+
puts "WordPress version found by wp_ver_meta method. " if @verbose
|
55
|
+
return wp_ver_meta(url)
|
56
|
+
elsif !wp_ver_generator(url).nil?
|
57
|
+
puts "WordPress version found by wp_ver_generator method. " if @verbose
|
58
|
+
return wp_ver_generator(url)
|
59
|
+
elsif !wp_ver_load_styles(url).nil?
|
60
|
+
puts "WordPress version found by wp_ver_load_styles method. " if @verbose
|
61
|
+
return wp_ver_load_styles(url)
|
62
|
+
else
|
63
|
+
return nil
|
64
|
+
end
|
65
|
+
rescue => ee
|
66
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
67
|
+
return nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# Wordpress detection checkpoint - readme.html
|
71
|
+
def wp_readme?(url)
|
72
|
+
site = url_2_site(url)
|
73
|
+
readme_url=site + "readme.html"
|
74
|
+
k=Wmap::UrlChecker.new
|
75
|
+
if k.response_code(readme_url) == 200
|
76
|
+
k=nil
|
77
|
+
doc=open_page(readme_url)
|
78
|
+
title=doc.css('title')
|
79
|
+
if title.to_s =~ /wordpress/i
|
80
|
+
return true
|
81
|
+
else
|
82
|
+
return false
|
83
|
+
end
|
84
|
+
else
|
85
|
+
k=nil
|
86
|
+
return false
|
87
|
+
end
|
88
|
+
rescue => ee
|
89
|
+
puts "Exception on method #{__method__} for site #{url}: #{ee}" if @verbose
|
90
|
+
return false
|
91
|
+
end
|
92
|
+
|
93
|
+
# Wordpress detection checkpoint - install.css
|
94
|
+
def wp_css?(url)
|
95
|
+
site = url_2_site(url)
|
96
|
+
css_url = site + "wp-admin/css/install.css"
|
97
|
+
k=Wmap::UrlChecker.new
|
98
|
+
if k.response_code(css_url) == 200
|
99
|
+
k=nil
|
100
|
+
parser = CssParser::Parser.new
|
101
|
+
parser.load_uri!(css_url)
|
102
|
+
rule = parser.find_by_selector('#logo a')
|
103
|
+
if rule.length >0
|
104
|
+
if rule[0] =~ /wordpress/i
|
105
|
+
return true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
k=nil
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
return false
|
113
|
+
rescue => ee
|
114
|
+
puts "Exception on method #{__method__} for site #{url}: #{ee}" if @verbose
|
115
|
+
return false
|
116
|
+
end
|
117
|
+
|
118
|
+
# Wordpress detection checkpoint - WP meta tag
|
119
|
+
def wp_meta?(url)
|
120
|
+
site=url_2_site(url)
|
121
|
+
k=Wmap::UrlChecker.new
|
122
|
+
if k.response_code(site) == 200
|
123
|
+
k=nil
|
124
|
+
doc=open_page(site)
|
125
|
+
meta=doc.css('meta')
|
126
|
+
if meta.to_s =~ /wordpress/i
|
127
|
+
return true
|
128
|
+
else
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return false
|
133
|
+
rescue => ee
|
134
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
135
|
+
return false
|
136
|
+
end
|
137
|
+
|
138
|
+
# Wordpress detection checkpoint - WP generator tag
|
139
|
+
def wp_gen?(url)
|
140
|
+
puts "#{__method__} check for #{url}" if @verbose
|
141
|
+
site = url_2_site(url)
|
142
|
+
gen_url_1 = site + "feed/"
|
143
|
+
gen_url_2 = site + "comments/feed"
|
144
|
+
k=Wmap::UrlChecker.new
|
145
|
+
if k.response_code(gen_url_1) == 200
|
146
|
+
doc=open_page(gen_url_1)
|
147
|
+
elsif k.response_code(gen_url_2) == 200
|
148
|
+
doc=open_page(gen_url_2)
|
149
|
+
else
|
150
|
+
k=nil
|
151
|
+
return false
|
152
|
+
end
|
153
|
+
#puts doc.inspect
|
154
|
+
gens=doc.css('generator')
|
155
|
+
if gens.nil?
|
156
|
+
k=nil
|
157
|
+
return false
|
158
|
+
end
|
159
|
+
gens.each do |gen|
|
160
|
+
if gen.text.to_s =~ /wordpress/i
|
161
|
+
k=doc=nil
|
162
|
+
return true
|
163
|
+
end
|
164
|
+
end
|
165
|
+
k=doc=nil
|
166
|
+
return false
|
167
|
+
rescue => ee
|
168
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
169
|
+
return false
|
170
|
+
end
|
171
|
+
|
172
|
+
# Wordpress detection checkpoint - wp-login
|
173
|
+
def wp_login?(url)
|
174
|
+
site=url_2_site(url)
|
175
|
+
login_url=site + "wp-login.php"
|
176
|
+
k=Wmap::UrlChecker.new
|
177
|
+
if k.response_code(login_url) == 200
|
178
|
+
k=nil
|
179
|
+
doc=open_page(login_url)
|
180
|
+
links=doc.css('link')
|
181
|
+
if links.to_s =~ /login.min.css/i
|
182
|
+
return true
|
183
|
+
else
|
184
|
+
return false
|
185
|
+
end
|
186
|
+
end
|
187
|
+
return false
|
188
|
+
rescue => ee
|
189
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
190
|
+
return false
|
191
|
+
end
|
192
|
+
|
193
|
+
# Wordpress detection checkpoint - xml-rpc
|
194
|
+
def wp_rpc?(url)
|
195
|
+
site=url_2_site(url)
|
196
|
+
rpc_url=site + "xmlrpc.php"
|
197
|
+
k=Wmap::UrlChecker.new
|
198
|
+
#puts "res code", k.response_code(rpc_url)
|
199
|
+
if k.response_code(rpc_url) == 405 # method not allowed
|
200
|
+
k=nil
|
201
|
+
return true
|
202
|
+
end
|
203
|
+
return false
|
204
|
+
rescue => ee
|
205
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
206
|
+
return false
|
207
|
+
end
|
208
|
+
|
209
|
+
# Wordpress detection checkpoint - /wp-admin/load-styles.php
|
210
|
+
def wp_load_styles?(url)
|
211
|
+
site = url_2_site(url)
|
212
|
+
load_styles_url=site + "wp-admin/load-styles.php"
|
213
|
+
k=Wmap::UrlChecker.new
|
214
|
+
if k.response_code(load_styles_url) == 200 && k.response_headers(load_styles_url).keys.include?("etag")
|
215
|
+
k=nil
|
216
|
+
return true
|
217
|
+
else
|
218
|
+
k=nil
|
219
|
+
return false
|
220
|
+
end
|
221
|
+
rescue => ee
|
222
|
+
puts "Exception on method #{__method__} for site #{url}: #{ee}" if @verbose
|
223
|
+
return false
|
224
|
+
end
|
225
|
+
|
226
|
+
# Identify wordpress version through the login page
|
227
|
+
def wp_ver_login(url,pattern)
|
228
|
+
puts "Check for #{pattern}" if @verbose
|
229
|
+
site=url_2_site(url)
|
230
|
+
login_url=site + "wp-login.php"
|
231
|
+
k=Wmap::UrlChecker.new
|
232
|
+
#puts "Res code: #{k.response_code(login_url)}" if @verbose
|
233
|
+
if k.response_code(login_url) == 200
|
234
|
+
doc=open_page(login_url)
|
235
|
+
#puts doc.inspect
|
236
|
+
links=doc.css('link')
|
237
|
+
#puts links.inspect if @verbose
|
238
|
+
links.each do |tag|
|
239
|
+
if tag.to_s.include?(pattern)
|
240
|
+
puts tag.to_s if @verbose
|
241
|
+
k=nil
|
242
|
+
if tag.to_s.scan(/[\d+\.]+\d+/).first =~ /\d+\./
|
243
|
+
return tag.to_s.scan(/[\d+\.]+\d+/).first
|
244
|
+
else
|
245
|
+
return nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
k=nil
|
251
|
+
return nil
|
252
|
+
rescue => ee
|
253
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
254
|
+
return nil
|
255
|
+
end
|
256
|
+
|
257
|
+
# Identify wordpress version through the meta link
|
258
|
+
def wp_ver_meta(url)
|
259
|
+
site=url_2_site(url)
|
260
|
+
k=Wmap::UrlChecker.new
|
261
|
+
if k.response_code(site) == 200
|
262
|
+
doc=open_page(site)
|
263
|
+
#puts doc.inspect
|
264
|
+
meta=doc.css('meta')
|
265
|
+
#puts meta.inspect
|
266
|
+
meta.each do |tag|
|
267
|
+
if tag['content'].to_s =~ /wordpress/i
|
268
|
+
#puts tag.to_s
|
269
|
+
k=nil
|
270
|
+
return tag['content'].to_s.scan(/[\d+\.]+\d+/).first
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
k=nil
|
275
|
+
return nil
|
276
|
+
rescue => ee
|
277
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
278
|
+
return nil
|
279
|
+
end
|
280
|
+
|
281
|
+
# Identify wordpress version through the generator tag: <generator>https://wordpress.org/?v=4.9.8</generator>
|
282
|
+
def wp_ver_generator(url)
|
283
|
+
puts "#{__method__} check for #{url}" if @verbose
|
284
|
+
site = url_2_site(url)
|
285
|
+
gen_url_1 = site + "feed/"
|
286
|
+
gen_url_2 = site + "comments/feed"
|
287
|
+
k=Wmap::UrlChecker.new
|
288
|
+
if k.response_code(gen_url_1) == 200
|
289
|
+
doc=open_page(gen_url_1)
|
290
|
+
elsif k.response_code(gen_url_2) == 200
|
291
|
+
doc=open_page(gen_url_2)
|
292
|
+
else
|
293
|
+
k=nil
|
294
|
+
return nil
|
295
|
+
end
|
296
|
+
#puts doc.inspect
|
297
|
+
gens=doc.css('generator')
|
298
|
+
if gens.nil?
|
299
|
+
k=nil
|
300
|
+
return nil
|
301
|
+
end
|
302
|
+
gens.each do |gen|
|
303
|
+
if gen.text.to_s =~ /wordpress/i
|
304
|
+
k=nil
|
305
|
+
return gen.text.to_s.scan(/[\d+\.]+\d+/).first
|
306
|
+
end
|
307
|
+
end
|
308
|
+
k=doc=nil
|
309
|
+
return nil
|
310
|
+
rescue => ee
|
311
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
312
|
+
return nil
|
313
|
+
end
|
314
|
+
|
315
|
+
# Wordpress version detection via - readme.html
|
316
|
+
def wp_ver_readme(url)
|
317
|
+
site=url_2_site(url)
|
318
|
+
readme_url=site + "readme.html"
|
319
|
+
k=Wmap::UrlChecker.new
|
320
|
+
puts "Res code: #{k.response_code(readme_url)}" if @verbose
|
321
|
+
if k.response_code(readme_url) == 200
|
322
|
+
k=nil
|
323
|
+
doc=open_page(readme_url)
|
324
|
+
puts doc if @verbose
|
325
|
+
logo=doc.css('h1#logo')[0]
|
326
|
+
puts logo.inspect if @verbose
|
327
|
+
return logo.to_s.scan(/[\d+\.]+\d+/).first
|
328
|
+
end
|
329
|
+
k=nil
|
330
|
+
return nil
|
331
|
+
rescue => ee
|
332
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
333
|
+
return nil
|
334
|
+
end
|
335
|
+
|
336
|
+
# Wordpress version detection via - /wp-admin/load-styles.php
|
337
|
+
def wp_ver_load_styles(url)
|
338
|
+
site=url_2_site(url)
|
339
|
+
load_styles_url = site + "wp-admin/load-styles.php"
|
340
|
+
k=Wmap::UrlChecker.new
|
341
|
+
if k.response_code(load_styles_url) == 200
|
342
|
+
headers = k.response_headers(load_styles_url)
|
343
|
+
if headers.keys.include?("etag")
|
344
|
+
k=nil
|
345
|
+
return headers["etag"]
|
346
|
+
end
|
347
|
+
end
|
348
|
+
k=nil
|
349
|
+
return nil
|
350
|
+
rescue => ee
|
351
|
+
puts "Exception on method #{__method__} for url #{url}: #{ee}" if @verbose
|
352
|
+
return nil
|
353
|
+
end
|
354
|
+
|
355
|
+
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|