metasploit-framework/modules/auxiliary/server/ldap.rb

116 lines
4.1 KiB
Ruby

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::LDAP::Server
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Native LDAP Server (Example)',
'Description' => %q{
This module provides a Rex based LDAP service to expose the
native Rex LDAP server functionality created during log4shell
development.
},
'Author' => [
'RageLtMan <rageltman[at]sempervictus>', # infrastructure
'Spencer McIntyre' # syntactically sane/correct Ruby LDAP object actions from early effort on l4j2 scanner
],
'License' => MSF_LICENSE,
'References' => [],
'Actions' => [
[ 'Service', { 'Description' => 'Run LDAP server' } ]
],
'PassiveActions' => [
'Service'
],
'DefaultAction' => 'Service',
'Notes' => {
'Stability' => [],
'Reliability' => [],
'SideEffects' => []
}
)
)
end
#
# Wrapper for service execution
#
def run
start_service
service.wait
rescue Rex::BindFailed => e
print_error "Failed to bind to port #{datastore['SRVPORT']}: #{e.message}"
end
#
# Creates Proc to handle incoming requests
#
def on_dispatch_request(client, data)
return if data.strip.empty?
data.extend(Net::BER::Extensions::String)
begin
pdu = Net::LDAP::PDU.new(data.read_ber!(Net::LDAP::AsnSyntax))
vprint_status("LDAP request data remaining: #{data}") if !data.empty?
resp = case pdu.app_tag
when Net::LDAP::PDU::BindRequest # bind request
# vprint_good("Received LDAP bind request from #{client} - #{pp pdu}")
client.authenticated = true
service.encode_ldap_response(
pdu.message_id,
Net::LDAP::ResultCodeSuccess,
'',
'',
Net::LDAP::PDU::BindResult
)
when Net::LDAP::PDU::SearchRequest # search request
if client.authenticated || datastore['LDAP_AUTH_BYPASS']
# Perform query against some loaded LDIF structure
filter = Net::LDAP::Filter.parse_ldap_filter(pdu.search_parameters[:filter])
attrs = pdu.search_parameters[:attributes].empty? ? :all : pdu.search_parameters[:attributes]
res = service.search_ldif(filter, pdu.message_id, attrs)
if res.nil? || res.empty?
service.encode_ldap_response(
pdu.message_id,
Net::LDAP::ResultCodeNoSuchObject, '',
Net::LDAP::ResultStrings[Net::LDAP::ResultCodeNoSuchObject],
Net::LDAP::PDU::SearchResult
)
else
# Send the results and return success message for callback completion
client.write(res.join)
service.encode_ldap_response(
pdu.message_id,
Net::LDAP::ResultCodeSuccess, '',
Net::LDAP::ResultStrings[Net::LDAP::ResultCodeSuccess],
Net::LDAP::PDU::SearchResult
)
end
else
service.encode_ldap_response(pdu.message_id, 50, '', 'Not authenticated', Net::LDAP::PDU::SearchResult)
end
else
# vprint_status("Received unknown LDAP request from #{client} - #{pp pdu}")
service.encode_ldap_response(
pdu.message_id,
Net::LDAP::ResultCodeUnwillingToPerform,
'',
Net::LDAP::ResultStrings[Net::LDAP::ResultCodeUnwillingToPerform],
Net::LDAP::PDU::SearchResult
)
end
resp.nil? ? client.close : on_send_response(client, resp)
rescue StandardError => e
print_error("Failed to handle LDAP request due to #{e}")
client.close
end
end
end