miteru 0.9.6 → 0.10.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 +2 -2
- data/lib/miteru/downloader.rb +18 -6
- data/lib/miteru/feeds.rb +1 -5
- data/lib/miteru/feeds/urlscan.rb +16 -2
- data/lib/miteru/http_client.rb +1 -12
- data/lib/miteru/version.rb +1 -1
- metadata +2 -4
- data/lib/miteru/feeds/openphish.rb +0 -19
- data/lib/miteru/feeds/phishtank.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3388ff4a8c19447535952bc611725e1faa31b04241b0432cb7516ed03222f1f
|
4
|
+
data.tar.gz: 28440e7ff65d33a303e5446b4c9eb454ee0831b6b2acc4bef938b855a9b08d23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc88d56a0b8d3d22ea703e8a4d60671804cda0d2ca8323733580260815aad0a0046757c31a35872140c1bee624b2ff17894eecd37c25390f3b85634bd1c2d0c3
|
7
|
+
data.tar.gz: ee0de0987aea58886a61d2c95e4df80a81d4cf8941342b1c0e48ef8528f21db411c59e047a423f6dbecfdeee79d98b4ed5a6587c6a741e8147d6b440c2b44752
|
data/README.md
CHANGED
@@ -11,8 +11,8 @@ Miteru is an experimental phishing kit detection tool.
|
|
11
11
|
|
12
12
|
- It collects phishing suspicious URLs from the following feeds:
|
13
13
|
- [urlscan.io certstream-suspicious feed](https://urlscan.io/search/#certstream-suspicious)
|
14
|
-
- [OpenPhish
|
15
|
-
- [PhishTank feed](
|
14
|
+
- [OpenPhish feed via urlscan.io](https://urlscan.io/search/#OpenPhish)
|
15
|
+
- [PhishTank feed via urlscan.io](https://urlscan.io/search/#PhishTank)
|
16
16
|
- It checks a suspicious URL whether it enables directory listing and contains a phishing kit (compressed file) or not.
|
17
17
|
- Note: compressed file = `*.zip`, `*.rar`, `*.7z`, `*.tar` and `*.gz`.
|
18
18
|
|
data/lib/miteru/downloader.rb
CHANGED
@@ -15,13 +15,15 @@ module Miteru
|
|
15
15
|
def download_compressed_files(url, compressed_files)
|
16
16
|
compressed_files.each do |path|
|
17
17
|
target_url = "#{url}/#{path}"
|
18
|
+
filename = filename_to_save(target_url)
|
19
|
+
destination = filepath_to_download(filename)
|
18
20
|
begin
|
19
|
-
|
20
|
-
if duplicated?(
|
21
|
-
puts "Do not download #{target_url} because there is a same hash file in the directory (SHA256: #{sha256(
|
22
|
-
FileUtils.rm
|
21
|
+
download_filepath = HTTPClient.download(target_url, destination)
|
22
|
+
if duplicated?(download_filepath)
|
23
|
+
puts "Do not download #{target_url} because there is a same hash file in the directory (SHA256: #{sha256(download_filepath)})."
|
24
|
+
FileUtils.rm download_filepath
|
23
25
|
else
|
24
|
-
puts "Download #{target_url} as #{
|
26
|
+
puts "Download #{target_url} as #{download_filepath}"
|
25
27
|
end
|
26
28
|
rescue Down::Error => e
|
27
29
|
puts "Failed to download: #{target_url} (#{e})"
|
@@ -31,12 +33,22 @@ module Miteru
|
|
31
33
|
|
32
34
|
private
|
33
35
|
|
36
|
+
def filename_to_save(url)
|
37
|
+
filename = url.split("/").last
|
38
|
+
extname = File.extname(filename)
|
39
|
+
"#{SecureRandom.alphanumeric}#{extname}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def filepath_to_download(filename)
|
43
|
+
"#{base_dir}/#{filename}"
|
44
|
+
end
|
45
|
+
|
34
46
|
def sha256(path)
|
35
47
|
digest = Digest::SHA256.file(path)
|
36
48
|
digest.hexdigest
|
37
49
|
end
|
38
50
|
|
39
|
-
def duplicated?(file_path
|
51
|
+
def duplicated?(file_path)
|
40
52
|
base = sha256(file_path)
|
41
53
|
sha256s = Dir.glob("#{base_dir}/*.{zip,rar,7z,tar,gz}").map { |path| sha256(path) }
|
42
54
|
sha256s.select { |sha256| sha256 == base }.length > 1
|
data/lib/miteru/feeds.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "./feeds/feed"
|
4
|
-
require_relative "./feeds/openphish"
|
5
|
-
require_relative "./feeds/phishtank"
|
6
4
|
require_relative "./feeds/urlscan"
|
7
5
|
|
8
6
|
module Miteru
|
@@ -11,15 +9,13 @@ module Miteru
|
|
11
9
|
attr_reader :directory_traveling
|
12
10
|
|
13
11
|
def initialize(urlscan_size = 100, directory_traveling: false)
|
14
|
-
@openphish = OpenPhish.new
|
15
|
-
@phishtank = PhishTank.new
|
16
12
|
@urlscan = UrlScan.new(urlscan_size)
|
17
13
|
@directory_traveling = directory_traveling
|
18
14
|
end
|
19
15
|
|
20
16
|
def suspicious_urls
|
21
17
|
@suspicious_urls ||= [].tap do |arr|
|
22
|
-
urls =
|
18
|
+
urls = urlscan.urls.select { |url| url.start_with?("http://", "https://") }
|
23
19
|
urls.map { |url| breakdown(url) }.flatten.uniq.sort.each { |url| arr << url }
|
24
20
|
end
|
25
21
|
end
|
data/lib/miteru/feeds/urlscan.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "json"
|
4
|
+
require "uri"
|
4
5
|
|
5
6
|
module Miteru
|
6
7
|
class Feeds
|
7
8
|
class UrlScan < Feed
|
8
|
-
|
9
|
+
HOST = "urlscan.io"
|
10
|
+
VERSION = 1
|
11
|
+
URL = "https://#{HOST}/api/v#{VERSION}"
|
9
12
|
|
10
13
|
attr_reader :size
|
11
14
|
def initialize(size = 100)
|
@@ -14,13 +17,24 @@ module Miteru
|
|
14
17
|
end
|
15
18
|
|
16
19
|
def urls
|
17
|
-
url = "
|
20
|
+
url = url_for("/search/")
|
21
|
+
url.query = URI.encode_www_form(
|
22
|
+
q: "PhishTank OR OpenPhish OR CertStream-Suspicious",
|
23
|
+
size: size
|
24
|
+
)
|
25
|
+
|
18
26
|
res = JSON.parse(get(url))
|
19
27
|
res["results"].map { |result| result.dig("task", "url") }
|
20
28
|
rescue HTTPResponseError => e
|
21
29
|
puts "Failed to load urlscan.io feed (#{e})"
|
22
30
|
[]
|
23
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def url_for(path)
|
36
|
+
URI(URL + path)
|
37
|
+
end
|
24
38
|
end
|
25
39
|
end
|
26
40
|
end
|
data/lib/miteru/http_client.rb
CHANGED
@@ -14,8 +14,7 @@ module Miteru
|
|
14
14
|
@ssl_context = ctx
|
15
15
|
end
|
16
16
|
|
17
|
-
def download(url,
|
18
|
-
destination = download_path(base_dir, filename_to_save(url))
|
17
|
+
def download(url, destination)
|
19
18
|
down = Down::Http.new(default_options) { |client| client.headers(default_headers) }
|
20
19
|
down.download(url, destination: destination)
|
21
20
|
destination
|
@@ -51,15 +50,5 @@ module Miteru
|
|
51
50
|
def default_options
|
52
51
|
{ ssl_context: ssl_context }
|
53
52
|
end
|
54
|
-
|
55
|
-
def filename_to_save(url)
|
56
|
-
filename = url.split("/").last
|
57
|
-
extname = File.extname(filename)
|
58
|
-
"#{SecureRandom.alphanumeric}#{extname}"
|
59
|
-
end
|
60
|
-
|
61
|
-
def download_path(base_dir, filename)
|
62
|
-
"#{base_dir}/#{filename}"
|
63
|
-
end
|
64
53
|
end
|
65
54
|
end
|
data/lib/miteru/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: miteru
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.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: 2018-11-
|
11
|
+
date: 2018-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -217,8 +217,6 @@ files:
|
|
217
217
|
- lib/miteru/error.rb
|
218
218
|
- lib/miteru/feeds.rb
|
219
219
|
- lib/miteru/feeds/feed.rb
|
220
|
-
- lib/miteru/feeds/openphish.rb
|
221
|
-
- lib/miteru/feeds/phishtank.rb
|
222
220
|
- lib/miteru/feeds/urlscan.rb
|
223
221
|
- lib/miteru/http_client.rb
|
224
222
|
- lib/miteru/version.rb
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module Miteru
|
6
|
-
class Feeds
|
7
|
-
class OpenPhish < Feed
|
8
|
-
ENDPOINT = "https://openphish.com"
|
9
|
-
|
10
|
-
def urls
|
11
|
-
res = get("#{ENDPOINT}/feed.txt")
|
12
|
-
res.lines.map(&:chomp)
|
13
|
-
rescue HTTPResponseError => e
|
14
|
-
puts "Failed to load OpenPhish feed (#{e})"
|
15
|
-
[]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "csv"
|
4
|
-
|
5
|
-
module Miteru
|
6
|
-
class Feeds
|
7
|
-
class PhishTank < Feed
|
8
|
-
ENDPOINT = "http://data.phishtank.com"
|
9
|
-
|
10
|
-
def urls
|
11
|
-
res = get("#{ENDPOINT}/data/online-valid.csv")
|
12
|
-
table = CSV.parse(res, headers: true)
|
13
|
-
table.map { |row| row["url"] }
|
14
|
-
rescue HTTPResponseError => e
|
15
|
-
puts "Failed to load PhishTank feed (#{e})"
|
16
|
-
[]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|