miteru 0.4.0 → 0.5.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: aa876b402ad3fcfe44fb1a66035bdb7649db11383650faf572d94fb8b4c8f498
4
- data.tar.gz: c8ffde9ad933fbe670900d8b6547f5ce35ba7f85bd0a0d1201d3c00518d612bb
3
+ metadata.gz: b3784652417f9e36941b1bc9ed8a76acaa86481a4730223b8ad1913775980097
4
+ data.tar.gz: 47526f0cc44c07a8aa9a651973f0fa4a3d455dfe49abed255f0aed1780abb604
5
5
  SHA512:
6
- metadata.gz: 15bc48dc53696348635d637674c5574d537b8cf220939dce354875706f1a58820b95ecab547da0106a72e76d026d3e067b14438bfbef7ce1ce971737491269e2
7
- data.tar.gz: 86d0aad06740b2013c35ef3920fa27fc1ac811580c08103273f3c073362d37b0e2c8bd0e49c9d8aac63dd06004556b902c6bccaf57f7833670e01d8e907d72a1
6
+ metadata.gz: 124a5071040ee603dab9e5986064566e6e61d2acb812d052bc8cee69a673253894004b1824c3fac80fa467674640c2a21edec37a14aa1b22d1d03d40c7b99b4c
7
+ data.tar.gz: 7da8680a710bef8081b2ba279843b53a28fba36c29290ba9566ce3e40fd892ac714a92feec4008236d2b84246ac5bbaa3d94600d008b39953c6103630faa3627
data/README.md CHANGED
@@ -9,8 +9,8 @@ Miteru is an experimental phishing kit detection tool.
9
9
 
10
10
  ## How it works
11
11
 
12
- - It collects phishing suspicious URLs from [urlscan.io](https://urlscan.io/search/#certstream-suspicious).
13
- - It checks a suspicious URL whether it contains a phishing kit (`*.zip` file) or not.
12
+ - It collects phishing suspicious URLs from [urlscan.io](https://urlscan.io/search/#certstream-suspicious) and [OpenPhish community feed](https://openphish.com/feed.txt).
13
+ - It checks a suspicious URL whether it has a directory listing and contains a phishing kit (`*.zip` file) or not.
14
14
 
15
15
  ## Installation
16
16
 
data/lib/miteru/cli.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "colorize"
4
+ require "digest"
5
+ require "fileutils"
4
6
  require "http"
5
7
  require "thor"
6
8
 
@@ -17,7 +19,7 @@ module Miteru
17
19
  websites.each do |website|
18
20
  next unless website.has_kit?
19
21
 
20
- message = "#{website.url}: it might contain a phishing kit (#{website.zip_files.join(',')})."
22
+ message = "#{website.url}: it might contain phishing kit(s) (#{website.zip_files.join(', ')})."
21
23
  puts message.colorize(:light_red)
22
24
  post_to_slack(message) if options[:post_to_slack] && valid_slack_setting?
23
25
  download_zip_files(website.url, website.zip_files, options[:download_to]) if options[:auto_download]
@@ -29,14 +31,30 @@ module Miteru
29
31
  zip_files.each do |path|
30
32
  target_url = "#{url}/#{path}"
31
33
  begin
32
- destination = HTTPClient.download(target_url, base_dir)
33
- puts "Download #{target_url} as #{destination}"
34
+ download_file_path = HTTPClient.download(target_url, base_dir)
35
+ if duplicated?(download_file_path, base_dir)
36
+ puts "Do not download #{target_url} because there is a same hash file in the directory (SHA256: #{sha256(download_file_path)})."
37
+ FileUtils.rm download_file_path
38
+ else
39
+ puts "Download #{target_url} as #{download_file_path}"
40
+ end
34
41
  rescue Down::Error => e
35
42
  puts "Failed to download: #{target_url} (#{e})"
36
43
  end
37
44
  end
38
45
  end
39
46
 
47
+ def sha256(path)
48
+ digest = Digest::SHA256.file(path)
49
+ digest.hexdigest
50
+ end
51
+
52
+ def duplicated?(file_path, base_dir)
53
+ base = sha256(file_path)
54
+ sha256s = Dir.glob("#{base_dir}/*.zip").map { |path| sha256(path) }
55
+ sha256s.select { |sha256| sha256 == base }.length > 1
56
+ end
57
+
40
58
  def valid_slack_setting?
41
59
  ENV["SLACK_WEBHOOK_URL"] != nil
42
60
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thread/pool"
4
3
  require "http"
4
+ require "json"
5
+ require "thread/pool"
6
+ require "uri"
5
7
 
6
8
  module Miteru
7
9
  class Crawler
@@ -9,6 +11,9 @@ module Miteru
9
11
  attr_reader :size
10
12
  attr_reader :verbose
11
13
 
14
+ URLSCAN_ENDPOINT = "https://urlscan.io/api/v1"
15
+ OPENPHISH_ENDPOINT = "https://openphish.com"
16
+
12
17
  def initialize(size: 100, verbose: false)
13
18
  @threads = 10
14
19
  @size = size
@@ -16,17 +21,44 @@ module Miteru
16
21
  raise ArgumentError, "size must be less than 100,000" if size > 100_000
17
22
  end
18
23
 
19
- def suspicous_urls
20
- url = "https://urlscan.io/api/v1/search/?q=certstream-suspicious&size=#{size}"
24
+ def urlscan_feed
25
+ url = "#{URLSCAN_ENDPOINT}/search/?q=certstream-suspicious&size=#{size}"
21
26
  res = JSON.parse(get(url))
22
27
  res["results"].map { |result| result.dig("task", "url") }
23
28
  end
24
29
 
30
+ def openphish_feed
31
+ res = get("#{OPENPHISH_ENDPOINT}/feed.txt")
32
+ res.lines.map(&:chomp)
33
+ end
34
+
35
+ def breakdown(url)
36
+ begin
37
+ uri = URI.parse(url)
38
+ rescue URI::InvalidURIError => _
39
+ return []
40
+ end
41
+ base = "#{uri.scheme}://#{uri.hostname}"
42
+ [base]
43
+ # TODO: Should add a option for burute force directory
44
+ # segments = uri.path.split("/")
45
+ # if segments.length.zero?
46
+ # [base]
47
+ # else
48
+ # (0...segments.length).map { |idx| "#{base}#{segments[0..idx].join('/')}" }
49
+ # end
50
+ end
51
+
52
+ def suspicious_urls
53
+ urls = urlscan_feed + openphish_feed
54
+ urls.map { |url| breakdown(url) }.flatten.uniq.sort
55
+ end
56
+
25
57
  def execute
26
58
  pool = Thread.pool(threads)
27
59
  websites = []
28
60
 
29
- suspicous_urls.each do |url|
61
+ suspicious_urls.each do |url|
30
62
  pool.process do
31
63
  website = Website.new(url)
32
64
  puts "#{website.url}: it doesn't contain a phishing kit." if verbose && !website.has_kit?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Miteru
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -18,7 +18,9 @@ module Miteru
18
18
  @zip_files ||= doc.css("a").map do |a|
19
19
  href = a.get("href")
20
20
  href&.end_with?(".zip") ? href : nil
21
- end.compact
21
+ end.compact.map do |href|
22
+ href.start_with?("/") ? href[1..-1] : href
23
+ end
22
24
  end
23
25
 
24
26
  def ok?
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.0
4
+ version: 0.5.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-09-22 00:00:00.000000000 Z
11
+ date: 2018-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler