rogue_one 0.1.4 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8a159994892e276c84f9854aea0d1bb1ed915da4d1441e362cd3df81967a029
4
- data.tar.gz: aeb889e5a15df10f85822fc78fb285a55f86268f7a6287e34f604698172ad0b0
3
+ metadata.gz: da6511f3f76c39a222c7b41458dd08675358923709006f56452e966369f166c9
4
+ data.tar.gz: 99ecea46070225babfb4c2b5f9d51da679a026afb22a443cadb6939e7507b697
5
5
  SHA512:
6
- metadata.gz: 2d49d2e63096010fae8beb77c5b0ff0eadcb83b350663a7f048a5f2402378b65ee99bd91ba83c6659a0cac87250d91c4a377d0c1a1f5e924e74b7aa4af670472
7
- data.tar.gz: 52f2ea2c904088b2f3c817653427e4d92ca04e1584a11754163a5ade8ee6a5075d4350e5fde3468cb87dc865caadcc6acc3de3edd98005d89dd5386214ed9505
6
+ metadata.gz: 7436a460f227a78b52d6bf57d85ac6e1f1b929f3b675aa02423f8cc5dc89a071cf01dc639e9ae20b688cb350bd99ec3cfef54332a07c56007b1364d82f96daab
7
+ data.tar.gz: 053b1f8f9a5c6eb5bf8b10654899bf7a41e106fa7fe412ce4e1fd27ad1917efd822a121464ba873ec698ea7d424d553cde8e85cd2f0ca53d26dd6cf11ac26b63
data/README.md CHANGED
@@ -1,9 +1,22 @@
1
- # Rogue one: a rogue DNS detector
1
+ # Rogue one
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rogue_one.svg)](https://badge.fury.io/rb/rogue_one)
4
4
  [![Build Status](https://travis-ci.org/ninoseki/rogue_one.svg?branch=master)](https://travis-ci.org/ninoseki/rogue_one)
5
+ [![CodeFactor](https://www.codefactor.io/repository/github/ninoseki/rogue_one/badge)](https://www.codefactor.io/repository/github/ninoseki/rogue_one)
5
6
  [![Coverage Status](https://coveralls.io/repos/github/ninoseki/rogue_one/badge.svg?branch=master)](https://coveralls.io/github/ninoseki/rogue_one?branch=master)
6
7
 
8
+ A tiny tool for detecting a rogue DNS server and extracting landing pages from the rogue DNS server.
9
+
10
+ ## How it works
11
+
12
+ ![image](./images/eyecatch.png)
13
+
14
+ IPv4 space is vast. But an attacker could secure a few numbers of IP addresses for landing pages.
15
+ It means you can (probably) find malicious landing pages by using the following methods.
16
+
17
+ - Resolving a bunch of domains by using a rogue DNS.
18
+ - Finding frequent IPv4s from the resolutions. They might be landing pages.
19
+
7
20
  ## Installation
8
21
 
9
22
  ```bash
@@ -18,6 +31,16 @@ Commands:
18
31
  rogue_one help [COMMAND] # Describe available commands or one specific command
19
32
  rogue_one report [DNS_SERVER] # Show a report of a given DNS server
20
33
 
34
+ $ rogue_one help report
35
+ Usage:
36
+ rogue_one report [DNS_SERVER]
37
+
38
+ Options:
39
+ [--custom-list=CUSTOM_LIST] # A path to a custom list of domains
40
+ [--verbose], [--no-verbose]
41
+
42
+ Show a report of a given DNS server
43
+
21
44
  $ rogue_one report 1.1.1.1
22
45
  {
23
46
  "verdict": "benign one",
@@ -35,12 +58,23 @@ $ rogue_one report 1.53.252.215
35
58
  "61.230.102.66"
36
59
  ]
37
60
  }
61
+
62
+ $ rogue_one report 171.244.3.111 --custom-list tmp/roaming.yml
63
+ {
64
+ "verdict": "rogue one",
65
+ "landing_pages": [
66
+ "154.223.53.53",
67
+ "58.82.243.9"
68
+ ]
69
+ }
70
+ # Note: a custom list should be an array of domains in YAML format.
38
71
  ```
39
72
 
40
- | Key | Desc. |
41
- |---------------|--------------------------------------------------|
42
- | verdict | A detection result (`rogue one` or `benign one`) |
43
- | landing_pages | An array of IP of landing pages |
73
+ | Key | Desc. |
74
+ |---------------|--------------------------------------------------------------------------|
75
+ | verdict | A detection result (`rogue one` or `benign one`) |
76
+ | landing_pages | An array of IP of landing pages |
77
+ | results | DNS resolution results (only available if --verbose option is specified) |
44
78
 
45
79
  ## Notes
46
80
 
Binary file
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "rogue_one/version"
4
4
 
5
+ require "rogue_one/domain_list"
6
+
5
7
  require "rogue_one/resolver"
6
8
  require "rogue_one/detector"
7
9
  require "rogue_one/ping"
@@ -6,11 +6,15 @@ require "json"
6
6
  module RogueOne
7
7
  class CLI < Thor
8
8
  desc "report [DNS_SERVER]", "Show a report of a given DNS server"
9
+ method_option :custom_list, type: :string, desc: "A path to a custom list of domains"
10
+ method_option :verbose, type: :boolean
9
11
  def report(dns_server)
10
12
  with_error_handling do
11
13
  Ping.pong? dns_server
12
14
 
13
- detector = Detector.new(target: dns_server)
15
+ custom_list = options["custom_list"]
16
+ verbose = options["verbose"]
17
+ detector = Detector.new(target: dns_server, custom_list: custom_list, verbose: verbose)
14
18
  puts JSON.pretty_generate(detector.report)
15
19
  end
16
20
  end
@@ -6,18 +6,24 @@ require "parallel"
6
6
  module RogueOne
7
7
  class Detector
8
8
  attr_reader :target
9
+ attr_reader :custom_list
10
+ attr_reader :verbose
9
11
 
10
12
  GOOGLE_PUBLIC_DNS = "8.8.8.8"
11
13
 
12
- def initialize(target:)
14
+ def initialize(target:, custom_list: nil, verbose: false)
13
15
  @target = target
16
+ @custom_list = custom_list
17
+ @verbose = verbose
18
+
14
19
  @memo = {}
20
+ @verbose_memo = nil
15
21
  end
16
22
 
17
23
  def report
18
24
  inspect
19
25
 
20
- { verdict: verdict, landing_pages: landing_pages }
26
+ { verdict: verdict, landing_pages: landing_pages, results: results }.compact
21
27
  end
22
28
 
23
29
  private
@@ -30,27 +36,49 @@ module RogueOne
30
36
  !landing_pages.empty?
31
37
  end
32
38
 
39
+ def threshold
40
+ @threshold ||= (domains.length.to_f / 10.0).ceil
41
+ end
42
+
33
43
  def landing_pages
34
44
  @memo.map do |ip, count|
35
- count > 10 ? ip : nil
45
+ count > threshold ? ip : nil
36
46
  end.compact.sort
37
47
  end
38
48
 
49
+ def results
50
+ @verbose_memo
51
+ end
52
+
39
53
  def inspect
40
54
  return unless @memo.empty?
41
55
 
42
- results = Parallel.map(top_100_domains) do |domain|
56
+ results = Parallel.map(domains) do |domain|
43
57
  normal_result = normal_resolver.dig(domain, "A")
44
58
  target_result = target_resolver.dig(domain, "A")
45
59
 
46
- target_result if target_result && normal_result != target_result
47
- end.compact
60
+ [domain, target_result] if target_result && normal_result != target_result
61
+ end.compact.to_h
48
62
 
49
- @memo = results.group_by(&:itself).map { |k, v| [k, v.length] }.to_h
63
+ @memo = results.values.group_by(&:itself).map { |k, v| [k, v.length] }.to_h
64
+ @verbose_memo = results if verbose
65
+ end
66
+
67
+ def domains
68
+ @domains ||= custom_domains || top_100_domains
69
+ end
70
+
71
+ def custom_domains
72
+ read_domains custom_list
50
73
  end
51
74
 
52
75
  def top_100_domains
53
- @top_100_domains ||= YAML.safe_load(File.read(File.expand_path("./data/top_100.yml", __dir__)))
76
+ read_domains File.expand_path("./data/top_100.yml", __dir__)
77
+ end
78
+
79
+ def read_domains(path)
80
+ list = DomainList.new(path)
81
+ list.valid? ? list.domains : nil
54
82
  end
55
83
 
56
84
  def normal_resolver
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module RogueOne
6
+ class DomainList
7
+ attr_reader :path
8
+
9
+ def initialize(path)
10
+ @path = path.to_s
11
+ end
12
+
13
+ def valid?
14
+ exists? && valid_format?
15
+ end
16
+
17
+ def domains
18
+ @domains ||= exists? ? YAML.safe_load(File.read(path)) : nil
19
+ end
20
+
21
+ private
22
+
23
+ def exists?
24
+ File.exist?(path)
25
+ end
26
+
27
+ def valid_format?
28
+ domains.is_a? Array
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RogueOne
4
- VERSION = "0.1.4"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -26,9 +26,9 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_development_dependency "bundler", "~> 2.0"
28
28
  spec.add_development_dependency "coveralls", "~> 0.8"
29
- spec.add_development_dependency "rake", "~> 12.3"
30
- spec.add_development_dependency "rspec", "~> 3.8"
29
+ spec.add_development_dependency "rake", "~> 13.0"
30
+ spec.add_development_dependency "rspec", "~> 3.9"
31
31
 
32
- spec.add_dependency "parallel", "~> 1.17"
33
- spec.add_dependency "thor", "~> 0.19"
32
+ spec.add_dependency "parallel", "~> 1.18"
33
+ spec.add_dependency "thor", "~> 0.20"
34
34
  end
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.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manabu Niseki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-09 00:00:00.000000000 Z
11
+ date: 2019-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,56 +44,56 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '12.3'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '12.3'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.8'
61
+ version: '3.9'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.8'
68
+ version: '3.9'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: parallel
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.17'
75
+ version: '1.18'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.17'
82
+ version: '1.18'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: thor
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.19'
89
+ version: '0.20'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.19'
96
+ version: '0.20'
97
97
  description: 'Rogue one: a rogue DNS detector'
98
98
  email:
99
99
  - manabu.niseki@gmail.com
@@ -112,10 +112,12 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - exe/rogue_one
115
+ - images/eyecatch.png
115
116
  - lib/rogue_one.rb
116
117
  - lib/rogue_one/cli.rb
117
118
  - lib/rogue_one/data/top_100.yml
118
119
  - lib/rogue_one/detector.rb
120
+ - lib/rogue_one/domain_list.rb
119
121
  - lib/rogue_one/ping.rb
120
122
  - lib/rogue_one/resolver.rb
121
123
  - lib/rogue_one/version.rb
@@ -139,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
141
  - !ruby/object:Gem::Version
140
142
  version: '0'
141
143
  requirements: []
142
- rubygems_version: 3.0.2
144
+ rubygems_version: 3.0.3
143
145
  signing_key:
144
146
  specification_version: 4
145
147
  summary: 'Rogue one: a rogue DNS detector'