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 +4 -4
- data/README.md +39 -5
- data/images/eyecatch.png +0 -0
- data/lib/rogue_one.rb +2 -0
- data/lib/rogue_one/cli.rb +5 -1
- data/lib/rogue_one/detector.rb +36 -8
- data/lib/rogue_one/domain_list.rb +31 -0
- data/lib/rogue_one/version.rb +1 -1
- data/rogue_one.gemspec +4 -4
- metadata +13 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da6511f3f76c39a222c7b41458dd08675358923709006f56452e966369f166c9
|
4
|
+
data.tar.gz: 99ecea46070225babfb4c2b5f9d51da679a026afb22a443cadb6939e7507b697
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7436a460f227a78b52d6bf57d85ac6e1f1b929f3b675aa02423f8cc5dc89a071cf01dc639e9ae20b688cb350bd99ec3cfef54332a07c56007b1364d82f96daab
|
7
|
+
data.tar.gz: 053b1f8f9a5c6eb5bf8b10654899bf7a41e106fa7fe412ce4e1fd27ad1917efd822a121464ba873ec698ea7d424d553cde8e85cd2f0ca53d26dd6cf11ac26b63
|
data/README.md
CHANGED
@@ -1,9 +1,22 @@
|
|
1
|
-
# Rogue one
|
1
|
+
# Rogue one
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/rogue_one)
|
4
4
|
[](https://travis-ci.org/ninoseki/rogue_one)
|
5
|
+
[](https://www.codefactor.io/repository/github/ninoseki/rogue_one)
|
5
6
|
[](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
|
+

|
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
|
|
data/images/eyecatch.png
ADDED
Binary file
|
data/lib/rogue_one.rb
CHANGED
data/lib/rogue_one/cli.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/rogue_one/detector.rb
CHANGED
@@ -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 >
|
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(
|
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
|
-
|
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
|
data/lib/rogue_one/version.rb
CHANGED
data/rogue_one.gemspec
CHANGED
@@ -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", "~>
|
30
|
-
spec.add_development_dependency "rspec", "~> 3.
|
29
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
30
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
31
31
|
|
32
|
-
spec.add_dependency "parallel", "~> 1.
|
33
|
-
spec.add_dependency "thor", "~> 0.
|
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.
|
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-
|
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: '
|
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: '
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
144
|
+
rubygems_version: 3.0.3
|
143
145
|
signing_key:
|
144
146
|
specification_version: 4
|
145
147
|
summary: 'Rogue one: a rogue DNS detector'
|