class Mihari::Analyzers::Shodan

Constants

PAGE_SIZE

Public Instance Methods

artifacts() click to toggle source
# File lib/mihari/analyzers/shodan.rb, line 13
def artifacts
  results = search
  return [] unless results || results.empty?

  results = results.map { |result| Structs::Shodan::Result.from_dynamic!(result) }
  results.map do |result|
    matches = result.matches || []
    matches.map { |match| build_artifact match }
  end.flatten.compact.uniq(&:data)
end

Private Instance Methods

api() click to toggle source
# File lib/mihari/analyzers/shodan.rb, line 32
def api
  @api ||= ::Shodan::API.new(key: Mihari.config.shodan_api_key)
end
build_artifact(match) click to toggle source

Build an artifact from a Shodan search API response

@param [Structs::Shodan::Match] match

@return [Artifact]

# File lib/mihari/analyzers/shodan.rb, line 80
def build_artifact(match)
  as = AutonomousSystem.new(asn: normalize_asn(match.asn))
  geolocation = Geolocation.new(
    country: match.location.country_name,
    country_code: match.location.country_code
  )

  Artifact.new(
    data: match.ip_str,
    source: source,
    autonomous_system: as,
    geolocation: geolocation
  )
end
configuration_keys() click to toggle source
# File lib/mihari/analyzers/shodan.rb, line 28
def configuration_keys
  %w[shodan_api_key]
end
search_with_page(query, page: 1) click to toggle source

Search with pagination

@param [String] query @param [Integer] page

@return [Hash]

# File lib/mihari/analyzers/shodan.rb, line 44
def search_with_page(query, page: 1)
  api.host.search(query, page: page)
rescue ::Shodan::Error => e
  raise RetryableError, e if e.message.include?("request timed out")

  raise e
end