Module: Msf::Exploit::Remote::MsSamr::Account

Includes:
Auxiliary::Report, Msf::Exploit::Remote::MsSamr
Defined in:
lib/msf/core/exploit/remote/ms_samr/account.rb

Defined Under Namespace

Classes: AccountInfo

Constant Summary

Constants included from SMB::Client

SMB::Client::CONST, SMB::Client::DCERPCClient, SMB::Client::DCERPCPacket, SMB::Client::DCERPCResponse, SMB::Client::DCERPCUUID, SMB::Client::NDR, SMB::Client::SIMPLE, SMB::Client::XCEPT

Instance Attribute Summary

Attributes included from SMB::Client

#simple

Attributes included from Tcp

#sock

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Msf::Exploit::Remote::MsSamr

connect_samr

Methods included from SMB::Client::Ipc

connect_ipc, disconnect_ipc

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Methods included from Kerberos::ServiceAuthenticator::Options

#kerberos_auth_options

Methods included from Kerberos::Ticket::Storage

#kerberos_storage_options, #kerberos_ticket_storage, store_ccache

Methods included from SMB::Client

#connect, #domain, #domain_username_split, #smb_create, #smb_direct, #smb_enumprinters, #smb_enumprintproviders, #smb_file_exist?, #smb_file_rm, #smb_fingerprint, #smb_fingerprint_windows_lang, #smb_fingerprint_windows_sp, #smb_hostname, #smb_lanman_netshareenumall, #smb_login, #smb_lookup_share_type, #smb_netshareenumall, #smb_netsharegetinfo, #smb_open, #smb_peer_lm, #smb_peer_os, #smb_srvsvc_netshareenumall, #smb_srvsvc_netsharegetinfo, #smbhost, #splitname, #unicode

Methods included from Tcp

#chost, #cleanup, #connect, #connect_timeout, #cport, #disconnect, #handler, #lhost, #lport, #peer, #print_prefix, #proxies, #rhost, #rport, #set_tcp_evasions, #shutdown, #ssl, #ssl_cipher, #ssl_verify_mode, #ssl_version

Class Method Details

.get_account_sid(samr_con, account_name) ⇒ Object

[View source] [View on GitHub]

182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 182

def (samr_con, )
  details = samr_con.samr.samr_lookup_names_in_domain(
    domain_handle: samr_con.domain_handle,
    names: [  ]
  )
  raise MsSamrNotFoundError, 'The account was not found.' if details.nil?

  details = details[]
  samr_con.samr.samr_rid_to_sid(
    object_handle: samr_con.domain_handle,
    rid: details[:rid]
  ).to_s
end

.random_hostname(prefix: 'DESKTOP') ⇒ Object

[View source] [View on GitHub]

178
179
180
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 178

def random_hostname(prefix: 'DESKTOP')
  "#{prefix}-#{Rex::Text.rand_base(8, '', ('A'..'Z').to_a + ('0'..'9').to_a)}$"
end

.report_creds(domain, username, password) ⇒ Object

[View source] [View on GitHub]

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 196

def report_creds(domain, username, password)
  service_data = {
    address: rhost,
    port: rport,
    service_name: 'smb',
    protocol: 'tcp',
    workspace_id: myworkspace_id
  }

  credential_data = {
    module_fullname: fullname,
    origin_type: :service,
    private_data: password,
    private_type: :password,
    username: username,
    realm_key: Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN,
    realm_value: domain
  }.merge(service_data)

  credential_core = create_credential(credential_data)

   = {
    core: credential_core,
    status: Metasploit::Model::Login::Status::UNTRIED
  }.merge(service_data)

  ()
end

Instance Method Details

#add_account(account_type, opts = {}) ⇒ Object

Add a new account (computer or user)

Parameters:

  • account_type (Symbol)

    The type (:computer or :user) of account to create

[View source] [View on GitHub]

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 48

def (, opts = {})
  raise MsSamrBadConfigError, 'Must specify computer or user account' unless [:computer, :user].include?()

  tree = opts[:tree] || connect_ipc

  samr_con = connect_samr(tree)

   = opts[:account_name] || datastore['ACCOUNT_NAME']
  if .blank?
    if  == :computer
       = generate_unused_computer_name(samr_con)
    else
      raise MsSamrBadConfigError, 'Must provide a user name'
    end
  else
    validate_name_doesnt_exist(samr_con, )
  end

   = opts[:account_password] || datastore['ACCOUNT_PASSWORD']
  if .blank?
     = Rex::Text.rand_text_alphanumeric(32)
  end

  uac =  == :computer ? RubySMB::Dcerpc::Samr::USER_WORKSTATION_TRUST_ACCOUNT : RubySMB::Dcerpc::Samr::USER_NORMAL_ACCOUNT

  result = samr_con.samr.samr_create_user2_in_domain(
    domain_handle: samr_con.domain_handle,
    name: ,
    account_type: uac,
    desired_access: RubySMB::Dcerpc::Samr::USER_FORCE_PASSWORD_CHANGE | RubySMB::Dcerpc::Samr::MAXIMUM_ALLOWED
  )

  user_handle = result[:user_handle]
  password_expired = ( == :computer) ? 1 : 0
   = RubySMB::Dcerpc::Samr::SamprUserInfoBuffer.new(
    tag: RubySMB::Dcerpc::Samr::USER_INTERNAL4_INFORMATION_NEW,
    member: RubySMB::Dcerpc::Samr::SamprUserInternal4InformationNew.new(
      i1: {
        password_expired: password_expired,
        which_fields: RubySMB::Dcerpc::Samr::USER_ALL_NTPASSWORDPRESENT | RubySMB::Dcerpc::Samr::USER_ALL_PASSWORDEXPIRED,
      },
      user_password: {
        buffer: RubySMB::Dcerpc::Samr::SamprEncryptedUserPasswordNew.encrypt_password(
          ,
          @simple.client.application_key
        )
      }
    )
  )
  samr_con.samr.samr_set_information_user2(
    user_handle: user_handle,
    user_info: 
  )

   = RubySMB::Dcerpc::Samr::SamprUserInfoBuffer.new(
    tag: RubySMB::Dcerpc::Samr::USER_CONTROL_INFORMATION,
    member: RubySMB::Dcerpc::Samr::UserControlInformation.new(
      user_account_control: uac
    )
  )
  samr_con.samr.samr_set_information_user2(
    user_handle: user_handle,
    user_info: 
  )
  print_good("Successfully created #{samr_con.domain_name}\\#{}")
  print_good("  Password: #{}")
  print_good("  SID:      #{(samr_con, )}")
  report_creds(samr_con.domain_name, , )

  AccountInfo.new(, )
rescue RubySMB::Dcerpc::Error::SamrError => e
  raise MsSamrUnknownError, "A DCERPC SAMR error occurred: #{e.message}"
ensure
  if samr_con
    samr_con.samr.close_handle(user_handle) if user_handle
    samr_con.samr.close_handle(samr_con.domain_handle) if samr_con.domain_handle
    samr_con.samr.close_handle(samr_con.server_handle) if samr_con.server_handle
  end
end

#delete_account(opts = {}) ⇒ Object

[View source] [View on GitHub]

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 128

def (opts = {})
  tree = opts[:tree] || connect_ipc

  samr_con = connect_samr(tree)

   = opts[:account_name] || datastore['ACCOUNT_NAME']
  if .blank?
    raise MsSamrBadConfigError, 'Unable to delete the account since its name is unknown'
  end

  details = samr_con.samr.samr_lookup_names_in_domain(domain_handle: samr_con.domain_handle, names: [  ])
  raise MsSamrBadConfigError, 'The specified account was not found.' if details.nil?
  details = details[]

  user_handle = samr_con.samr.samr_open_user(domain_handle: samr_con.domain_handle, user_id: details[:rid])
  samr_con.samr.samr_delete_user(user_handle: user_handle)
  print_good('The specified account has been deleted.')
rescue RubySMB::Dcerpc::Error::SamrError => e
  # `user_handle` only needs to be closed if an error occurs in `samr_delete_user`
  # If this method succeed, the server took care of closing the handle
  samr_con.samr.close_handle(user_handle) if user_handle
  raise MsSamrUnknownError, "Could not delete the account #{}: #{e.message}"
ensure
  if samr_con
    samr_con.samr.close_handle(samr_con.domain_handle) if samr_con.domain_handle
    samr_con.samr.close_handle(samr_con.server_handle) if samr_con.server_handle
  end
end

#generate_unused_computer_name(samr_con) ⇒ Object

[View source] [View on GitHub]

25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 25

def generate_unused_computer_name(samr_con)
  computer_name = random_hostname
  4.downto(0) do |attempt|
    break if samr_con.samr.samr_lookup_names_in_domain(
      domain_handle: samr_con.domain_handle,
      names: [ computer_name ]
    ).nil?

    computer_name = random_hostname
    raise MsSamrBadConfigError, 'Could not find an unused computer name.' if attempt == 0
  end

  computer_name
end

#initialize(info = {}) ⇒ Object

[View source] [View on GitHub]

16
17
18
19
20
21
22
23
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 16

def initialize(info = {})
  super

  register_options([
    OptString.new('ACCOUNT_NAME', [ false, 'The account name' ]),
    OptString.new('ACCOUNT_PASSWORD', [ false, 'The password for the new account' ]),
  ], Msf::Exploit::Remote::MsSamr)
end

#lookup_account(opts = {}) ⇒ Object

[View source] [View on GitHub]

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 157

def (opts = {})
  tree = opts[:tree] || connect_ipc

  samr_con = connect_samr(tree)

   = opts[:account_name] || datastore['ACCOUNT_NAME']
  if .blank?
    raise MsSamrBadConfigError, 'Unable to lookup the account since its name is unknown'
  end

  sid = (samr_con, )
  print_good("Found #{samr_con.domain_name}\\#{} (SID: #{sid})")
ensure
  if samr_con
    samr_con.samr.close_handle(samr_con.domain_handle) if samr_con.domain_handle
    samr_con.samr.close_handle(samr_con.server_handle) if samr_con.server_handle
  end
end

#validate_name_doesnt_exist(samr_con, name) ⇒ Object

[View source] [View on GitHub]

40
41
42
43
44
# File 'lib/msf/core/exploit/remote/ms_samr/account.rb', line 40

def validate_name_doesnt_exist(samr_con, name)
  if samr_con.samr.samr_lookup_names_in_domain(domain_handle: samr_con.domain_handle, names: [ name ])
    raise MsSamrBadConfigError, 'The specified name already exists.'
  end
end