A heap-based buffer overflow vulnerability exists in Ivanti Avalanche prior to 6.4.3.
A message sent to Avalanche's WLAvalancheService.exe on TCP port 1777 has the following structure:
// be = big-endian
strut msg
{
preamble pre;
hp hdrpay;
};
struct preamble
{
be32 MsgSize; // size of hp + 16
be32 HdrSize; // size of hp.hdr
be32 PayloadSize; // size of hp.payload
be32 unk:24;
be32 em:8; // encryption method
};
// header + payload
struct hp
{
MuProperty hdr[]; // hdr as array of MuProperty structure(s)
// h.cmd
// - REQ_REGISTER (18)
// - RSP_REGISTER (19)
// - REQ_AUTH_DEVICE_KEY (28)
// - RSP_AUTH_DEVICE_KEY (29)
// - REQ_AUTH_AGENT_KEY (30)
// - RSP_AUTH_AGENT_KEY (31)
// - REQ_FILE_UPLOAD (10)
// - RSP_FILE_UPLOAD (11)
// - REQ_FILE_UPLOAD_CONT (12)
// - RSP_FILE_UPLOAD_CONT (13)
// - ...
MuProperty payload[]; // payload as array of MuProperty structure(s)
byte pad[]; // zero-padded to 16-byte boundary
};
struct MuProperty
{
be32 type; // property type, valid: 1-9, 100-102
be32 NameSize;
be32 ValueSize;
byte name[NameSize]; // property name
byte value[ValueSize]; // property value
// format depends on @type
// 3 - hex string
// 9 - list of decimal strings separated by ;
// 100-102 - list of tokens separated by ;
};
WLAvalancheService.exe allows upload of a large amount of file data via multiple RSP_FILE_UPLOAD / RSP_FILE_UPLOAD_CONT messages from the client. Each message carries a block of compressed file data in the 'p.parcel' property in the message payload, which is limited to a certain size as preamble.MsgSize has a maximum size (i.e., 0x200000).
The compressed and decompressed sizes of a file block are specified in the 'p.parcel.cmp' and 'p.parcel.info' properties, respectively. The last file block transferred is indicated by the 'p.eof' property set to a non-zero value.
WLAvalancheService.exe calculates the decompressed size for all file blocks by adding the decompressed size in each RSP_FILE_UPLOAD / RSP_FILE_UPLOAD_CONT message and allocates a buffer of that size to store the decompressed file data:
// WLAvalancheService.exe v6.4.2.0
[...]
.text:004C4715 foreach_file_upload_msg: ; CODE XREF: sub_4C4650+E6↓j
.text:004C4715 mov eax, [ebp+inmsg]
.text:004C4718 mov ecx, [eax+INMSG.pNext]
.text:004C471E mov [ebp+inmsg], ecx
.text:004C4721
.text:004C4721 loc_4C4721: ; CODE XREF: sub_4C4650+C3↑j
.text:004C4721 cmp [ebp+inmsg], 0
.text:004C4725 jz short loc_4C4738
.text:004C4727 mov edx, [ebp+inmsg]
.text:004C472A mov eax, [ebp+TotalDecompressedSize]
.text:004C472D add eax, [edx+INMSG.DecompressedSize] ; int32 overflow
.text:004C4733 mov [ebp+TotalDecompressedSize], eax
.text:004C4736 jmp short foreach_file_upload_msg
.text:004C4738 ; ---------------------------------------------------------------------------
.text:004C4738
.text:004C4738 loc_4C4738: ; CODE XREF: sub_4C4650+D5↑j
.text:004C4738 mov ecx, [ebp+TotalDecompressedSize]
.text:004C473B push ecx
.text:004C473C call operator new(uint)
.text:004C4741 add esp, 4
.text:004C4744 mov [ebp+var_74], eax
.text:004C4747 mov edx, [ebp+var_74]
.text:004C474A mov [ebp+pbDecompressedBuf], edx
[...]
.text:004C47E5 lea eax, [ebp+pbDecompressedMsg]
.text:004C47E8 push eax
.text:004C47E9 mov ecx, [ebp+pSession]
.text:004C47EF mov edx, [ecx+SESS.field_1BB4]
.text:004C47F5 push edx
.text:004C47F6 mov eax, [ebp+inmsg]
.text:004C47F9 push eax
.text:004C47FA mov ecx, [ebp+pSession]
.text:004C4800 call decompress_msg ; return true/false
.text:004C4805 mov byte ptr [ebp+var_64], al
.text:004C4808 mov ecx, [ebp+var_64]
.text:004C480B and ecx, 0FFh
.text:004C4811 test ecx, ecx
.text:004C4813 jz short err_4C4886
.text:004C4815 cmp [ebp+pbDecompressedMsg], 0
.text:004C4819 jz short copy_input_data
.text:004C481B mov edx, [ebp+inmsg]
.text:004C481E mov ecx, [edx+INMSG.DecompressedSize]
.text:004C4824 mov esi, [ebp+pbDecompressedMsg]
.text:004C4827 mov edi, [ebp+pbDecompressedBuf]
.text:004C482A add edi, [ebp+offset]
.text:004C482D mov eax, ecx
.text:004C482F shr ecx, 2
.text:004C4832 rep movsd ; copy decompressed data to small
.text:004C4832 ; heap buf -> heap overflow
.text:004C4834 mov ecx, eax
.text:004C4836 and ecx, 3
.text:004C4839 rep movsb
[...]
An unauthenticated remote attacker can specify a large decompressed size in multiple RSP_FILE_UPLOAD / RSP_FILE_UPLOAD_CONT messages to cause an int32 overflow in the total decompressed size for all file blocks. This can result in a heap-based buffer overflow when decompressed data is copied to a small heap-based buffer.