Skip to content

Commit

Permalink
Merge pull request #7 from PercussiveElbow/reverse_endpoint
Browse files Browse the repository at this point in the history
Adding reverse endpoint support
  • Loading branch information
PercussiveElbow authored Oct 21, 2020
2 parents ed00cee + bbda172 commit 8596bd3
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 13 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Crystal SDK and command line client for [SonarSearch/Crobat](https://github.com/

## Download
Prebuilt binary releases available [here](https://github.com/PercussiveElbow/crobat-sdk-crystal/releases).
Preuilt Docker container available [here](https://github.com/users/PercussiveElbow/packages/container/package/crobat).
Prebuilt Docker container available [here](https://github.com/users/PercussiveElbow/packages/container/package/crobat).

To grab the latest release:

Expand All @@ -20,19 +20,19 @@ To run the latest Docker container (~20MB)

```
Usage: ./crobat_client [arguments]
-d DOMAIN, --domain Target domain.
-s TYPE, --type Search type. (SUBDOMAIN, ALL, TLD)
-q QUERY, --query Target domain, IP or IP range to query.
-s TYPE, --type Search type. (SUBDOMAIN, ALL, REVERSE TLD)
-f FORMAT, --format File output format. (JSON, TXT, CSV)
-o FILE, --output File output location.
-h, --help Show help.
E.g ./crobat_client -d twitter.com -s subdomain
E.g ./crobat_client -q twitter.com -s subdomain
```

### Client - Docker
To build and use the Docker container:
```
sudo docker build . -t crobat && sudo docker run -it crobat -d twitter.com -s subdomain
sudo docker build . -t crobat && sudo docker run -it crobat -q twitter.com -s subdomain
```

## Usage - SDK
Expand All @@ -58,6 +58,12 @@ puts(client.retrieve_all("twitter.com"))
# Retrieving tlds via SDK
puts(client.retrieve_tlds("twitter.com"))
# Retrieving reverse info for an IP via SDK
puts(client.retrieve_reverse("8.8.8.8"))
# Retrieving reverse info for an IP range via SDK
puts(client.retrieve_reverse_range("95.138.157.0/16"))
```

## Building manually
Expand Down
34 changes: 29 additions & 5 deletions src/crobat_client.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def output_txt_or_csv(output_results : Array(String), output_path : String, outp
end
end

def output_to_file(results, output_format : String, output_path : String, search_type : String) # needs cleaned up
def output_to_file(results, output_format : String, output_path : String, search_type : String, query : String)
output_file = File.open output_path, "w"

if results.is_a?(Array(String))
Expand All @@ -18,11 +18,29 @@ def output_to_file(results, output_format : String, output_path : String, search
when "csv"
output_txt_or_csv(results.insert(0,search_type == "tld" ? "tld" : "subdomain"), output_path, output_file)
when "json"
output_file.puts({search_type => results}.to_json.to_s)
output_file.puts({query => results}.to_json.to_s)
else
puts("Unable to output file")
end

elsif results.is_a?(Hash(String,Array(String)))
organised_results = [] of String
results.each_key do | key |
results[key].each do | value |
organised_results.push(key + ", " + value)
end
end

case output_format.downcase
when "txt"
output_txt_or_csv(organised_results, output_path, output_file)
when "csv"
output_txt_or_csv(organised_results.insert(0,"IP, subdomain"), output_path, output_file)
when "json"
output_file.puts({query => results}.to_json.to_s)
else
puts("Unable to output file")
end
elsif results.is_a?(Array(Crobat::CrobatSDK::SonarAllResult))
organised_results = [] of String
results.each do | result |
Expand Down Expand Up @@ -52,8 +70,8 @@ def cli

OptionParser.parse do |parser|
parser.banner = "Crobat Client.\nUsage: ./crobat.cr [arguments]"
parser.on("-d DOMAIN", "--domain", "Target domain.") { |domain| target = domain }
parser.on("-s TYPE","--type", "Search type. (SUBDOMAIN, ALL, TLD)") { |type| search_type = type }
parser.on("-q QUERY", "--query", "Domain, IP or IP range to query.") { |query| target = query }
parser.on("-s TYPE","--type", "Search type. (SUBDOMAIN, TLD, REVERSE, ALL)") { |type| search_type = type }
parser.on("-f FORMAT", "--format","File output format. (JSON, TXT, CSV)") { |format| output_format = format}
parser.on("-o FILE", "--output","File output location.") { |file| output_path = file}
parser.on("-h", "--help", "Show help.") { puts parser }
Expand All @@ -71,6 +89,12 @@ def cli
results = client.retrieve_tlds(target)
when "subdomain"
results = client.retrieve_subdomains(target)
when "reverse"
if target.includes?("/")
results = client.retrieve_reverse_range(target)
else
results = client.retrieve_reverse(target)
end
else
puts("Invalid search type supplied. Valid search types: SUBDOMAIN, ALL, TLD")
end
Expand All @@ -81,7 +105,7 @@ def cli
end

if output_format.size() > 0 && output_path.size() > 0
output_to_file(results, output_format, output_path,search_type)
output_to_file(results, output_format, output_path, search_type, target)
end
end

Expand Down
40 changes: 37 additions & 3 deletions src/crobat_sdk.cr
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Crobat
resp = HTTP::Client.get("#{@api_url}/subdomains/#{domain}#{page_query}")
if resp.status_code == 200
items = Array(String).from_json(resp.body)
return items.size()>=999 ? items + retrieve_subdomains(domain,page+1) : items
return items.size()>=9999 ? items + retrieve_subdomains(domain,page+1) : items
else
raise CrobatQueryException.new("Error querying Subdomains API Endpoint #{@api_url} with domain #{domain}. Status code #{resp.status_code}")
end
Expand All @@ -32,7 +32,7 @@ module Crobat
resp = HTTP::Client.get("#{@api_url}/tlds/#{search_query}#{page_query}")
if resp.status_code == 200
items = Array(String).from_json(resp.body)
return items.size()>=999 ? items + retrieve_tlds(search_query,page+1) : items
return items.size()>=9999 ? items + retrieve_tlds(search_query,page+1) : items
else
raise CrobatQueryException.new("Error querying TLD API Endpoint #{@api_url} with TLD #{search_query}. Status code #{resp.status_code}")
end
Expand All @@ -48,7 +48,7 @@ module Crobat
resp = HTTP::Client.get( "#{@api_url}/all/#{search_query}#{page_query}")
if resp.status_code == 200
items = Array(SonarAllResult).from_json(resp.body)
if items.size()>=999
if items.size()>=9999
recursive_items = retrieve_all(search_query,page+1)
return recursive_items.size()> 0 ? items + recursive_items : items
else
Expand All @@ -64,6 +64,40 @@ module Crobat
return [] of SonarAllResult
end
end

def retrieve_reverse_range(search_query : String, page : Int = 0) : Hash(String,Array(String))
begin
page_query = page > 0 ? "?page=#{page.to_s}" : ""
resp = HTTP::Client.get( "#{@api_url}/reverse/#{search_query}#{page_query}")
if resp.status_code == 200
return Hash(String,Array(String)).from_json(resp.body)
else
puts(resp.headers)
raise CrobatQueryException.new("Error querying Reverse API Endpoint #{@api_url} with query #{search_query}. Status code #{resp.status_code}")
return Hash(String,Array(String)).new
end
rescue ex : Exception
print(ex)
return Hash(String,Array(String)).new
end
end

def retrieve_reverse(search_query : String, page : Int = 0) : Array(String)
begin
page_query = page > 0 ? "?page=#{page.to_s}" : ""
resp = HTTP::Client.get( "#{@api_url}/reverse/#{search_query}#{page_query}")
if resp.status_code == 200
return Array(String).from_json(resp.body)
else
puts(resp.headers)
raise CrobatQueryException.new("Error querying Reverse API Endpoint #{@api_url} with query #{search_query}. Status code #{resp.status_code}")
return [] of String
end
rescue ex : Exception
print(ex)
return [] of String
end
end

class SonarAllResult include JSON::Serializable
property name : String
Expand Down

0 comments on commit 8596bd3

Please sign in to comment.