CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/gss/kerberos/message_encryptor.rb
Views: 11766
1
module Rex
2
module Proto
3
module Gss
4
module Kerberos
5
#
6
# Encrypt messages according to RFC4121 (Kerberos with GSS)
7
# Performs wrapping of tokens in the GSS structure, filler bytes, rotation
8
# and sequence number tracking and verification.
9
#
10
class MessageEncryptor
11
12
# @param [Rex::Proto::Kerberos::Model::EncryptionKey] key The encryption key used to perform encryption and decryption
13
# @param [Integer] encrypt_sequence_number The starting sequence number used to encrypt messages
14
# @param [Integer] decrypt_sequence_number The starting sequence number we expect to see when we decrypt messages
15
# @param [Boolean] is_initiator Are we the initiator in this communication (used for setting flags and key usage values)
16
# @param [Boolean] use_acceptor_subkey Are we using the subkey provided by the acceptor? (used for setting appropriate flags)
17
# @param [Boolean] dce_style Is the format of the encrypted blob DCE-style?
18
def initialize(key, encrypt_sequence_number, decrypt_sequence_number, is_initiator: true, use_acceptor_subkey: true, dce_style: false, rc4_pad_style: :single_byte)
19
@key = key
20
@encrypt_sequence_number = encrypt_sequence_number
21
@decrypt_sequence_number = decrypt_sequence_number
22
@is_initiator = is_initiator
23
@use_acceptor_subkey = use_acceptor_subkey
24
@dce_style = dce_style
25
@rc4_pad_style = rc4_pad_style
26
@encryptor = Rex::Proto::Kerberos::Crypto::Encryption::from_etype(key.type)
27
end
28
29
#
30
# Encrypt the message, wrapping it in GSS structures, and increment the sequence number
31
# @return [String, Integer, Integer] The encrypted data, the length of its header, and the length of padding added to it prior to encryption
32
#
33
def encrypt_and_increment(data)
34
result = encryptor.gss_wrap(data, @key, @encrypt_sequence_number, @is_initiator, use_acceptor_subkey: @use_acceptor_subkey, dce_style: @dce_style, rc4_pad_style: @rc4_pad_style)
35
@encrypt_sequence_number += 1
36
37
result
38
end
39
40
#
41
# Decrypt a ciphertext, and verify its validity
42
#
43
def decrypt_and_verify(data)
44
result = encryptor.gss_unwrap(data, @key, @decrypt_sequence_number, @is_initiator, use_acceptor_subkey: @use_acceptor_subkey)
45
@decrypt_sequence_number += 1 unless @decrypt_sequence_number.nil?
46
47
result
48
end
49
50
def calculate_encrypted_length(plaintext_len)
51
encryptor.calculate_encrypted_length(plaintext_len)
52
end
53
54
#
55
# The sequence number to use when we are encrypting, which should be incremented for each message
56
#
57
attr_accessor :encrypt_sequence_number
58
59
#
60
# The sequence number we expect to see after decrypting, which is expected to be incremented for each message
61
#
62
attr_accessor :decrypt_sequence_number
63
64
#
65
# [Rex::Proto::Kerberos::Model::EncryptionKey] The encryption key to use for encryption and decryption
66
#
67
attr_accessor :key
68
69
#
70
# Are we (the encryptor) also the initiator in this interaction (vs being the Acceptor)
71
# This refers to the term used in RFC2743/RFC4121
72
#
73
attr_accessor :is_initiator
74
75
#
76
# [Boolean] Whether the acceptor subkey is used for these operations
77
#
78
attr_accessor :use_acceptor_subkey
79
80
#
81
# [Boolean] Whether this encryptor will be used for DCERPC purposes (since the behaviour is subtly different)
82
# See MS-KILE 3.4.5.4.1 for details about the exception to the rule:
83
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/e94b3acd-8415-4d0d-9786-749d0c39d550
84
#
85
# "For [MS-RPCE], the length field in the above pseudo ASN.1 header does not include the length of the concatenated data if [RFC1964] is used."
86
#
87
attr_accessor :dce_style
88
89
#
90
# [Symbol] The RC4 spec (RFC4757) section 7.3 implies that RC4-HMAC only needs one byte of padding,
91
# although it doesn't come straight out and say it. Some protocols (LDAP, at least on a DC) complain
92
# if you give it more than a single byte of paddding.
93
# Other protocols (DRSR) complain if you don't align it perfectly with an 8-byte boundary.
94
# The MS-RPCE spec is a little vague on why exactly that might be, but we can at least
95
# show empirically that it is happy if you just give it an 8-byte aligned encrypted stub.
96
# Yet other protocols are happy whatever the padding (WinRM).
97
# Here, we allow customising the behaviour of the RC4-HMAC GSSAPI crypto scheme by providing either:
98
# - :single_byte -> Puts a single '\x01' byte of padding at the end
99
# - :eight_byte_aligned -> Puts between 1 and 8 bytes of PKCS#5 padding
100
attr_accessor :rc4_pad_style
101
102
#
103
# [Rex::Proto::Kerberos::Crypto::*] Encryption class for encrypting/decrypting messages
104
#
105
attr_accessor :encryptor
106
end
107
end
108
end
109
end
110
end
111
112