Facebook Google Plus Twitter LinkedIn YouTube RSS Menu Search Resource - BlogResource - WebinarResource - ReportResource - Eventicons_066 icons_067icons_068icons_069icons_070

Schneider Electric IGSS Data Server Multiple Vulnerabilities

Critical

Synopsis

Tenable discovered multiple vulnerabilities in Schneider Electric IGSS Data Server (IGSSdataServer.exe)

1) Opcode 1 (LOG) appendRequest Out-of-bounds Write

IGSSdataServer limits an incoming request packet to 0x1000 bytes. A message with opcode 1 can be longer than 0x1000 bytes and thus needs to be sent in multiple requests. When appending the second request to the existing message data, IGSSdataServer.exe can incorrectly compute the buffer location to store the incoming request, leading to an out-of-bounds write with attacker-controlled data.

The opcode 1 message has the following format:

le = little endian
struct hdr
{
   le16 ReqSize; // total req size including this field
   le16 unk;
   le16 unk;
   le32 opcode; 
   le32 unk;
   le32 IsFinal; // is the request the final fragment in a message?
};

struct opcode_1_req
{
   hdr h;         // h.opcode must be 1
   le16 nItems;   // number of 0xC-byte items
   FILETIME ftime1;
   FILETIME ftime2;
   byte items[nItems * 0xC];    // 0xC-byte items
};


An unauthenticated remote attacker can send the first request fragment with a large opcode_1_req.nItems but only a single item in opcode_1_req.items. IGSSdataServer.exe does not check the received request indeed has nItems of data in the items field.

After receiving the first request fragment, IGSSdataServer.exe marks the current message size using the request packet size received from the wire, but it also marks the message currently having nItems (arbitrary value specified by the attacker) of data. The end result is that the current message size can be significantly less than the amount the nItems field would indicate.

When the second request arrives, the server reallocates the message buffer to store the incoming items in the request. It computes the space required to store the items in the request and adds it to the current message size:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:004A69A9    mov     eax, [ebp+arg_pbReq] ; incoming request
.text:004A69AC    movzx   ecx, [eax+LOG_REQ.nItems]
.text:004A69B0    imul    edx, ecx, 0Ch ; space required to store the items
.text:004A69B0                          ; in the incoming req
.text:004A69B3    mov     [ebp+Size], edx
.text:004A69B6    mov     eax, [ebp+ctx]
.text:004A69B9    mov     ecx, [eax+LOG_CTX.cbMsg]
.text:004A69BC    add     ecx, [ebp+Size] ; add to current msg size
.text:004A69BF    mov     edx, [ebp+ctx]
.text:004A69C2    mov     [edx+LOG_CTX.cbMsg], ecx
.text:004A69C5    mov     eax, [ebp+ctx]
.text:004A69C8    mov     ecx, [eax+LOG_CTX.cbMsg]
.text:004A69CB    push    ecx
.text:004A69CC    mov     edx, [ebp+ctx]
.text:004A69CF    mov     eax, [edx+LOG_CTX.pbMsg] ; reallocate msg buffer
.text:004A69D2    push    eax
.text:004A69D3    call    ds:realloc
<...snip...>


The server then copies the items in the second request to the now expanded message buffer at a location determined by the opcode_1_req.nItems field in the first request. It uses this field to compute the offset within the message buffer where the items in the first request would end:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:004A6A02    movzx   ecx, [edx+LOG_REQ.nItems] ; attacker-controlled -> OOB write
.text:004A6A06    imul    edx, ecx, 0Ch
.text:004A6A09    lea     eax, [eax+edx+LOG_REQ.items] ; 0xC-byte items
.text:004A6A0D    push    eax
.text:004A6A0E    call    memcpy
<...snip...>


However, this field can be set to an arbitrary large number by the attacker and can cause memcpy() to write to a location way past the end of the message buffer on the heap. This can lead to an out-of-bounds write with attacker-controlled data.

Proof of Concept: 

python3 igss_dataserver_appendRequest_oob_write.py -t <target> -p 12401 -o 1
Attempting Out-of-bounds write using opcode 1
connection 0001: items specified in req = 00002, actual items = 00001
Traceback (most recent call last):
  File "/work/0day/igss_dataserver_appendRequest_oob_write.py", line 130, in <module>
    s.connect((target, port))
ConnectionRefusedError: [Errno 111] Connection refused


Heap corruption caused by the POC:

0:008> g
Critical error detected c0000374
(27b0.8ec): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=054197d8 ecx=c0000374 edx=0092f541 esi=00000002 edi=00660000
eip=773c6ca2 esp=0092f6b0 ebp=0092f73c iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!RtlReportCriticalFailure+0x4b:
773c6ca2 cc              int     3
0:008> kb
 # ChildEBP RetAddr      Args to Child              
00 0092f73c 773cfda4     00000001 77403990 773cdc99 ntdll!RtlReportCriticalFailure+0x4b
01 0092f748 773cdc99     ded7cede 00660000 0541a7e8 ntdll!RtlpReportHeapFailure+0x2f
02 0092f778 773d6110     00000003 00660000 0541a7e8 ntdll!RtlpHpHeapHandleError+0x89
03 0092f790 7732436f     0541a7e8 00000000 00000000 ntdll!RtlpLogHeapFailure+0x43
04 0092f8f8 773678fd     054197d8 054197e0 054197e0 ntdll!RtlpFreeHeap+0x70f
05 0092f954 77323c06     00000000 00000000 00000000 ntdll!RtlpFreeHeapInternal+0x783
06 0092f970 75373c9b     00660000 00000000 054197e0 ntdll!RtlFreeHeap+0x46
07 0092f984 75373c68     054197e0 00000000 0092f9b4 ucrtbase!_free_base+0x1b
08 0092f994 005cbf75     054197e0 90206481 04915f38 ucrtbase!free+0x18
WARNING: Stack unwind information not available. Following frames may be wrong.
09 0092f9b4 005d6959     902064e9 fffffffe 0092f9f8 IGSSdataServer+0x9bf75
0a 0092f9dc 005d697f     04915f38 0092fa04 005e406b IGSSdataServer+0xa6959
0b 0092f9e8 005e406b     00000001 77137b80 04915f38 IGSSdataServer+0xa697f
0c 0092fa04 005e5921     00000000 0092fa90 005e563c IGSSdataServer+0xb406b
0d 0092fa10 005e563c     054160b0 0092fa38 00000444 IGSSdataServer+0xb5921
0e 0092fa90 75384f9f     054160b0 1e46d56d 75384f60 IGSSdataServer+0xb563c
0f 0092fac8 7583fa29     053cdb88 7583fa10 0092fb34 ucrtbase!thread_start<unsigned int (__stdcall*)(void *),1>+0x3f
10 0092fad8 77347a7e     053cdb88 ded7c292 00000000 KERNEL32!BaseThreadInitThunk+0x19
11 0092fb34 77347a4e     ffffffff 77368a44 00000000 ntdll!__RtlUserThreadStart+0x2f
12 0092fb44 00000000     75384f60 053cdb88 00000000 ntdll!_RtlUserThreadStart+0x1b

2) Opcode 2 (BCL) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 2:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:0049E132    movzx   ecx, [edx+BCL_REQ.nItems] ; attacker-controlled -> OOB write
.text:0049E136    imul    edx, ecx, 48h ; 'H'
.text:0049E139    lea     eax, [eax+edx+BCL_REQ.items] ; 0x48-byte items
.text:0049E13D    push    eax
.text:0049E13E    call    memcpy
<...snip...>


3) Opcode 5 (ONL) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 5:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:004A7602    movzx   ecx, [edx+ONL_REQ.nItems] ; attacker-controlled -> OOB write
.text:004A7606    lea     edx, [eax+ecx*8+ONL_REQ.items] ; 8-byte items
.text:004A760A    push    edx
.text:004A760B    call    memcpy
<...snip...>


4) Opcode 6 (HDM) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 6:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:004A34B6    movzx   ecx, [edx+HDM_REQ.nItems] ; attacker-controlled -> OOB write
.text:004A34BA    imul    edx, ecx, 48h ; 'H'
.text:004A34BD    lea     eax, [eax+edx+HDM_REQ.items] ; 0x48-byte items
.text:004A34C1    push    eax           ; void *
.text:004A34C2    call    memcpy
<...snip...>


5) Opcode 9 (ALM) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 9:

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:0049C292    movzx   ecx, [edx+ALM_REQ.nItems] ; attacker-controlled -> OOB write
.text:0049C296    lea     edx, [eax+ecx*8+ALM_REQ.items] ; 8-byte items
.text:0049C29A    push    edx           ; void *
.text:0049C29B    call    memcpy
<...snip...>


6) Opcode 16/20 (PUTONL) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 16 or 20 :

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:004A83C2    movzx   ecx, [edx+PUTONL_REQ.nItems] ; attacker-controlled -> OOB write
.text:004A83C6    imul    edx, ecx, 14h
.text:004A83C9    lea     eax, [eax+edx+PUTONL_REQ.items] ; 0x14-byte items
.text:004A83CD    push    eax           ; void *
.text:004A83CE    call    memcpy
<...snip...>


7) Opcode 18 (ALMCACHE) appendRequest Out-of-bounds Write

An out-of-bounds write also occurs when appending a request with opcode 18 :

IGSSdataServer.exe v15.0.0.22082
<...snip...>
.text:0049CB26    movzx   ecx, [edx+ALMCACHE_REQ.nItems] ; attacker-controlled -> OOB write
.text:0049CB2A    lea     edx, [eax+ecx*4+ALMCACHE_REQ.items] ; 4-byte items
.text:0049CB2E    push    edx           ; void *
.text:0049CB2F    call    memcpy
<...snip...>

Solution

Schneider Electric released IGSS Data Server V15.0.0.22171 which includes fixes for these vulnerabilities.

Disclosure Timeline

6 May, 2022 - Issue reported to Schneider Electric
6 May, 2022 - Schneider Electric acknowledges
17 May, 2022 - Schneider Electric confirms the issues as duplicates of issues reported (but yet to be fixed/disclosed) by another researcher
14 June, 2022 - Schneider Electric informs Tenable of released fixes and advisory
17 June, 2022 - Tenable informs Schneider Electric that the original patch (15.0.0.22140) is incomplete for opcode 20
17 June, 2022 - Schneider Electric acknowledges
20 June, 2022 - Schneider Electric confirms the patch is incomplete
22 June, 2022 - Schneider Electric notifies Tenable that a new patch is ready for release
23 June, 2022 - Schneider Electric releases new patch and a new security notification

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]

Risk Information

Tenable Advisory ID: TRA-2022-22
CVSSv3 Base / Temporal Score:
9.8
CVSSv3 Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Affected Products:
Schneider Electric IGSS Data Server < 15.0.0.22171
Risk Factor:
Critical

Advisory Timeline

15 June 2022 - Advisory Published
24 June 2022 - Advisory updated with new fixed version