Files
beef/extensions/dns/rest/dns.rb
2014-12-30 07:44:58 +10:00

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