Module: Msf::Exploit::Remote::Kerberos::Client::Pac

Included in:
Msf::Exploit::Remote::Kerberos::Client
Defined in:
lib/msf/core/exploit/remote/kerberos/client/pac.rb

Instance Method Summary collapse

Instance Method Details

#build_empty_auth_dataObject



180
181
182
183
184
185
186
187
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 180

def build_empty_auth_data
  pac_auth_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
    elements: [{ type: Rex::Proto::Kerberos::Pac::AD_WIN2K_PAC, data: "\x00" }]
  )
  Rex::Proto::Kerberos::Model::AuthorizationData.new(
    elements: [{ type: Rex::Proto::Kerberos::Model::AuthorizationDataType::AD_IF_RELEVANT, data: pac_auth_data.encode }]
  )
end

#build_pa_pac_request(opts = {}) ⇒ Rex::Proto::Kerberos::Model::Field::PreAuthDataEntry

Builds a kerberos PA-PAC-REQUEST pre authenticated structure

Parameters:

  • opts (Hash{Symbol => Boolean}) (defaults to: {})

Options Hash (opts):

  • :pac_request_value (Boolean)

Returns:

  • (Rex::Proto::Kerberos::Model::Field::PreAuthDataEntry)

See Also:



18
19
20
21
22
23
24
25
26
27
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 18

def build_pa_pac_request(opts = {})
  value = opts[:pac_request_value] || false
  pac_request = Rex::Proto::Kerberos::Model::PreAuthPacRequest.new(value: value)
  pa_pac_request = Rex::Proto::Kerberos::Model::PreAuthDataEntry.new(
    type: Rex::Proto::Kerberos::Model::PreAuthType::PA_PAC_REQUEST,
    value: pac_request.encode
  )

  pa_pac_request
end

#build_pac(opts = {}) ⇒ Rex::Proto::Kerberos::Pac::Krb5Pac

Builds a kerberos PACTYPE structure

Parameters:

  • opts (Hash{Symbol => <String, Integer, Array, Time>}) (defaults to: {})
  • opts[String] (Hash)

    a customizable set of options

  • opts[Boolean] (Hash)

    a customizable set of options

Options Hash (opts):

  • :client_name (String)
  • :user_id (Integer)

    the user SID Ex: 1000

  • :group_id (Integer)

    Ex: 513 for 'Domain Users'

  • :group_ids (Array<Integer>)
  • :extra_sids (Array<String>)

    An array of extra sids, Ex: `['S-1-5-etc-etc-519']`

  • :realm (String)
  • :domain_id (String)

    the domain SID Ex: S-1-5-21-1755879683-3641577184-3486455962

  • :auth_time (Time)

Returns:

See Also:



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
127
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
156
157
158
159
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 48

def build_pac(opts = {})
  user_name = opts[:client_name] || ''
  user_id = opts[:user_id] || Rex::Proto::Kerberos::Pac::DEFAULT_ADMIN_RID
  primary_group_id = opts[:group_id] || Rex::Proto::Kerberos::Pac::DOMAIN_USERS
  group_ids = opts[:group_ids] || [Rex::Proto::Kerberos::Pac::DOMAIN_USERS]
  extra_sids = opts[:extra_sids] || []
  logon_domain_name = opts[:logon_domain_name] || opts[:realm] || ''
  logon_count = opts.fetch(:logon_count) { 0 }
  password_last_set = opts.fetch(:password_last_set) { nil }
  domain_id = opts[:domain_id] || Rex::Proto::Kerberos::Pac::NT_AUTHORITY_SID
  auth_time = opts[:auth_time] || Time.now
  checksum_type = opts[:checksum_type] || Rex::Proto::Kerberos::Crypto::Checksum::RSA_MD5
  ticket_checksum = opts[:ticket_checksum] || nil
  is_golden = opts.fetch(:is_golden) { true }
  base_vi = opts[:base_verification_info]
  upn_dns_info_pac_element = opts[:upn_dns_info_pac_element]

  obj_opts = {
    logon_time: auth_time,
    effective_name: user_name,
    user_id: user_id,
    primary_group_id: primary_group_id,
    logon_domain_name: logon_domain_name,
    logon_domain_id: domain_id,
    logon_count: logon_count,
    full_name: '',
    logon_script: '',
    profile_path: '',
    home_directory: '',
    home_directory_drive: '',
    logon_server: '',
    password_last_set: password_last_set
  }
  unless base_vi.nil?
    obj_opts.merge({
      full_name: base_vi.full_name,
      logon_script: base_vi.logon_script,
      profile_path: base_vi.profile_path,
      home_directory: base_vi.home_directory,
      home_directory_drive: base_vi.home_directory_drive,
      logon_server: base_vi.logon_server,
      logon_count: base_vi.logon_count,
      bad_password_count: base_vi.bad_password_count,
      user_account_control: base_vi.,
      sub_auth_status: base_vi.sub_auth_status,
      last_successful_i_logon: base_vi.last_successful_i_logon,
      last_failed_i_logon: base_vi.last_failed_i_logon,
      failed_i_logon_count: base_vi.failed_i_logon_count
    })
  end

  validation_info = Rex::Proto::Kerberos::Pac::Krb5ValidationInfo.new(**obj_opts)
  validation_info.group_ids = group_ids
  if extra_sids && extra_sids.length > 0
    validation_info.extra_sids = extra_sids.map do |sid|
      { sid: sid, attributes: Rex::Proto::Kerberos::Pac::SE_GROUP_ALL }
    end
  end

  logon_info = Rex::Proto::Kerberos::Pac::Krb5LogonInformation.new(
    data: validation_info
  )

  client_info = Rex::Proto::Kerberos::Pac::Krb5ClientInfo.new(
    client_id: auth_time,
    name: user_name
  )

  if is_golden
    pac_requestor = Rex::Proto::Kerberos::Pac::Krb5PacRequestor.new(
      user_sid: "#{domain_id}-#{user_id}"
    )

    pac_attributes = Rex::Proto::Kerberos::Pac::Krb5PacAttributes.new
  end

  server_checksum = Rex::Proto::Kerberos::Pac::Krb5PacServerChecksum.new(
    signature_type: checksum_type
  )

  priv_srv_checksum = Rex::Proto::Kerberos::Pac::Krb5PacPrivServerChecksum.new(
    signature_type: checksum_type
  )

  pac_elements = [
    logon_info,
    client_info
  ]

  unless upn_dns_info_pac_element.nil?
    pac_elements.append(upn_dns_info_pac_element)
  end

  if is_golden
    # These PAC elements are required for golden tickets in post-October 2022 systems
    pac_elements.append(
      pac_requestor,
      pac_attributes
      )
  end

  pac_elements.append(
      server_checksum,
      priv_srv_checksum
  )
  pac_elements << ticket_checksum unless ticket_checksum.nil?

  pac_type = Rex::Proto::Kerberos::Pac::Krb5Pac.new
  pac_type.assign(pac_elements: pac_elements)
  pac_type.sign!(service_key: opts[:checksum_enc_key])
  pac_type
end

#build_pac_authorization_data(opts = {}) ⇒ Rex::Proto::Kerberos::Model::AuthorizationData

Builds an kerberos AuthorizationData structure containing a PACTYPE

Parameters:

  • opts (Hash{Symbol => Rex::Proto::Kerberos::Pac::Type}) (defaults to: {})

Options Hash (opts):

  • :pac (Rex::Proto::Kerberos::Pac::Type)

Returns:

See Also:



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 167

def build_pac_authorization_data(opts = {})
  pac = opts[:pac] || build_pac(opts)

  pac_auth_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
    elements: [{ type: Rex::Proto::Kerberos::Pac::AD_WIN2K_PAC, data: pac.to_binary_s}]
  )
  authorization_data = Rex::Proto::Kerberos::Model::AuthorizationData.new(
    elements: [{ type: Rex::Proto::Kerberos::Model::AuthorizationDataType::AD_IF_RELEVANT, data: pac_auth_data.encode }]
  )

  authorization_data
end