miteru 0.9.1 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/miteru.rb +1 -0
- data/lib/miteru/crawler.rb +6 -39
- data/lib/miteru/downloader.rb +42 -0
- data/lib/miteru/version.rb +1 -1
- data/lib/miteru/website.rb +3 -12
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8370829b3ad8da53b7c73070fd972269b09ea27c6c7dce1a3da5d855f81da27
|
4
|
+
data.tar.gz: c017feecfeaa27912de5dc898f23b430652270a16852510785109d60ed04891a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0796be92ea1586ec57f12a4157097d65ea0d49e151eb8876eda3b406ca05908b0bc01ff021f270ab5a1467bda415e281909ef47502f1fb490d5285c69dd1bd9b'
|
7
|
+
data.tar.gz: edbc8c6cce3d85cbfb8bdac217d7ca0ee9d3dfc353a3b7a3c1c7f7ad132b7d9ee80960bda1bba638b859f53d2805a7634901d47fd9a913630b16b0552d463078
|
data/README.md
CHANGED
@@ -37,7 +37,7 @@ Usage:
|
|
37
37
|
miteru execute
|
38
38
|
|
39
39
|
Options:
|
40
|
-
[--auto-download], [--no-auto-download] # Enable or disable auto-download of
|
40
|
+
[--auto-download], [--no-auto-download] # Enable or disable auto-download of compressed file(s)
|
41
41
|
[--directory-traveling], [--no-directory-traveling] # Enable or disable directory traveling
|
42
42
|
[--download-to=DOWNLOAD_TO] # Directory to download file(s)
|
43
43
|
# Default: /tmp
|
data/lib/miteru.rb
CHANGED
data/lib/miteru/crawler.rb
CHANGED
@@ -10,7 +10,7 @@ module Miteru
|
|
10
10
|
class Crawler
|
11
11
|
attr_reader :auto_download
|
12
12
|
attr_reader :directory_traveling
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :downloader
|
14
14
|
attr_reader :size
|
15
15
|
attr_reader :threads
|
16
16
|
attr_reader :verbose
|
@@ -22,7 +22,7 @@ module Miteru
|
|
22
22
|
def initialize(auto_download: false, directory_traveling: false, download_to: "/tmp", post_to_slack: false, size: 100, threads: 10, verbose: false)
|
23
23
|
@auto_download = auto_download
|
24
24
|
@directory_traveling = directory_traveling
|
25
|
-
@
|
25
|
+
@downloader = Downloader.new(download_to)
|
26
26
|
@post_to_slack = post_to_slack
|
27
27
|
@size = size
|
28
28
|
@threads = threads
|
@@ -59,6 +59,7 @@ module Miteru
|
|
59
59
|
rescue URI::InvalidURIError => _
|
60
60
|
return []
|
61
61
|
end
|
62
|
+
|
62
63
|
base = "#{uri.scheme}://#{uri.hostname}"
|
63
64
|
return [base] unless directory_traveling
|
64
65
|
|
@@ -82,23 +83,17 @@ module Miteru
|
|
82
83
|
def execute
|
83
84
|
puts "Loaded #{suspicious_urls.length} URLs to crawl." if verbose
|
84
85
|
|
85
|
-
websites = []
|
86
86
|
Parallel.each(suspicious_urls, in_threads: threads) do |url|
|
87
87
|
website = Website.new(url)
|
88
|
-
|
89
88
|
if website.has_kit?
|
90
89
|
message = "#{website.url}: it might contain phishing kit(s) (#{website.compressed_files.join(', ')})."
|
91
90
|
puts message.colorize(:light_red)
|
92
|
-
|
93
|
-
download_compressed_files(website.url, website.compressed_files
|
91
|
+
post_a_message_to_slack(message) if post_to_slack? && valid_slack_setting?
|
92
|
+
downloader.download_compressed_files(website.url, website.compressed_files) if auto_download?
|
94
93
|
else
|
95
94
|
puts "#{website.url}: it doesn't contain a phishing kit." if verbose
|
96
95
|
end
|
97
|
-
break
|
98
|
-
rescue StandardError => e
|
99
|
-
puts "Failed to load #{url} (#{e})" if verbose
|
100
96
|
end
|
101
|
-
websites
|
102
97
|
end
|
103
98
|
|
104
99
|
def self.execute(auto_download: false, directory_traveling: false, download_to: "/tmp", post_to_slack: false, size: 100, threads: 10, verbose: false)
|
@@ -113,24 +108,7 @@ module Miteru
|
|
113
108
|
).execute
|
114
109
|
end
|
115
110
|
|
116
|
-
def
|
117
|
-
compressed_files.each do |path|
|
118
|
-
target_url = "#{url}/#{path}"
|
119
|
-
begin
|
120
|
-
download_file_path = HTTPClient.download(target_url, base_dir)
|
121
|
-
if duplicated?(download_file_path, base_dir)
|
122
|
-
puts "Do not download #{target_url} because there is a same hash file in the directory (SHA256: #{sha256(download_file_path)})."
|
123
|
-
FileUtils.rm download_file_path
|
124
|
-
else
|
125
|
-
puts "Download #{target_url} as #{download_file_path}"
|
126
|
-
end
|
127
|
-
rescue Down::Error => e
|
128
|
-
puts "Failed to download: #{target_url} (#{e})"
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def post_to_slack(message)
|
111
|
+
def post_a_message_to_slack(message)
|
134
112
|
webhook_url = ENV["SLACK_WEBHOOK_URL"]
|
135
113
|
raise ArgumentError, "Please set the Slack webhook URL via SLACK_WEBHOOK_URL env" unless webhook_url
|
136
114
|
|
@@ -154,17 +132,6 @@ module Miteru
|
|
154
132
|
|
155
133
|
private
|
156
134
|
|
157
|
-
def sha256(path)
|
158
|
-
digest = Digest::SHA256.file(path)
|
159
|
-
digest.hexdigest
|
160
|
-
end
|
161
|
-
|
162
|
-
def duplicated?(file_path, base_dir)
|
163
|
-
base = sha256(file_path)
|
164
|
-
sha256s = Dir.glob("#{base_dir}/*.zip").map { |path| sha256(path) }
|
165
|
-
sha256s.select { |sha256| sha256 == base }.length > 1
|
166
|
-
end
|
167
|
-
|
168
135
|
def get(url)
|
169
136
|
res = HTTP.follow(max_hops: 3).get(url)
|
170
137
|
raise HTTPResponseError if res.code != 200
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Miteru
|
4
|
+
class Downloader
|
5
|
+
attr_reader :base_dir
|
6
|
+
|
7
|
+
def initialize(base_dir = "/tmp")
|
8
|
+
@base_dir = base_dir
|
9
|
+
raise ArgumentError, "#{base_dir} is not existing." unless Dir.exist?(base_dir)
|
10
|
+
end
|
11
|
+
|
12
|
+
def download_compressed_files(url, compressed_files)
|
13
|
+
compressed_files.each do |path|
|
14
|
+
target_url = "#{url}/#{path}"
|
15
|
+
begin
|
16
|
+
download_file_path = HTTPClient.download(target_url, base_dir)
|
17
|
+
if duplicated?(download_file_path, base_dir)
|
18
|
+
puts "Do not download #{target_url} because there is a same hash file in the directory (SHA256: #{sha256(download_file_path)})."
|
19
|
+
FileUtils.rm download_file_path
|
20
|
+
else
|
21
|
+
puts "Download #{target_url} as #{download_file_path}"
|
22
|
+
end
|
23
|
+
rescue Down::Error => e
|
24
|
+
puts "Failed to download: #{target_url} (#{e})"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def sha256(path)
|
32
|
+
digest = Digest::SHA256.file(path)
|
33
|
+
digest.hexdigest
|
34
|
+
end
|
35
|
+
|
36
|
+
def duplicated?(file_path, base_dir)
|
37
|
+
base = sha256(file_path)
|
38
|
+
sha256s = Dir.glob("#{base_dir}/*.zip").map { |path| sha256(path) }
|
39
|
+
sha256s.select { |sha256| sha256 == base }.length > 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/miteru/version.rb
CHANGED
data/lib/miteru/website.rb
CHANGED
@@ -7,7 +7,6 @@ module Miteru
|
|
7
7
|
attr_reader :url
|
8
8
|
def initialize(url)
|
9
9
|
@url = url
|
10
|
-
build
|
11
10
|
end
|
12
11
|
|
13
12
|
def title
|
@@ -36,17 +35,9 @@ module Miteru
|
|
36
35
|
end
|
37
36
|
|
38
37
|
def has_kit?
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def build
|
43
|
-
doc
|
44
|
-
end
|
45
|
-
|
46
|
-
def unbuild
|
47
|
-
@doc = nil
|
48
|
-
@response = nil
|
49
|
-
@compressed_files = nil
|
38
|
+
ok? && index? && compressed_files?
|
39
|
+
rescue StandardError => _
|
40
|
+
false
|
50
41
|
end
|
51
42
|
|
52
43
|
private
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miteru
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manabu Niseki
|
@@ -213,6 +213,7 @@ files:
|
|
213
213
|
- lib/miteru.rb
|
214
214
|
- lib/miteru/cli.rb
|
215
215
|
- lib/miteru/crawler.rb
|
216
|
+
- lib/miteru/downloader.rb
|
216
217
|
- lib/miteru/error.rb
|
217
218
|
- lib/miteru/http_client.rb
|
218
219
|
- lib/miteru/version.rb
|