site-inspector 1.0.2 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +8 -0
- data/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +139 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +7 -0
- data/Guardfile +10 -0
- data/README.md +189 -0
- data/Rakefile +10 -0
- data/bin/site-inspector +50 -22
- data/lib/cliver/dependency_ext.rb +24 -0
- data/lib/site-inspector.rb +62 -615
- data/lib/site-inspector/cache.rb +10 -51
- data/lib/site-inspector/checks/accessibility.rb +135 -0
- data/lib/site-inspector/checks/check.rb +54 -0
- data/lib/site-inspector/checks/content.rb +85 -0
- data/lib/site-inspector/checks/cookies.rb +45 -0
- data/lib/site-inspector/checks/dns.rb +138 -0
- data/lib/site-inspector/checks/headers.rb +68 -0
- data/lib/site-inspector/checks/hsts.rb +81 -0
- data/lib/site-inspector/checks/https.rb +40 -0
- data/lib/site-inspector/checks/sniffer.rb +67 -0
- data/lib/site-inspector/checks/wappalyzer.rb +62 -0
- data/lib/site-inspector/checks/whois.rb +36 -0
- data/lib/site-inspector/disk_cache.rb +42 -0
- data/lib/site-inspector/domain.rb +271 -0
- data/lib/site-inspector/endpoint.rb +217 -0
- data/lib/site-inspector/rails_cache.rb +13 -0
- data/lib/site-inspector/version.rb +5 -0
- data/package-lock.json +505 -0
- data/package.json +23 -0
- data/script/bootstrap +2 -0
- data/script/cibuild +11 -0
- data/script/console +3 -0
- data/script/pa11y-version +10 -0
- data/script/release +38 -0
- data/site-inspector.gemspec +42 -0
- data/spec/checks/site_inspector_endpoint_accessibility_spec.rb +84 -0
- data/spec/checks/site_inspector_endpoint_check_spec.rb +42 -0
- data/spec/checks/site_inspector_endpoint_content_spec.rb +117 -0
- data/spec/checks/site_inspector_endpoint_cookies_spec.rb +73 -0
- data/spec/checks/site_inspector_endpoint_dns_spec.rb +184 -0
- data/spec/checks/site_inspector_endpoint_headers_spec.rb +65 -0
- data/spec/checks/site_inspector_endpoint_hsts_spec.rb +92 -0
- data/spec/checks/site_inspector_endpoint_https_spec.rb +49 -0
- data/spec/checks/site_inspector_endpoint_sniffer_spec.rb +150 -0
- data/spec/checks/site_inspector_endpoint_wappalyzer_spec.rb +34 -0
- data/spec/checks/site_inspector_endpoint_whois_spec.rb +26 -0
- data/spec/fixtures/wappalyzer.json +125 -0
- data/spec/site_inspector_cache_spec.rb +15 -0
- data/spec/site_inspector_disk_cache_spec.rb +39 -0
- data/spec/site_inspector_domain_spec.rb +271 -0
- data/spec/site_inspector_endpoint_spec.rb +252 -0
- data/spec/site_inspector_spec.rb +48 -0
- data/spec/spec_helper.rb +19 -0
- metadata +204 -63
- data/lib/site-inspector/compliance.rb +0 -19
- data/lib/site-inspector/dns.rb +0 -92
- data/lib/site-inspector/headers.rb +0 -59
- data/lib/site-inspector/sniffer.rb +0 -26
@@ -1,19 +0,0 @@
|
|
1
|
-
class SiteInspector
|
2
|
-
|
3
|
-
def path_exists?(path)
|
4
|
-
url = URI.join uri, path
|
5
|
-
Typhoeus::Request.get(url, followlocation: true, timeout: 10).success?
|
6
|
-
end
|
7
|
-
|
8
|
-
def slash_data?
|
9
|
-
@slash_data ||= path_exists?("/data")
|
10
|
-
end
|
11
|
-
|
12
|
-
def slash_developer?
|
13
|
-
@slash_developer ||= (path_exists?("/developer") || path_exists?("/developers"))
|
14
|
-
end
|
15
|
-
|
16
|
-
def data_dot_json?
|
17
|
-
@data_dot_json ||= path_exists?("/data.json")
|
18
|
-
end
|
19
|
-
end
|
data/lib/site-inspector/dns.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
class SiteInspector
|
2
|
-
|
3
|
-
def resolver
|
4
|
-
require "dnsruby"
|
5
|
-
@resolver ||= begin
|
6
|
-
resolver = Dnsruby::Resolver.new
|
7
|
-
resolver.config.nameserver = ["8.8.8.8", "8.8.4.4"]
|
8
|
-
resolver
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def query(type="ANY")
|
13
|
-
resolver.query(domain.to_s, type).answer
|
14
|
-
rescue
|
15
|
-
[]
|
16
|
-
end
|
17
|
-
|
18
|
-
def dns
|
19
|
-
@dns ||= query
|
20
|
-
end
|
21
|
-
|
22
|
-
def has_record?(type)
|
23
|
-
dns.any? { |record| record.type == type } || query(type).count != 0
|
24
|
-
end
|
25
|
-
|
26
|
-
def dnssec?
|
27
|
-
@dnssec ||= has_record? "DNSKEY"
|
28
|
-
end
|
29
|
-
|
30
|
-
def ipv6?
|
31
|
-
@ipv6 ||= has_record? "AAAA"
|
32
|
-
end
|
33
|
-
|
34
|
-
def detect_by_hostname(type)
|
35
|
-
|
36
|
-
haystack = SiteInspector.load_data(type)
|
37
|
-
needle = haystack.find { |name, domain|
|
38
|
-
cnames.any? { |cname|
|
39
|
-
domain == cname.tld || domain == "#{cname.sld}.#{cname.tld}"
|
40
|
-
}
|
41
|
-
}
|
42
|
-
|
43
|
-
return needle[0] if needle
|
44
|
-
return false unless hostname
|
45
|
-
|
46
|
-
needle = haystack.find { |name, domain|
|
47
|
-
domain == hostname.tld || domain == "#{hostname.sld}.#{hostname.tld}"
|
48
|
-
}
|
49
|
-
|
50
|
-
needle ? needle[0] : false
|
51
|
-
end
|
52
|
-
|
53
|
-
def cdn
|
54
|
-
detect_by_hostname "cdn"
|
55
|
-
end
|
56
|
-
|
57
|
-
def cdn?
|
58
|
-
!!cdn
|
59
|
-
end
|
60
|
-
|
61
|
-
def cloud_provider
|
62
|
-
detect_by_hostname "cloud"
|
63
|
-
end
|
64
|
-
|
65
|
-
def cloud?
|
66
|
-
!!cloud_provider
|
67
|
-
end
|
68
|
-
|
69
|
-
def google_apps?
|
70
|
-
@google ||= dns.any? do |record|
|
71
|
-
record.type == "MX" && record.exchange =~ /google(mail)?\.com\.?$/
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def ip
|
76
|
-
require 'resolv'
|
77
|
-
@ip ||= Resolv.getaddress domain.to_s
|
78
|
-
rescue Resolv::ResolvError
|
79
|
-
nil
|
80
|
-
end
|
81
|
-
|
82
|
-
def hostname
|
83
|
-
require 'resolv'
|
84
|
-
@hostname ||= PublicSuffix.parse(Resolv.getname(ip))
|
85
|
-
rescue Exception => e
|
86
|
-
nil
|
87
|
-
end
|
88
|
-
|
89
|
-
def cnames
|
90
|
-
@cnames ||= dns.select {|record| record.type == "CNAME" }.map { |record| PublicSuffix.parse(record.cname.to_s) }
|
91
|
-
end
|
92
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
class SiteInspector
|
2
|
-
|
3
|
-
# cookies can have multiple set-cookie headers, so this detects
|
4
|
-
# whether cookies are set, but not all their values.
|
5
|
-
def has_cookies?
|
6
|
-
!!headers["set-cookie"]
|
7
|
-
end
|
8
|
-
|
9
|
-
def strict_transport_security?
|
10
|
-
!!strict_transport_security
|
11
|
-
end
|
12
|
-
|
13
|
-
def content_security_policy?
|
14
|
-
!!content_security_policy
|
15
|
-
end
|
16
|
-
|
17
|
-
def click_jacking_protection?
|
18
|
-
!!click_jacking_protection
|
19
|
-
end
|
20
|
-
|
21
|
-
# return the found header value
|
22
|
-
|
23
|
-
def strict_transport_security
|
24
|
-
headers["strict-transport-security"]
|
25
|
-
end
|
26
|
-
|
27
|
-
def content_security_policy
|
28
|
-
headers["content-security-policy"]
|
29
|
-
end
|
30
|
-
|
31
|
-
def click_jacking_protection
|
32
|
-
headers["x-frame-options"]
|
33
|
-
end
|
34
|
-
|
35
|
-
def server
|
36
|
-
headers["server"]
|
37
|
-
end
|
38
|
-
|
39
|
-
def xss_protection
|
40
|
-
headers["x-xss-protection"]
|
41
|
-
end
|
42
|
-
|
43
|
-
# more specific checks than presence of headers
|
44
|
-
def xss_protection?
|
45
|
-
xss_protection == "1; mode=block"
|
46
|
-
end
|
47
|
-
|
48
|
-
def secure_cookies?
|
49
|
-
return false if !has_cookies?
|
50
|
-
cookie = headers["set-cookie"]
|
51
|
-
cookie = cookie.first if cookie.is_a?(Array)
|
52
|
-
!!(cookie =~ /(; secure.*; httponly|; httponly.*; secure)/i)
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns an array of hashes of downcased key/value header pairs (or an empty hash)
|
56
|
-
def headers
|
57
|
-
@headers ||= response ? Hash[response.headers.map{ |k,v| [k.downcase,v] }] : {}
|
58
|
-
end
|
59
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class SiteInspector
|
2
|
-
def sniff(type)
|
3
|
-
require 'sniffles'
|
4
|
-
results = Sniffles.sniff(body, type).select { |name, meta| meta[:found] == true }
|
5
|
-
results.each { |name, result| result.delete :found} if results
|
6
|
-
results
|
7
|
-
rescue
|
8
|
-
nil
|
9
|
-
end
|
10
|
-
|
11
|
-
def cms
|
12
|
-
sniff :cms
|
13
|
-
end
|
14
|
-
|
15
|
-
def analytics
|
16
|
-
sniff :analytics
|
17
|
-
end
|
18
|
-
|
19
|
-
def javascript
|
20
|
-
sniff :javascript
|
21
|
-
end
|
22
|
-
|
23
|
-
def advertising
|
24
|
-
sniff :advertising
|
25
|
-
end
|
26
|
-
end
|