mihari 0.1.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 +7 -0
 - data/.gitignore +56 -0
 - data/.rspec +3 -0
 - data/.travis.yml +7 -0
 - data/Gemfile +4 -0
 - data/LICENSE +21 -0
 - data/README.md +110 -0
 - data/Rakefile +6 -0
 - data/bin/console +14 -0
 - data/bin/setup +8 -0
 - data/examples/ipinfo_hosted_domains.rb +45 -0
 - data/examples/vt_passive_dns.rb +46 -0
 - data/exe/mihari +8 -0
 - data/lib/mihari/analyzers/base.rb +50 -0
 - data/lib/mihari/analyzers/basic.rb +19 -0
 - data/lib/mihari/analyzers/censys.rb +53 -0
 - data/lib/mihari/analyzers/shodan.rb +48 -0
 - data/lib/mihari/artifact.rb +38 -0
 - data/lib/mihari/cli.rb +64 -0
 - data/lib/mihari/errors.rb +5 -0
 - data/lib/mihari/notifiers/base.rb +20 -0
 - data/lib/mihari/notifiers/slack.rb +89 -0
 - data/lib/mihari/notifiers/the_hive.rb +26 -0
 - data/lib/mihari/the_hive.rb +41 -0
 - data/lib/mihari/type_checker.rb +86 -0
 - data/lib/mihari/version.rb +5 -0
 - data/lib/mihari.rb +34 -0
 - data/mihari.gemspec +42 -0
 - metadata +267 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: a60ee7c7a40195a7b6b49484ce1df99926278721bd77603b6c9d0f3a952c4ac2
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 5c51449f1c2c3a7e14f745490c2bee6f2d18c3f5e5eaafc25a2ba55b15e83e12
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: dba9abb2e8c856bd2fc814daf4d7d4b5d63912d707c6e4e1225dc8ecb3d7f07067d6e8764509013a99621902fb24d7a74c8dd8a5dcbde00ec2469075799458db
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 53f255209c397224a7250c5adc6323c1e99a833426f9304649c779751f0299a898c28c9b911289bf941ebed8b8ab0b61c9aef298153acf3fe269a9e9044b58e5
         
     | 
    
        data/.gitignore
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            *.gem
         
     | 
| 
      
 2 
     | 
    
         
            +
            *.rbc
         
     | 
| 
      
 3 
     | 
    
         
            +
            /.config
         
     | 
| 
      
 4 
     | 
    
         
            +
            /coverage/
         
     | 
| 
      
 5 
     | 
    
         
            +
            /InstalledFiles
         
     | 
| 
      
 6 
     | 
    
         
            +
            /pkg/
         
     | 
| 
      
 7 
     | 
    
         
            +
            /spec/reports/
         
     | 
| 
      
 8 
     | 
    
         
            +
            /spec/examples.txt
         
     | 
| 
      
 9 
     | 
    
         
            +
            /test/tmp/
         
     | 
| 
      
 10 
     | 
    
         
            +
            /test/version_tmp/
         
     | 
| 
      
 11 
     | 
    
         
            +
            /tmp/
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # Used by dotenv library to load environment variables.
         
     | 
| 
      
 14 
     | 
    
         
            +
            .env
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ## Specific to RubyMotion:
         
     | 
| 
      
 17 
     | 
    
         
            +
            .dat*
         
     | 
| 
      
 18 
     | 
    
         
            +
            .repl_history
         
     | 
| 
      
 19 
     | 
    
         
            +
            build/
         
     | 
| 
      
 20 
     | 
    
         
            +
            *.bridgesupport
         
     | 
| 
      
 21 
     | 
    
         
            +
            build-iPhoneOS/
         
     | 
| 
      
 22 
     | 
    
         
            +
            build-iPhoneSimulator/
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            ## Specific to RubyMotion (use of CocoaPods):
         
     | 
| 
      
 25 
     | 
    
         
            +
            #
         
     | 
| 
      
 26 
     | 
    
         
            +
            # We recommend against adding the Pods directory to your .gitignore. However
         
     | 
| 
      
 27 
     | 
    
         
            +
            # you should judge for yourself, the pros and cons are mentioned at:
         
     | 
| 
      
 28 
     | 
    
         
            +
            # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
         
     | 
| 
      
 29 
     | 
    
         
            +
            #
         
     | 
| 
      
 30 
     | 
    
         
            +
            # vendor/Pods/
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            ## Documentation cache and generated files:
         
     | 
| 
      
 33 
     | 
    
         
            +
            /.yardoc/
         
     | 
| 
      
 34 
     | 
    
         
            +
            /_yardoc/
         
     | 
| 
      
 35 
     | 
    
         
            +
            /doc/
         
     | 
| 
      
 36 
     | 
    
         
            +
            /rdoc/
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ## Environment normalization:
         
     | 
| 
      
 39 
     | 
    
         
            +
            /.bundle/
         
     | 
| 
      
 40 
     | 
    
         
            +
            /vendor/bundle
         
     | 
| 
      
 41 
     | 
    
         
            +
            /lib/bundler/man/
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            # for a library or gem, you might want to ignore these files since the code is
         
     | 
| 
      
 44 
     | 
    
         
            +
            # intended to run in multiple environments; otherwise, check them in:
         
     | 
| 
      
 45 
     | 
    
         
            +
            Gemfile.lock
         
     | 
| 
      
 46 
     | 
    
         
            +
            .ruby-version
         
     | 
| 
      
 47 
     | 
    
         
            +
            .ruby-gemset
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
         
     | 
| 
      
 50 
     | 
    
         
            +
            .rvmrc
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            # rspec
         
     | 
| 
      
 53 
     | 
    
         
            +
            .rspec_status
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            # solargraph
         
     | 
| 
      
 56 
     | 
    
         
            +
            .solargraph.yml
         
     | 
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2019 Manabu Niseki
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 13 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # mihari
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            [](https://travis-ci.org/ninoseki/mihari)
         
     | 
| 
      
 4 
     | 
    
         
            +
            [](https://coveralls.io/github/ninoseki/mihari?branch=master)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            mihari(`見張り`) is a framework for continuous malicious hosts (C2 / landing page / phishing, etc.) monitoring backended with [TheHive](https://github.com/TheHive-Project/TheHive).
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ## How it works
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            - mihari checks whether a TheHive instance contains given artifacts or not.
         
     | 
| 
      
 11 
     | 
    
         
            +
              - If it doesn't contain the artifacts:
         
     | 
| 
      
 12 
     | 
    
         
            +
                - mihari creates an alert with the artifacts on the TheHive instance.
         
     | 
| 
      
 13 
     | 
    
         
            +
                - mihari sends a notification to Slack. (Optional)
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 18 
     | 
    
         
            +
            gem install mihari
         
     | 
| 
      
 19 
     | 
    
         
            +
            ```
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            ## Configuration
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            All configuration is done via ENV variables.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            | Key                  | Desc.              | Required or optional           |
         
     | 
| 
      
 26 
     | 
    
         
            +
            |----------------------|--------------------|--------------------------------|
         
     | 
| 
      
 27 
     | 
    
         
            +
            | THEHIVE_API_ENDPOINT | TheHive URL        | Required                       |
         
     | 
| 
      
 28 
     | 
    
         
            +
            | THEHIVE_API_KEY      | TheHive API key    | Required                       |
         
     | 
| 
      
 29 
     | 
    
         
            +
            | SLACK_WEBHOOK_URL    | Slack Webhook URL  | Optional                       |
         
     | 
| 
      
 30 
     | 
    
         
            +
            | SLACK_CHANNEL        | Slack channel name | Optional (default: `#general`) |
         
     | 
| 
      
 31 
     | 
    
         
            +
            | CENSYS_ID            | CENSYS API ID      | Optional                       |
         
     | 
| 
      
 32 
     | 
    
         
            +
            | CENSYS_SECRET        | CENSYS secret      | Optional                       |
         
     | 
| 
      
 33 
     | 
    
         
            +
            | SHODAN_API_KEY       | Shodan API key     | Optional                       |
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            ## Basic usage
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            ### Censys
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 40 
     | 
    
         
            +
            mihari censys "YOUR_QUERY"
         
     | 
| 
      
 41 
     | 
    
         
            +
            ```
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ### Shodan
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 46 
     | 
    
         
            +
            mihari shodan "YOUR QUERY"
         
     | 
| 
      
 47 
     | 
    
         
            +
            ```
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            ### Import from JSON
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 52 
     | 
    
         
            +
            echo '{ "title": "test", "description": "test", "artifacts": ["1.1.1.1", "github.com", "2.2.2.2"] }' | mihari import_from_json
         
     | 
| 
      
 53 
     | 
    
         
            +
            ```
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            The input is a JSON data should have `title`, `description` and `artifacts` key.
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            ```json
         
     | 
| 
      
 58 
     | 
    
         
            +
            {
         
     | 
| 
      
 59 
     | 
    
         
            +
              "title": "test",
         
     | 
| 
      
 60 
     | 
    
         
            +
              "description": "test",
         
     | 
| 
      
 61 
     | 
    
         
            +
              "artifacts": ["1.1.1.1", "github.com"]
         
     | 
| 
      
 62 
     | 
    
         
            +
            }
         
     | 
| 
      
 63 
     | 
    
         
            +
            ```
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            | Key         | Desc.                                                                      |
         
     | 
| 
      
 66 
     | 
    
         
            +
            |-------------|----------------------------------------------------------------------------|
         
     | 
| 
      
 67 
     | 
    
         
            +
            | title       | A title of an alert                                                        |
         
     | 
| 
      
 68 
     | 
    
         
            +
            | description | A description of an alert                                                  |
         
     | 
| 
      
 69 
     | 
    
         
            +
            | artifacts   | An array of artifacts (supported data types: ip, domain, url, email, hash) |
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            ## How to create a custom analyzer
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            Create a class which extends `Mihari::Analyzers::Base` and implements the following methods.
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            | Name           | Desc.                                                                      | @return       |
         
     | 
| 
      
 76 
     | 
    
         
            +
            |----------------|----------------------------------------------------------------------------|---------------|
         
     | 
| 
      
 77 
     | 
    
         
            +
            | `#title`       | A title of an alert                                                        | String        |
         
     | 
| 
      
 78 
     | 
    
         
            +
            | `#description` | A description of an alert                                                  | String        |
         
     | 
| 
      
 79 
     | 
    
         
            +
            | `#artifacts`   | An array of artifacts (supported data types: ip, domain, url, email, hash) | Array<String> |
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 82 
     | 
    
         
            +
            require "mihari"
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 85 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 86 
     | 
    
         
            +
                class Example < Base
         
     | 
| 
      
 87 
     | 
    
         
            +
                  def title
         
     | 
| 
      
 88 
     | 
    
         
            +
                    "example"
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  def description
         
     | 
| 
      
 92 
     | 
    
         
            +
                    "example"
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 96 
     | 
    
         
            +
                    ["9.9.9.9", "example.com"]
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
            end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
            example = Mihari::Analyzers::Example.new
         
     | 
| 
      
 103 
     | 
    
         
            +
            example.run
         
     | 
| 
      
 104 
     | 
    
         
            +
            ```
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            See `/examples` for more.
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
         
     | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/console
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "mihari"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # You can add fixtures and/or initialization code here to make experimenting
         
     | 
| 
      
 7 
     | 
    
         
            +
            # with your gem easier. You can also use a different console, if you like.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         
     | 
| 
      
 10 
     | 
    
         
            +
            # require "pry"
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Pry.start
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require "irb"
         
     | 
| 
      
 14 
     | 
    
         
            +
            IRB.start(__FILE__)
         
     | 
    
        data/bin/setup
    ADDED
    
    
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift("#{__dir__}/../lib")
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "mihari"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "open-uri"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 10 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 11 
     | 
    
         
            +
                class HostedDomains < Base
         
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :ip
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  IPINFO_API_ENDPOINT = "https://ipinfo.io"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize(ip, token: nil)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @ip = ip
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @token = token
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def title
         
     | 
| 
      
 22 
     | 
    
         
            +
                    "IPinfo hosted domains"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def description
         
     | 
| 
      
 26 
     | 
    
         
            +
                    "IP info hosted domains: #{ip}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def token
         
     | 
| 
      
 30 
     | 
    
         
            +
                    ENV["IPINFO_TOKEN"] || @token
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 34 
     | 
    
         
            +
                    uri = URI("#{IPINFO_API_ENDPOINT}/domains/#{ip}?token=#{token}")
         
     | 
| 
      
 35 
     | 
    
         
            +
                    res = uri.read
         
     | 
| 
      
 36 
     | 
    
         
            +
                    json = JSON.parse(res)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    json.dig("domains") || []
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ip = "TARGET_IP"
         
     | 
| 
      
 44 
     | 
    
         
            +
            analyzer = Mihari::Analyzers::HostedDomains.new(ip)
         
     | 
| 
      
 45 
     | 
    
         
            +
            analyzer.run
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            $LOAD_PATH.unshift("#{__dir__}/../lib")
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require "mihari"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require "virustotal_api"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 10 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 11 
     | 
    
         
            +
                class VTPassiveDNS < Base
         
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :ip
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def initialize(ip, api_key: nil)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @ip = ip
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @api_key = api_key
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def title
         
     | 
| 
      
 20 
     | 
    
         
            +
                    "VT passive DNS"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def description
         
     | 
| 
      
 24 
     | 
    
         
            +
                    "VT passive DNS: #{ip}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def api_key
         
     | 
| 
      
 28 
     | 
    
         
            +
                    ENV["VT_API_KEY"] || @api_key
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 32 
     | 
    
         
            +
                    ip_report = VirustotalAPI::IPReport.find(ip, api_key)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    return [] unless ip_report.exists?
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    report = ip_report.report
         
     | 
| 
      
 36 
     | 
    
         
            +
                    report.dig("resolutions")&.map do |resolution|
         
     | 
| 
      
 37 
     | 
    
         
            +
                      resolution.dig("hostname")
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end&.compact
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            ip = "TARGET_IP"
         
     | 
| 
      
 45 
     | 
    
         
            +
            analyzer = Mihari::Analyzers::VTPassiveDNS.new(ip)
         
     | 
| 
      
 46 
     | 
    
         
            +
            analyzer.run
         
     | 
    
        data/exe/mihari
    ADDED
    
    
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :the_hive
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @the_hive = TheHive.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  # @return [Array<String>, Array<Mihari::Artifact>]
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 14 
     | 
    
         
            +
                    raise NotImplementedError, "You must implement #{self.class}##{__method__}"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def title
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.class.to_s.split("::").last
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def description
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise NotImplementedError, "You must implement #{self.class}##{__method__}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def run(reject_exists_ones: true)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    unique_artifacts = normalized_artifacts.reject do |artifact|
         
     | 
| 
      
 29 
     | 
    
         
            +
                      reject_exists_ones & the_hive.valid? && the_hive.exists?(data: artifact.data, data_type: artifact.data_type)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    Mihari.notifiers.each do |notifier_class|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      notifier = notifier_class.new
         
     | 
| 
      
 34 
     | 
    
         
            +
                      next unless notifier.valid?
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                      notifier.notify(title: title, description: description, artifacts: unique_artifacts)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  private
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # @return [Array<Mihari::Artifact>]
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def normalized_artifacts
         
     | 
| 
      
 44 
     | 
    
         
            +
                    artifacts.map do |artifact|
         
     | 
| 
      
 45 
     | 
    
         
            +
                      artifact.is_a?(Artifact) ? artifact : Artifact.new(artifact)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end.select(&:valid?)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Basic < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :title
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :description
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :artifacts
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(title:, description:, artifacts:)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    super()
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    @title = title
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @description = description
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @artifacts = artifacts
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "censu"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Censys < Base
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :api
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :title
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :description
         
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_reader :query
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  CENSYS_ID_KEY = "CENSYS_ID"
         
     | 
| 
      
 14 
     | 
    
         
            +
                  CENSYS_SECRET_KEY = "CENSYS_SECRET"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def initialize(query)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    super()
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    raise ArgumentError, "#{CENSYS_ID_KEY} and #{CENSYS_SECRET_KEY} are required" unless valid?
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    @api = ::Censys::API.new
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @query = query
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @title = "Censys lookup"
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @description = "Query: #{query}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 28 
     | 
    
         
            +
                    ipv4s = []
         
     | 
| 
      
 29 
     | 
    
         
            +
                    res = api.ipv4.search(query: query)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    res.each_page do |page|
         
     | 
| 
      
 31 
     | 
    
         
            +
                      page.each { |result| ipv4s << result.ip }
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    ipv4s
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def censys_id?
         
     | 
| 
      
 39 
     | 
    
         
            +
                    ENV.key? CENSYS_ID_KEY
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def censys_secret?
         
     | 
| 
      
 44 
     | 
    
         
            +
                    ENV.key? CENSYS_SECRET_KEY
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def valid?
         
     | 
| 
      
 49 
     | 
    
         
            +
                    censys_id? && censys_secret?
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "open-uri"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Analyzers
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Shodan < Base
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :api_key
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :title
         
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_reader :description
         
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :query
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def initialize(query)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    super()
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    api_key = ENV.fetch("SHODAN_API_KEY", nil)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    raise ArgumentError, "SHODAN_API_KEY is required" unless api_key
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    @api_key = api_key
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @query = query
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @title = "Shodan lookup"
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @description = "Query: #{query}"
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def artifacts
         
     | 
| 
      
 27 
     | 
    
         
            +
                    result = search
         
     | 
| 
      
 28 
     | 
    
         
            +
                    return [] unless result
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    matches = result.dig("matches") || []
         
     | 
| 
      
 31 
     | 
    
         
            +
                    matches.map do |match|
         
     | 
| 
      
 32 
     | 
    
         
            +
                      match.dig "ip_str"
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end.compact
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  private
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def search
         
     | 
| 
      
 39 
     | 
    
         
            +
                    uri = URI("https://api.shodan.io/shodan/host/search?key=#{api_key}&query=#{query}")
         
     | 
| 
      
 40 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 41 
     | 
    
         
            +
                      JSON.parse uri.read
         
     | 
| 
      
 42 
     | 
    
         
            +
                    rescue OpenURI::HTTPError
         
     | 
| 
      
 43 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "hachi"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Artifact
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :data
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @param [String] data
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @param [String, nil] message
         
     | 
| 
      
 12 
     | 
    
         
            +
                #
         
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize(data, message: nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @data = data
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @message = message
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                # @return [String, nil]
         
     | 
| 
      
 19 
     | 
    
         
            +
                def data_type
         
     | 
| 
      
 20 
     | 
    
         
            +
                  TypeChecker.type data
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 24 
     | 
    
         
            +
                def message
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @mesasge || data
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 29 
     | 
    
         
            +
                def valid?
         
     | 
| 
      
 30 
     | 
    
         
            +
                  !data_type.nil?
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # @return [Hash]
         
     | 
| 
      
 34 
     | 
    
         
            +
                def to_h
         
     | 
| 
      
 35 
     | 
    
         
            +
                  { data: data, data_type: data_type, message: message }
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/mihari/cli.rb
    ADDED
    
    | 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "thor"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 7 
     | 
    
         
            +
              class CLI < Thor
         
     | 
| 
      
 8 
     | 
    
         
            +
                desc "censys [QUERY]", "Censys lookup by a given query"
         
     | 
| 
      
 9 
     | 
    
         
            +
                def censys(query)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  with_error_handling do
         
     | 
| 
      
 11 
     | 
    
         
            +
                    censys = Analyzers::Censys.new(query)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    censys.run
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                desc "shodan [QUERY]", "Shodan lookup by a given query"
         
     | 
| 
      
 17 
     | 
    
         
            +
                def shodan(query)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  with_error_handling do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    shodan = Analyzers::Shodan.new(query)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    shodan.run
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                desc "import_from_json", "Give a JSON input via STDIN"
         
     | 
| 
      
 25 
     | 
    
         
            +
                def import_from_json(input = nil)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  json = input || STDIN.gets.chomp
         
     | 
| 
      
 27 
     | 
    
         
            +
                  raise ArgumentError, "Input not found: please give an input in a JSON format" unless json
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  json = parse_as_json(json)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  raise ArgumentError, "Invalid input format: an input JSON data should have title, description and artifacts key" unless valid_json?(json)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  title = json.dig("title")
         
     | 
| 
      
 33 
     | 
    
         
            +
                  description = json.dig("description")
         
     | 
| 
      
 34 
     | 
    
         
            +
                  artifacts = json.dig("artifacts")
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  with_error_handling do
         
     | 
| 
      
 37 
     | 
    
         
            +
                    basic = Analyzers::Basic.new(title: title, description: description, artifacts: artifacts)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    basic.run
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                no_commands do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  def with_error_handling
         
     | 
| 
      
 44 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 45 
     | 
    
         
            +
                  rescue ArgumentError, Hachi::Error, Censys::ResponseError => e
         
     | 
| 
      
 46 
     | 
    
         
            +
                    puts "Warning: #{e}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                  rescue StandardError => e
         
     | 
| 
      
 48 
     | 
    
         
            +
                    puts "Warning: #{e}"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    puts e.backtrace.join('\n')
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def parse_as_json(input)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    JSON.parse input
         
     | 
| 
      
 54 
     | 
    
         
            +
                  rescue JSON::ParserError => _
         
     | 
| 
      
 55 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  def valid_json?(json)
         
     | 
| 
      
 60 
     | 
    
         
            +
                    %w(title description artifacts).all? { |key| json.key? key }
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Notifiers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.inherited(child)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Mihari.notifiers << child
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def valid?
         
     | 
| 
      
 12 
     | 
    
         
            +
                    raise NotImplementedError, "You must implement #{self.class}##{__method__}"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def notify(title:, description:, artifacts:)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    raise NotImplementedError, "You must implement #{self.class}##{__method__}"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "slack/incoming/webhooks"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "digest/sha2"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Notifiers
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Attachment
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :data, :data_type
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(data:, data_type:)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @data = data
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @data_type = data_type
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def link
         
     | 
| 
      
 18 
     | 
    
         
            +
                    case data_type
         
     | 
| 
      
 19 
     | 
    
         
            +
                    when "hash"
         
     | 
| 
      
 20 
     | 
    
         
            +
                      "https://www.virustotal.com/#/file/#{data}"
         
     | 
| 
      
 21 
     | 
    
         
            +
                    when "ip"
         
     | 
| 
      
 22 
     | 
    
         
            +
                      "https://www.virustotal.com/#/ip-address/#{data}"
         
     | 
| 
      
 23 
     | 
    
         
            +
                    when "domain"
         
     | 
| 
      
 24 
     | 
    
         
            +
                      "https://www.virustotal.com/#/domain/#{data}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    when "url"
         
     | 
| 
      
 26 
     | 
    
         
            +
                      "https://www.virustotal.com/#/url/#{sha256}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                    when "mail"
         
     | 
| 
      
 28 
     | 
    
         
            +
                      "https://www.virustotal.com/#/search/#{data}"
         
     | 
| 
      
 29 
     | 
    
         
            +
                    else
         
     | 
| 
      
 30 
     | 
    
         
            +
                      ""
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  def to_h
         
     | 
| 
      
 36 
     | 
    
         
            +
                    {
         
     | 
| 
      
 37 
     | 
    
         
            +
                      fallback: "VT link",
         
     | 
| 
      
 38 
     | 
    
         
            +
                      title: data,
         
     | 
| 
      
 39 
     | 
    
         
            +
                      title_link: link,
         
     | 
| 
      
 40 
     | 
    
         
            +
                      footer: "virustotal.com",
         
     | 
| 
      
 41 
     | 
    
         
            +
                      footer_icon: "http://www.google.com/s2/favicons?domain=virustotal.com"
         
     | 
| 
      
 42 
     | 
    
         
            +
                    }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  private
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  # @return [String]
         
     | 
| 
      
 48 
     | 
    
         
            +
                  def sha256
         
     | 
| 
      
 49 
     | 
    
         
            +
                    Digest::SHA256.hexdigest data
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                class Slack < Base
         
     | 
| 
      
 54 
     | 
    
         
            +
                  SLACK_WEBHOOK_URL_KEY = "SLACK_WEBHOOK_URL"
         
     | 
| 
      
 55 
     | 
    
         
            +
                  SLACK_CHANNEL_KEY = "SLACK_CHANNEL"
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def slack_channel
         
     | 
| 
      
 58 
     | 
    
         
            +
                    ENV.fetch SLACK_CHANNEL_KEY, "#general"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def slack_webhook_url
         
     | 
| 
      
 62 
     | 
    
         
            +
                    ENV.fetch SLACK_WEBHOOK_URL_KEY
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  def slack_webhook_url?
         
     | 
| 
      
 66 
     | 
    
         
            +
                    ENV.key? SLACK_WEBHOOK_URL_KEY
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  def valid?
         
     | 
| 
      
 70 
     | 
    
         
            +
                    slack_webhook_url?
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def to_attachments(artifacts)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    artifacts.map do |artifact|
         
     | 
| 
      
 75 
     | 
    
         
            +
                      Attachment.new(data: artifact.data, data_type: artifact.data_type).to_h
         
     | 
| 
      
 76 
     | 
    
         
            +
                    end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def notify(title:, description:, artifacts:)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    return if artifacts.empty?
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    attachments = to_attachments(artifacts)
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    slack = ::Slack::Incoming::Webhooks.new(slack_webhook_url, channel: slack_channel)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    slack.post("#{title} (#{description})", attachments: attachments)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Notifiers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class TheHive < Base
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :api
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @api = Mihari::TheHive.new
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  # @return [true, false]
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def valid?
         
     | 
| 
      
 14 
     | 
    
         
            +
                    api.valid?
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def notify(title:, description:, artifacts:)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    return if artifacts.empty?
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    res = api.create_alert(title: title, description: description, artifacts: artifacts.map(&:to_h))
         
     | 
| 
      
 21 
     | 
    
         
            +
                    id = res.dig("id")
         
     | 
| 
      
 22 
     | 
    
         
            +
                    puts "A new alret is created. (id: #{id})"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,41 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 4 
     | 
    
         
            +
              class TheHive
         
     | 
| 
      
 5 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 6 
     | 
    
         
            +
                def api_endpont?
         
     | 
| 
      
 7 
     | 
    
         
            +
                  ENV.key? "THEHIVE_API_ENDPOINT"
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 11 
     | 
    
         
            +
                def api_key?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ENV.key? "THEHIVE_API_KEY"
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 16 
     | 
    
         
            +
                def valid?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  api_endpont? && api_key?
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [Hachi::API]
         
     | 
| 
      
 21 
     | 
    
         
            +
                def api
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @api ||= Hachi::API.new
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                # @return [Hash]
         
     | 
| 
      
 26 
     | 
    
         
            +
                def search(data:, data_type:, range: "all")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  api.artifact.search(data: data, data_type: data_type, range: range)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 31 
     | 
    
         
            +
                def exists?(data:, data_type:)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  res = search(data: data, data_type: data_type, range: "0-1")
         
     | 
| 
      
 33 
     | 
    
         
            +
                  !res.empty?
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                # @return [Hash]
         
     | 
| 
      
 37 
     | 
    
         
            +
                def create_alert(title:, description:, artifacts:)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  api.alert.create(title: title, description: description, artifacts: artifacts, type: "external", source: "mihari")
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "addressable/uri"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "email_address"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "ipaddr"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "public_suffix"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 9 
     | 
    
         
            +
              class TypeChecker
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :data
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(data)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @data = data
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 17 
     | 
    
         
            +
                def hash?
         
     | 
| 
      
 18 
     | 
    
         
            +
                  md5? || sha1? || sha256? || sha512?
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 22 
     | 
    
         
            +
                def ip?
         
     | 
| 
      
 23 
     | 
    
         
            +
                  IPAddr.new data
         
     | 
| 
      
 24 
     | 
    
         
            +
                  true
         
     | 
| 
      
 25 
     | 
    
         
            +
                rescue IPAddr::InvalidAddressError => _
         
     | 
| 
      
 26 
     | 
    
         
            +
                  false
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 30 
     | 
    
         
            +
                def domain?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  uri = Addressable::URI.parse("http://#{data}")
         
     | 
| 
      
 32 
     | 
    
         
            +
                  uri.host == data && PublicSuffix.valid?(uri.host)
         
     | 
| 
      
 33 
     | 
    
         
            +
                rescue Addressable::URI::InvalidURIError => _
         
     | 
| 
      
 34 
     | 
    
         
            +
                  false
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 38 
     | 
    
         
            +
                def url?
         
     | 
| 
      
 39 
     | 
    
         
            +
                  uri = Addressable::URI.parse(data)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  uri.scheme && uri.host && uri.path && PublicSuffix.valid?(uri.host)
         
     | 
| 
      
 41 
     | 
    
         
            +
                rescue Addressable::URI::InvalidURIError => _
         
     | 
| 
      
 42 
     | 
    
         
            +
                  false
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 46 
     | 
    
         
            +
                def mail?
         
     | 
| 
      
 47 
     | 
    
         
            +
                  EmailAddress.valid? data
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # @return [String, nil]
         
     | 
| 
      
 51 
     | 
    
         
            +
                def type
         
     | 
| 
      
 52 
     | 
    
         
            +
                  return "hash" if hash?
         
     | 
| 
      
 53 
     | 
    
         
            +
                  return "ip" if ip?
         
     | 
| 
      
 54 
     | 
    
         
            +
                  return "domain" if domain?
         
     | 
| 
      
 55 
     | 
    
         
            +
                  return "url" if url?
         
     | 
| 
      
 56 
     | 
    
         
            +
                  return "mail" if mail?
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                # @return [String, nil]
         
     | 
| 
      
 60 
     | 
    
         
            +
                def self.type(data)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  new(data).type
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                private
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 67 
     | 
    
         
            +
                def md5?
         
     | 
| 
      
 68 
     | 
    
         
            +
                  data.match? /^[A-Fa-f0-9]{32}$/
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 72 
     | 
    
         
            +
                def sha1?
         
     | 
| 
      
 73 
     | 
    
         
            +
                  data.match? /^[A-Fa-f0-9]{40}$/
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 77 
     | 
    
         
            +
                def sha256?
         
     | 
| 
      
 78 
     | 
    
         
            +
                  data.match? /^[A-Fa-f0-9]{64}$/
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # @return [true, false]
         
     | 
| 
      
 82 
     | 
    
         
            +
                def sha512?
         
     | 
| 
      
 83 
     | 
    
         
            +
                  data.match? /^[A-Fa-f0-9]{128}$/
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/mihari.rb
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "mem"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mihari
         
     | 
| 
      
 6 
     | 
    
         
            +
              class << self
         
     | 
| 
      
 7 
     | 
    
         
            +
                include Mem
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def notifiers
         
     | 
| 
      
 10 
     | 
    
         
            +
                  []
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
                memoize :notifiers
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            require "mihari/version"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            require "mihari/errors"
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            require "mihari/type_checker"
         
     | 
| 
      
 21 
     | 
    
         
            +
            require "mihari/artifact"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            require "mihari/the_hive"
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            require "mihari/analyzers/base"
         
     | 
| 
      
 26 
     | 
    
         
            +
            require "mihari/analyzers/basic"
         
     | 
| 
      
 27 
     | 
    
         
            +
            require "mihari/analyzers/censys"
         
     | 
| 
      
 28 
     | 
    
         
            +
            require "mihari/analyzers/shodan"
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            require "mihari/notifiers/base"
         
     | 
| 
      
 31 
     | 
    
         
            +
            require "mihari/notifiers/slack"
         
     | 
| 
      
 32 
     | 
    
         
            +
            require "mihari/notifiers/the_hive"
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            require "mihari/cli"
         
     | 
    
        data/mihari.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            lib = File.expand_path('lib', __dir__)
         
     | 
| 
      
 4 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "mihari/version"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.name          = "mihari"
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.version       = Mihari::VERSION
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.authors       = ["Manabu Niseki"]
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.email         = ["manabu.niseki@gmail.com"]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              spec.summary       = "A framework for continuous malicious hosts monitoring."
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.description   = "A framework for continuous malicious hosts monitoring."
         
     | 
| 
      
 15 
     | 
    
         
            +
              spec.homepage      = "https://github.com/ninoseki/mihari"
         
     | 
| 
      
 16 
     | 
    
         
            +
              spec.license       = "MIT"
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              # Specify which files should be added to the gem when it is released.
         
     | 
| 
      
 19 
     | 
    
         
            +
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         
     | 
| 
      
 20 
     | 
    
         
            +
              spec.files         = Dir.chdir(File.expand_path(__dir__)) do
         
     | 
| 
      
 21 
     | 
    
         
            +
                `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.bindir        = "exe"
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.require_paths = ["lib"]
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              spec.add_development_dependency "bundler", "~> 2.0"
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_development_dependency "coveralls", "~> 0.8"
         
     | 
| 
      
 29 
     | 
    
         
            +
              spec.add_development_dependency "rake", "~> 12.3"
         
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_development_dependency "rspec", "~> 3.8"
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_development_dependency "vcr", "~> 4.0"
         
     | 
| 
      
 32 
     | 
    
         
            +
              spec.add_development_dependency "webmock", "~> 3.5"
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              spec.add_dependency "addressable", "~> 2.6"
         
     | 
| 
      
 35 
     | 
    
         
            +
              spec.add_dependency "censu", "~> 0.2"
         
     | 
| 
      
 36 
     | 
    
         
            +
              spec.add_dependency "email_address", "~> 0.1"
         
     | 
| 
      
 37 
     | 
    
         
            +
              spec.add_dependency "hachi", "~> 0.1"
         
     | 
| 
      
 38 
     | 
    
         
            +
              spec.add_dependency "mem", "~> 0.1"
         
     | 
| 
      
 39 
     | 
    
         
            +
              spec.add_dependency "public_suffix", "~> 3.0"
         
     | 
| 
      
 40 
     | 
    
         
            +
              spec.add_dependency "slack-incoming-webhooks", "~> 0.2"
         
     | 
| 
      
 41 
     | 
    
         
            +
              spec.add_dependency "thor", "~> 0.19"
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,267 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: mihari
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Manabu Niseki
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-04-23 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: coveralls
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '0.8'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '0.8'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: '12.3'
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '12.3'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 57 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 58 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 59 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 61 
     | 
    
         
            +
                    version: '3.8'
         
     | 
| 
      
 62 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 63 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '3.8'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              name: vcr
         
     | 
| 
      
 71 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 73 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 75 
     | 
    
         
            +
                    version: '4.0'
         
     | 
| 
      
 76 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 77 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '4.0'
         
     | 
| 
      
 83 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 84 
     | 
    
         
            +
              name: webmock
         
     | 
| 
      
 85 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 88 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                    version: '3.5'
         
     | 
| 
      
 90 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 91 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 92 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 94 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 96 
     | 
    
         
            +
                    version: '3.5'
         
     | 
| 
      
 97 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 98 
     | 
    
         
            +
              name: addressable
         
     | 
| 
      
 99 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 100 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 101 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 102 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 103 
     | 
    
         
            +
                    version: '2.6'
         
     | 
| 
      
 104 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 105 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 106 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 107 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 108 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 109 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 110 
     | 
    
         
            +
                    version: '2.6'
         
     | 
| 
      
 111 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 112 
     | 
    
         
            +
              name: censu
         
     | 
| 
      
 113 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 114 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 115 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 116 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 117 
     | 
    
         
            +
                    version: '0.2'
         
     | 
| 
      
 118 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 119 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 120 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 121 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 122 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 123 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 124 
     | 
    
         
            +
                    version: '0.2'
         
     | 
| 
      
 125 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 126 
     | 
    
         
            +
              name: email_address
         
     | 
| 
      
 127 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 128 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 129 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 130 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 131 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 132 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 133 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 134 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 135 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 136 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 137 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 138 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 139 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 140 
     | 
    
         
            +
              name: hachi
         
     | 
| 
      
 141 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 142 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 143 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 144 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 145 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 146 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 147 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 148 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 149 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 150 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 151 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 152 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 153 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 154 
     | 
    
         
            +
              name: mem
         
     | 
| 
      
 155 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 156 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 157 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 158 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 159 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 160 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 161 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 162 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 163 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 164 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 165 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 166 
     | 
    
         
            +
                    version: '0.1'
         
     | 
| 
      
 167 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 168 
     | 
    
         
            +
              name: public_suffix
         
     | 
| 
      
 169 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 170 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 171 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 172 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 173 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 174 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 175 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 176 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 177 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 178 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 179 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 180 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 181 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 182 
     | 
    
         
            +
              name: slack-incoming-webhooks
         
     | 
| 
      
 183 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 184 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 185 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 186 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 187 
     | 
    
         
            +
                    version: '0.2'
         
     | 
| 
      
 188 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 189 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 190 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 191 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 192 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 193 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 194 
     | 
    
         
            +
                    version: '0.2'
         
     | 
| 
      
 195 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 196 
     | 
    
         
            +
              name: thor
         
     | 
| 
      
 197 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 198 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 199 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 200 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 201 
     | 
    
         
            +
                    version: '0.19'
         
     | 
| 
      
 202 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 203 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 204 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 205 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 206 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 207 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 208 
     | 
    
         
            +
                    version: '0.19'
         
     | 
| 
      
 209 
     | 
    
         
            +
            description: A framework for continuous malicious hosts monitoring.
         
     | 
| 
      
 210 
     | 
    
         
            +
            email:
         
     | 
| 
      
 211 
     | 
    
         
            +
            - manabu.niseki@gmail.com
         
     | 
| 
      
 212 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 213 
     | 
    
         
            +
            - mihari
         
     | 
| 
      
 214 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 215 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 216 
     | 
    
         
            +
            files:
         
     | 
| 
      
 217 
     | 
    
         
            +
            - ".gitignore"
         
     | 
| 
      
 218 
     | 
    
         
            +
            - ".rspec"
         
     | 
| 
      
 219 
     | 
    
         
            +
            - ".travis.yml"
         
     | 
| 
      
 220 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 221 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 222 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 223 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 224 
     | 
    
         
            +
            - bin/console
         
     | 
| 
      
 225 
     | 
    
         
            +
            - bin/setup
         
     | 
| 
      
 226 
     | 
    
         
            +
            - examples/ipinfo_hosted_domains.rb
         
     | 
| 
      
 227 
     | 
    
         
            +
            - examples/vt_passive_dns.rb
         
     | 
| 
      
 228 
     | 
    
         
            +
            - exe/mihari
         
     | 
| 
      
 229 
     | 
    
         
            +
            - lib/mihari.rb
         
     | 
| 
      
 230 
     | 
    
         
            +
            - lib/mihari/analyzers/base.rb
         
     | 
| 
      
 231 
     | 
    
         
            +
            - lib/mihari/analyzers/basic.rb
         
     | 
| 
      
 232 
     | 
    
         
            +
            - lib/mihari/analyzers/censys.rb
         
     | 
| 
      
 233 
     | 
    
         
            +
            - lib/mihari/analyzers/shodan.rb
         
     | 
| 
      
 234 
     | 
    
         
            +
            - lib/mihari/artifact.rb
         
     | 
| 
      
 235 
     | 
    
         
            +
            - lib/mihari/cli.rb
         
     | 
| 
      
 236 
     | 
    
         
            +
            - lib/mihari/errors.rb
         
     | 
| 
      
 237 
     | 
    
         
            +
            - lib/mihari/notifiers/base.rb
         
     | 
| 
      
 238 
     | 
    
         
            +
            - lib/mihari/notifiers/slack.rb
         
     | 
| 
      
 239 
     | 
    
         
            +
            - lib/mihari/notifiers/the_hive.rb
         
     | 
| 
      
 240 
     | 
    
         
            +
            - lib/mihari/the_hive.rb
         
     | 
| 
      
 241 
     | 
    
         
            +
            - lib/mihari/type_checker.rb
         
     | 
| 
      
 242 
     | 
    
         
            +
            - lib/mihari/version.rb
         
     | 
| 
      
 243 
     | 
    
         
            +
            - mihari.gemspec
         
     | 
| 
      
 244 
     | 
    
         
            +
            homepage: https://github.com/ninoseki/mihari
         
     | 
| 
      
 245 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 246 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 247 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 248 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 249 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 250 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 251 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 252 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 253 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 254 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 255 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 256 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 257 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 258 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 259 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 260 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 261 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 262 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 263 
     | 
    
         
            +
            rubygems_version: 3.0.2
         
     | 
| 
      
 264 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 265 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 266 
     | 
    
         
            +
            summary: A framework for continuous malicious hosts monitoring.
         
     | 
| 
      
 267 
     | 
    
         
            +
            test_files: []
         
     |