CVE-2022-43663
An integer conversion vulnerability exists in the SORBAx64.dll RecvPacket functionality of WellinTech KingHistorian 35.01.00.05. A specially crafted network packet can lead to a buffer overflow. An attacker can send a malicious packet to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
WellinTech KingHistorian 35.01.00.05
KingHistorian - https://www.wellintech.com/product/kinghistorian
8.1 - CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE-195 - Signed to Unsigned Conversion Error
KingHistorian is a time-series database used for ingesting and analyzing industrial control system data. KingHistorian is designed to be high performance and highly reliable for process data.
Within the RecvPacket
functionality of SORBAx64.dll, an integer conversion issue exists that can lead to a buffer overflow. The assembly related to the conversion issue can be seen below.
18002e81c // 0x18002cd50 - SORBA::TcpTransceiver::Recv
18002e81c ff5028 call qword [rax+0x28]
18002e81f 85c0 test eax, eax
18002e821 // Check if recv successfully retrieved data
18002e821 0f8566010000 jne 0x18002e98d
18002e827 // Get the first byte of data
18002e827 440fb69c24409000…movzx r11d, byte [rsp+0x9040 {stack_recvBuffer}]
18002e830 // sign extend the packet data size after the header (reported in header)
18002e830 4863c7 movsxd rax, edi
18002e833 ba01000000 mov edx, 0x1
18002e838 48014328 add qword [rbx+0x28 {SORBA::TransceiverInputStream::m_nRecvLength}], rax {SORBA::TransceiverInputStream::m_nRecvLength}
18002e83c 410fb6c3 movzx eax, r11b
18002e840 41b904000000 mov r9d, 0x4
18002e846 2402 and al, 0x2
18002e848 3c02 cmp al, 0x2 [1]
18002e84a // First byte of recv buffer has 2 bit set
18002e84a 410f44d1 cmove edx, r9d {0x4} [2]
18002e84e 8d42ff lea eax, [rdx-0x1]
18002e851 83f803 cmp eax, 0x3
18002e854 770a ja 0x18002e860
18002e856 // offset into packet to find length
18002e856 448b841441900000 mov r8d, dword [rsp+rdx+0x9041 {var_fa17}]
18002e85e eb03 jmp 0x18002e863
18002e863 418bc9 mov ecx, r9d {0x4}
18002e866 bfffffffff mov edi, 0xffffffff
18002e86b 2bca sub ecx, edx // rcx = 0
18002e86d 8bef mov ebp, edi {0xffffffff}
18002e86f c1e103 shl ecx, 0x3 // rcx = 0
18002e872 d3ed shr ebp, cl // rbp = 0xFFFF_FFFF
18002e874 // rbp = packet_data & 0xFFFFFFFF (so no change to packet data)
18002e874 4123e8 and ebp, r8d
18002e877 81fdecf90000 cmp ebp, 0xf9ec [3]
18002e87d // signed comparison of extracted length
18002e87d // This is an issue because this guard is here to protect lengths too large to
18002e87d // fit in the buffer
18002e87d 0f8f14ffffff jg 0x18002e797
...
18002e8b3 442bca sub r9d, edx [4]
18002e8b6 418bc4 mov eax, r12d
18002e8b9 418bc9 mov ecx, r9d
18002e8bc c1e103 shl ecx, 0x3
18002e8bf 48d3ef shr rdi, cl
18002e8c2 4823f8 and rdi, rax
18002e8c5 41f6c301 test r11b, 0x1 [5]
18002e8c9 7422 je 0x18002e8ed
...
18002e8ed 8d441201 lea eax, [rdx+rdx+0x1]
18002e8f1 4c8bc7 mov r8, rdi
18002e8f4 4863c8 movsxd rcx, eax
18002e8f7 488d940c40900000 lea rdx, [rsp+rcx+0x9040] {var_18a58}
18002e8ff 498bca mov rcx, r10
18002e902 e82f150000 call memcpy [6]
At [1]
a flag is extracted from the received packet that is used to determine how large the size field is later in the packet: if the second bit is set in the first byte, then the size field is 4 bytes, which is seen at [2]
. Using this size field, some shifting is done to properly extract the size field from the packet for all possible values (only 1 or 4 in this code base). The main issue occurs at [3]
, where the size is extracted by AND’ing the packet data with 0xFFFFFFFF. If the packet data contains a value greater than 0x80000000, then the signed comparison will pass. It is then used to determine if the allocated stack buffer is large enough to hold all the data. The buffer is statically sized at 0xfa00 bytes. At [4]
and [5]
the same feature extraction is used to grab the size field again, but at [5]
a different flag is checked, this one corresponding to if the payload is compressed or not. Regardless of if the packet is compressed, a multitude of bugs will occur. One such instance is at [6]
, where the extracted value is used directly as the size of memcpy
, which can result in a buffer overflow.
2022-12-16 - Initial Vendor Contact
2022-12-22 - Vendor Disclosure
2022-12-22 - Initial Vendor Contact
2023-03-17 - Vendor Patch Release
2023-03-20 - Public Release
Discovered by Carl Hurd of Cisco Talos.