153 lines
4.7 KiB
Ruby
153 lines
4.7 KiB
Ruby
#
|
|
# Copyright (c) 2006-2015 Wade Alcorn - wade@bindshell.net
|
|
# Browser Exploitation Framework (BeEF) - http://beefproject.com
|
|
# See the file 'doc/COPYING' for copying permission
|
|
#
|
|
module BeEF
|
|
module Extension
|
|
module Dns
|
|
|
|
# This class handles the routing of RESTful API requests that query BeEF's DNS server
|
|
class DnsRest < BeEF::Core::Router::Router
|
|
|
|
# Filters out bad requests before performing any routing
|
|
before do
|
|
@dns ||= BeEF::Extension::Dns::Server.instance
|
|
config = BeEF::Core::Configuration.instance
|
|
|
|
# Require a valid API token from a valid IP address
|
|
halt 401 unless params[:token] == config.get('beef.api_token')
|
|
halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)
|
|
|
|
headers 'Content-Type' => 'application/json; charset=UTF-8',
|
|
'Pragma' => 'no-cache',
|
|
'Cache-Control' => 'no-cache',
|
|
'Expires' => '0'
|
|
end
|
|
|
|
# Returns the entire current DNS ruleset
|
|
get '/ruleset' do
|
|
begin
|
|
ruleset = @dns.get_ruleset
|
|
count = ruleset.length
|
|
|
|
result = {}
|
|
result[:count] = count
|
|
result[:ruleset] = ruleset
|
|
result.to_json
|
|
rescue StandardError => e
|
|
print_error "Internal error while retrieving DNS ruleset (#{e.message})"
|
|
halt 500
|
|
end
|
|
end
|
|
|
|
# Returns a specific rule given its id
|
|
get '/rule/:id' do
|
|
begin
|
|
id = params[:id]
|
|
|
|
rule = @dns.get_rule(id)
|
|
raise InvalidParamError, 'id' if rule.nil?
|
|
halt 404 if rule.empty?
|
|
|
|
rule.to_json
|
|
rescue InvalidParamError => e
|
|
print_error e.message
|
|
halt 400
|
|
rescue StandardError => e
|
|
print_error "Internal error while retrieving DNS rule with id #{id} (#{e.message})"
|
|
halt 500
|
|
end
|
|
end
|
|
|
|
# Adds a new DNS rule
|
|
post '/rule' do
|
|
begin
|
|
body = JSON.parse(request.body.read)
|
|
|
|
pattern = body['pattern']
|
|
resource = body['resource']
|
|
response = body['response']
|
|
|
|
valid_resources = ["A", "AAAA", "CNAME", "HINFO", "MINFO", "MX", "NS", "PTR", "SOA", "TXT", "WKS"]
|
|
|
|
# Validate required JSON keys
|
|
unless [pattern, resource, response].include?(nil)
|
|
if response.is_a?(Array)
|
|
raise InvalidJsonError, 'Empty "response" key passed to endpoint /api/dns/rule' if response.empty?
|
|
else
|
|
raise InvalidJsonError, 'Non-array "response" key passed to endpoint /api/dns/rule'
|
|
end
|
|
|
|
raise InvalidJsonError, 'Wrong "resource" key passed to endpoint /api/dns/rule' unless valid_resources.include?(resource)
|
|
|
|
id = @dns.add_rule(
|
|
:pattern => pattern,
|
|
:resource => eval("Resolv::DNS::Resource::IN::#{resource}"),
|
|
:response => response
|
|
)
|
|
|
|
result = {}
|
|
result['success'] = true
|
|
result['id'] = id
|
|
result.to_json
|
|
end
|
|
rescue InvalidJsonError => e
|
|
print_error e.message
|
|
halt 400
|
|
rescue StandardError => e
|
|
print_error "Internal error while adding DNS rule (#{e.message})"
|
|
halt 500
|
|
end
|
|
end
|
|
|
|
# Removes a rule given its id
|
|
delete '/rule/:id' do
|
|
begin
|
|
id = params[:id]
|
|
|
|
removed = @dns.remove_rule!(id)
|
|
raise InvalidParamError, 'id' if removed.nil?
|
|
|
|
result = {}
|
|
result['success'] = removed
|
|
result.to_json
|
|
rescue InvalidParamError => e
|
|
print_error e.message
|
|
halt 400
|
|
rescue StandardError => e
|
|
print_error "Internal error while removing DNS rule with id #{id} (#{e.message})"
|
|
halt 500
|
|
end
|
|
end
|
|
|
|
# Raised when invalid JSON input is passed to an /api/dns handler.
|
|
class InvalidJsonError < StandardError
|
|
|
|
DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler'
|
|
|
|
def initialize(message = nil)
|
|
super(message || DEFAULT_MESSAGE)
|
|
end
|
|
|
|
end
|
|
|
|
# Raised when an invalid named parameter is passed to an /api/dns handler.
|
|
class InvalidParamError < StandardError
|
|
|
|
DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler'
|
|
|
|
def initialize(message = nil)
|
|
str = "Invalid \"%s\" parameter passed to /api/dns handler"
|
|
message = sprintf str, message unless message.nil?
|
|
super(message)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|