diff --git a/extensions/dns/rest/dns.rb b/extensions/dns/rest/dns.rb index 2dcc0a192..2df9982d7 100644 --- a/extensions/dns/rest/dns.rb +++ b/extensions/dns/rest/dns.rb @@ -54,30 +54,41 @@ module DNS body = JSON.parse(request.body.read) pattern = body['pattern'] - type = eval body['type'] - block = body['block'] + type = body['type'] + response = body['response'] # Validate required JSON keys - unless [pattern, type, block].include?(nil) + unless [pattern, type, response].include?(nil) # Determine whether 'pattern' is a String or Regexp begin pattern_test = eval pattern pattern = pattern_test if pattern_test.class == Regexp rescue => e; end - if type.superclass != Resolv::DNS::Resource - raise InvalidJsonError, 'Invalid "type" key passed to endpoint /api/dns/rule' + if response.class == Array + if response.length == 0 + raise InvalidJsonError, 'Empty "reponse" key passed to endpoint /api/dns/rule' + end + else + raise InvalidJsonError, 'Non-array "reponse" key passed to endpoint /api/dns/rule' end - unless BeEF::Filters.is_non_empty_string?(block) - raise InvalidJsonError, 'Invalid "block" key passed to endpoint /api/dns/rule' + unless BeEF::Filters.is_non_empty_string?(pattern) + raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule' + end + + unless BeEF::Filters.is_non_empty_string?(type) + raise InvalidJsonError, 'Empty "type" key passed to endpoint /api/dns/rule' end id = '' - # Bypass #add_rule so that 'block' can be passed as a String + type_obj = eval "Resolv::DNS::Resource::IN::#{type}" + block_src = format_response(type, response) + + # Bypass #add_rule so that 'block_src' can be passed as a String BeEF::Extension::DNS::DNS.instance.instance_eval do - id = @server.match(pattern, type, block) + id = @server.match(pattern, type_obj, block_src) end result = {} @@ -89,8 +100,8 @@ module DNS print_error e.message halt 400 rescue Exception => e - print_error 'Invalid JSON input passed to endpoint /api/dns/rule' - halt 400 + print_error "Internal error while adding DNS rule (#{e.message})" + halt 500 end end @@ -110,6 +121,78 @@ module DNS end end + private + + # Generates a formatted string representation of the callback to invoke as a response. + # + # @param [String] type resource record type (e.g. A, CNAME, NS, etc.) + # @param [Array] rdata record data to include in response + # + # @return [String] string representation of response callback + def format_response(type, rdata) + src = "proc { |t| t.respond!(%s) }" + + src % case type + when 'A' + data = { :address => rdata[0] } + "'%
s'" % data + when 'AAAA' + data = { :address => rdata[0] } + "'%s'" % data + when 'CNAME' + data = { :cname => rdata[0] } + "Resolv::DNS::Name.create('%