Files
beef/extensions/dns/rest/dns.rb
2022-01-22 11:16:12 +00:00

161 lines
5.4 KiB
Ruby

#
# Copyright (c) 2006-2022 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
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
# Returns a specific rule given its id
get '/rule/:id' do
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
# Adds a new DNS rule
post '/rule' do
body = JSON.parse(request.body.read)
pattern = body['pattern']
resource = body['resource']
response = body['response']
# Validate required JSON keys
raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule' if pattern.nil? || pattern.eql?('')
raise InvalidJsonError, 'Invalid "resource" key passed to endpoint /api/dns/rule' if resource !~ /\A[A-Z]+\Z/
raise InvalidJsonError, 'Non-array "response" key passed to endpoint /api/dns/rule' unless response.is_a?(Array)
raise InvalidJsonError, 'Empty "response" array passed to endpoint /api/dns/rule' if response.empty?
# Validate resource
case resource
when 'A'
dns_resource = Resolv::DNS::Resource::IN::A
when 'AAAA'
dns_resource = Resolv::DNS::Resource::IN::AAAA
when 'CNAME'
dns_resource = Resolv::DNS::Resource::IN::CNAME
when 'HINFO'
dns_resource = Resolv::DNS::Resource::IN::HINFO
when 'MINFO'
dns_resource = Resolv::DNS::Resource::IN::MINFO
when 'MX'
dns_resource = Resolv::DNS::Resource::IN::MX
when 'NS'
dns_resource = Resolv::DNS::Resource::IN::NS
when 'PTR'
dns_resource = Resolv::DNS::Resource::IN::PTR
when 'SOA'
dns_resource = Resolv::DNS::Resource::IN::SOA
when 'TXT'
dns_resource = Resolv::DNS::Resource::IN::TXT
when 'WKS'
dns_resource = Resolv::DNS::Resource::IN::WKS
else
raise InvalidJsonError, 'Invalid "resource" key passed to endpoint /api/dns/rule'
end
# Add rule
id = @dns.add_rule(
pattern: pattern,
resource: dns_resource,
response: response
)
# Return result
result = {}
result['success'] = true
result['id'] = id
result.to_json
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
# Removes a rule given its id
delete '/rule/:id' do
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
# 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 = format str, message unless message.nil?
super(message)
end
end
end
end
end
end