rogue_one 0.4.1 → 0.4.2

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: a66b70adea810f6e952e08294a0323dc2be06c23d7ccbc28739045829696aae5
4
- data.tar.gz: 5d41ff1fa13254071aecef1cbf70168d818a963207922be4d44f134d9bb42f0d
3
+ metadata.gz: 36b1d9ea6171500c42fd1930ba0807e74d8df4908fdec5eb47f1b88b0262caf6
4
+ data.tar.gz: 3836ad7bc6a13b68e1fa07d5d584ccbe0da64c8a4c1ee31e16d8f6e5037ada7f
5
5
  SHA512:
6
- metadata.gz: c08f2049c42ac79a9a0256ae2f99761748660fa3bd1981f680196540e4525db9b4e8dbba54264d35cc2b7b5773b96441886a0a7acb4900e1626cd42c34089304
7
- data.tar.gz: a4cffb3b9d5c92f90ac267201417c459b334d38aa82a0631a43c7db15552bed00d11cc9f37291904f48bfad08c33f4bc7d051bf3946acf4c35fcdc9a7e927567
6
+ metadata.gz: 8659b118ceaf22a6ec4756d4f883f8bda633ddf1230aab126c2666ad967df887dd7b1fed576b2f3608ed0adefea695067030ed079b3a915af8c06b1398bd2bd0
7
+ data.tar.gz: 3c6debab123e645b9765627dda48bc5c2674ee9101f53da0c8bb967a72d54cea411213cc6b6d2354263f1034b73d75282058872779f75a1ac07ec3e5bb77a63d
data/README.md CHANGED
@@ -39,16 +39,16 @@ Usage:
39
39
  rogue_one report [DNS_SERVER]
40
40
 
41
41
  Options:
42
+ [--custom-list=CUSTOM_LIST] # A path to a custom list of domains
42
43
  [--default-list=DEFAULT_LIST] # A default list of top 100 domains (Alexa or Fortune)
43
44
  # Default: alexa
44
- [--custom-list=CUSTOM_LIST] # A path to a custom list of domains
45
+ [--record-type=RECORD_TYPE] # A type of the DNS resource to check
46
+ # Default: A
45
47
  [--threshold=N] # Threshold value for determining malicious or not
46
48
  [--verbose], [--no-verbose]
47
49
 
48
50
  Show a report of a given DNS server
49
51
 
50
- Show a report of a given DNS server
51
-
52
52
  $ rogue_one report 1.1.1.1
53
53
  {
54
54
  "verdict": "benign one",
@@ -4,7 +4,6 @@ require "rogue_one/version"
4
4
 
5
5
  require "rogue_one/domain_list"
6
6
 
7
- require "rogue_one/resolver"
8
7
  require "rogue_one/detector"
9
8
  require "rogue_one/ping"
10
9
  require "rogue_one/cli"
@@ -5,20 +5,36 @@ require "json"
5
5
 
6
6
  module RogueOne
7
7
  class CLI < Thor
8
+ class << self
9
+ def exit_on_failure?
10
+ true
11
+ end
12
+ end
13
+
8
14
  desc "report [DNS_SERVER]", "Show a report of a given DNS server"
9
- method_option :default_list, type: :string, default: "alexa", desc: "A default list of top 100 domains (Alexa or Fortune)"
10
15
  method_option :custom_list, type: :string, desc: "A path to a custom list of domains"
16
+ method_option :default_list, type: :string, default: "alexa", desc: "A default list of top 100 domains (Alexa or Fortune)"
17
+ method_option :record_type, type: :string, default: "A", desc: "A type of the DNS resource to check"
11
18
  method_option :threshold, type: :numeric, desc: "Threshold value for determining malicious or not"
12
19
  method_option :verbose, type: :boolean
13
20
  def report(dns_server)
14
21
  with_error_handling do
15
22
  Ping.pong? dns_server
16
23
 
17
- default_list = options["default_list"].downcase
18
24
  custom_list = options["custom_list"]
25
+ default_list = options["default_list"].downcase
26
+ record_type = options["record_type"].upcase
19
27
  threshold = options["threshold"]
20
28
  verbose = options["verbose"]
21
- detector = Detector.new(target: dns_server, default_list: default_list, custom_list: custom_list, threshold: threshold, verbose: verbose)
29
+
30
+ detector = Detector.new(
31
+ custom_list: custom_list,
32
+ default_list: default_list,
33
+ record_type: record_type,
34
+ target: dns_server,
35
+ threshold: threshold,
36
+ verbose: verbose,
37
+ )
22
38
  puts JSON.pretty_generate(detector.report)
23
39
  end
24
40
  end
@@ -11,18 +11,26 @@ require "etc"
11
11
 
12
12
  module RogueOne
13
13
  class Detector
14
- attr_reader :target
15
- attr_reader :default_list
16
14
  attr_reader :custom_list
17
- attr_reader :verbose
15
+ attr_reader :default_list
18
16
  attr_reader :max_concurrency
17
+ attr_reader :record_type
18
+ attr_reader :target
19
+ attr_reader :verbose
19
20
 
20
21
  GOOGLE_PUBLIC_DNS = "8.8.8.8"
21
22
 
22
- def initialize(target:, default_list: "alexa", custom_list: nil, threshold: nil, verbose: false)
23
+ def initialize(target:,
24
+ custom_list: nil,
25
+ default_list: "alexa",
26
+ record_type: "A",
27
+ threshold: nil,
28
+ verbose: false)
23
29
  @target = target
24
- @default_list = default_list
30
+
25
31
  @custom_list = custom_list
32
+ @default_list = default_list
33
+ @record_type = record_type.upcase.to_sym
26
34
  @threshold = threshold
27
35
  @verbose = verbose
28
36
 
@@ -59,7 +67,10 @@ module RogueOne
59
67
  def meta
60
68
  return nil unless verbose
61
69
 
62
- { threshold: threshold }
70
+ {
71
+ record_type: record_type,
72
+ threshold: threshold,
73
+ }
63
74
  end
64
75
 
65
76
  def landing_pages
@@ -89,13 +100,13 @@ module RogueOne
89
100
  return unless @memo.empty?
90
101
 
91
102
  # read domains outside of the async blocks
92
- domains
103
+ load_domains
93
104
 
94
- normal = bulk_resolve(normal_resolver, domains)
105
+ normal_resolutions = bulk_resolve(normal_resolver, domains)
95
106
  resolutions = bulk_resolve(target_resolver, domains)
96
107
 
97
108
  results = resolutions.map do |domain, addresses|
98
- normal_addresses = normal.dig(domain) || []
109
+ normal_addresses = normal_resolutions.dig(domain) || []
99
110
  address = (addresses || []).first
100
111
  [domain, address] if address && !normal_addresses.include?(address)
101
112
  end.compact.to_h
@@ -104,6 +115,10 @@ module RogueOne
104
115
  @verbose_memo = results if verbose
105
116
  end
106
117
 
118
+ def load_domains
119
+ domains
120
+ end
121
+
107
122
  def domains
108
123
  @domains ||= custom_list ? custom_domains : top_100_domains
109
124
  end
@@ -131,6 +146,7 @@ module RogueOne
131
146
 
132
147
  def bulk_resolve(resolver, domains)
133
148
  results = []
149
+
134
150
  Async do
135
151
  barrier = Async::Barrier.new
136
152
  semaphore = Async::Semaphore.new(max_concurrency, parent: barrier)
@@ -139,7 +155,7 @@ module RogueOne
139
155
  semaphore.async do
140
156
  addresses = []
141
157
  begin
142
- addresses = resolver.addresses_for(domain, Resolv::DNS::Resource::IN::A, { retries: 1 }).map(&:to_s)
158
+ addresses = resolver.addresses_for(domain, dns_resource_by_record_type, { retries: 1 }).map(&:to_s)
143
159
  rescue Async::DNS::ResolutionFailure
144
160
  # do nothing
145
161
  end
@@ -157,5 +173,16 @@ module RogueOne
157
173
  def target_resolver
158
174
  Async::DNS::Resolver.new([[:udp, target, 53], [:tcp, target, 53]])
159
175
  end
176
+
177
+ def dns_resource_by_record_type
178
+ @dns_resource_by_record_type ||= dns_resources.dig(record_type)
179
+ end
180
+
181
+ def dns_resources
182
+ {
183
+ A: Resolv::DNS::Resource::IN::A,
184
+ AAAA: Resolv::DNS::Resource::IN::AAAA,
185
+ }
186
+ end
160
187
  end
161
188
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RogueOne
4
- VERSION = "0.4.1"
4
+ VERSION = "0.4.2"
5
5
  end
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rogue_one
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-29 00:00:00.000000000 Z
11
+ date: 2020-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,8 +120,8 @@ files:
120
120
  - lib/rogue_one/detector.rb
121
121
  - lib/rogue_one/domain_list.rb
122
122
  - lib/rogue_one/ping.rb
123
- - lib/rogue_one/resolver.rb
124
123
  - lib/rogue_one/version.rb
124
+ - renovate.json
125
125
  - rogue_one.gemspec
126
126
  homepage: https://github.com/ninoseki/rogue_one
127
127
  licenses:
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "resolv"
4
-
5
- module RogueOne
6
- class Resolver
7
- attr_reader :nameserver
8
-
9
- def initialize(nameserver:)
10
- @nameserver = nameserver
11
- end
12
-
13
- def get_resource(domain, type)
14
- _resolver.getresource(domain, resource_by_type(type)).address.to_s
15
- rescue Resolv::ResolvError => _e
16
- nil
17
- end
18
-
19
- def get_resources(domain, type)
20
- _resolver.getresources(domain, resource_by_type(type)).map { |r| r.address.to_s }
21
- rescue Resolv::ResolvError => _e
22
- nil
23
- end
24
-
25
- private
26
-
27
- def _resolver
28
- @_resolver ||= Resolv::DNS.new(nameserver: [nameserver])
29
- @_resolver.timeouts = 5
30
- @_resolver
31
- end
32
-
33
- def resource_by_type(type)
34
- resources.dig(type.upcase.to_sym)
35
- end
36
-
37
- def resources
38
- {
39
- ANY: Resolv::DNS::Resource::IN::ANY,
40
- NS: Resolv::DNS::Resource::IN::NS,
41
- CNAME: Resolv::DNS::Resource::IN::CNAME,
42
- SOA: Resolv::DNS::Resource::IN::SOA,
43
- HINFO: Resolv::DNS::Resource::IN::HINFO,
44
- MINFO: Resolv::DNS::Resource::IN::MINFO,
45
- MX: Resolv::DNS::Resource::IN::MX,
46
- TXT: Resolv::DNS::Resource::IN::TXT,
47
- A: Resolv::DNS::Resource::IN::A,
48
- WKS: Resolv::DNS::Resource::IN::WKS,
49
- PTR: Resolv::DNS::Resource::IN::PTR,
50
- AAAA: Resolv::DNS::Resource::IN::AAAA,
51
- SRV: Resolv::DNS::Resource::IN::SRV,
52
- }
53
- end
54
- end
55
- end