CVE-2023-27772 (published 2023-04-13T18:15Z)

libiec61850 v1.5.1 was discovered to contain a segmentation violation via the function ControlObjectClient_setOrigin() at /client/client_control.c.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-754
cwe_name: Improper Check for Unusual or Exceptional Conditions
description: The product does not check or incorrectly checks for unusual or exceptional conditions that are not expected to occur frequently during day to day operation of the product.
extended_description: 
            The programmer may assume that certain events or conditions will never occur or do not need to be worried about, such as low memory conditions, lack of access to resources due to restrictive permissions, or misbehaving clients or components. However, attackers may intentionally trigger these unusual conditions, thus violating the programmer's assumptions, possibly introducing instability, incorrect behavior, or a vulnerability.
            Note that this entry is not exclusively about the use of exceptions and exception handling, which are mechanisms for both checking and handling unusual or unexpected conditions.
         
         

Fix information:
repo_url: https://github.com/mz-automation/libiec61850
commit_details: repo_url: https://github.com/mz-automation/libiec61850
author: Michael Zillgith
author_date: 2023-02-24 11:07:09+00:00
msg: - added missing checks in iec61850_client_example_control (#442)
repository: repo_url: https://github.com/mz-automation/libiec61850
repo_name: mz-automation/libiec61850
description: Official repository for libIEC61850, the open-source library for the IEC 61850 protocols
repo_language: C
owner: mz-automation
file_changes: filename: client_example_control.c
change_type: ModificationType.MODIFY
diff: @@ -45,8 +45,10 @@ int main(int argc, char** argv) {
 
     IedConnection_connect(con, &error, hostname, tcpPort);
 
-    if (error == IED_ERROR_OK) {
-
+    if (error == IED_ERROR_OK)
+    {
+        MmsValue* ctlVal = NULL;
+        MmsValue* stVal = NULL;
 
         /************************
          * Direct control
@@ -55,99 +57,116 @@ int main(int argc, char** argv) {
         ControlObjectClient control
             = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO1", con);
 
-        MmsValue* ctlVal = MmsValue_newBoolean(true);
+        if (control)
+        {
+            ctlVal = MmsValue_newBoolean(true);
 
-        ControlObjectClient_setOrigin(control, NULL, 3);
+            ControlObjectClient_setOrigin(control, NULL, 3);
 
-        if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
-            printf("simpleIOGenericIO/GGIO1.SPCSO1 operated successfully\n");
-        }
-        else {
-            printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO1\n");
-        }
+            if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
+                printf("simpleIOGenericIO/GGIO1.SPCSO1 operated successfully\n");
+            }
+            else {
+                printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO1\n");
+            }
+
+            MmsValue_delete(ctlVal);
 
-        MmsValue_delete(ctlVal);
+            ControlObjectClient_destroy(control);
 
-        ControlObjectClient_destroy(control);
+            /* Check if status value has changed */
 
-        /* Check if status value has changed */
+            stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO1.stVal", IEC61850_FC_ST);
 
-        MmsValue* stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO1.stVal", IEC61850_FC_ST);
+            if (error == IED_ERROR_OK) {
+                bool state = MmsValue_getBoolean(stVal);
+                MmsValue_delete(stVal);
 
-        if (error == IED_ERROR_OK) {
-            bool state = MmsValue_getBoolean(stVal);
-            MmsValue_delete(stVal);
+                printf("New status of simpleIOGenericIO/GGIO1.SPCSO1.stVal: %i\n", state);
+            }
+            else {
+                printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO1 failed!\n");
+            }
 
-            printf("New status of simpleIOGenericIO/GGIO1.SPCSO1.stVal: %i\n", state);
         }
         else {
-            printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO1 failed!\n");
+            printf("Control object simpleIOGenericIO/GGIO1.SPCSO1 not found in server\n");
         }
 
-
         /************************
          * Select before operate
          ***********************/
 
         control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO2", con);
 
-        if (ControlObjectClient_select(control)) {
+        if (control)
+        {
+            if (ControlObjectClient_select(control)) {
 
-            ctlVal = MmsValue_newBoolean(true);
+                ctlVal = MmsValue_newBoolean(true);
 
-            if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
-                printf("simpleIOGenericIO/GGIO1.SPCSO2 operated successfully\n");
+                if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
+                    printf("simpleIOGenericIO/GGIO1.SPCSO2 operated successfully\n");
+                }
+                else {
+                    printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO2!\n");
+                }
+
+                MmsValue_delete(ctlVal);
             }
             else {
-                printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO2!\n");
+                printf("failed to select simpleIOGenericIO/GGIO1.SPCSO2!\n");
             }
 
-            MmsValue_delete(ctlVal);
+            ControlObjectClient_destroy(control);
         }
         else {
-            printf("failed to select simpleIOGenericIO/GGIO1.SPCSO2!\n");
+            printf("Control object simpleIOGenericIO/GGIO1.SPCSO2 not found in server\n");
         }
 
-        ControlObjectClient_destroy(control);
-
-
         /****************************************
          * Direct control with enhanced security
          ****************************************/
 
         control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO3", con);
 
-        ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
+        if (control)
+        {
+            ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
 
-        ctlVal = MmsValue_newBoolean(true);
+            ctlVal = MmsValue_newBoolean(true);
 
-        if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
-            printf("simpleIOGenericIO/GGIO1.SPCSO3 operated successfully\n");
-        }
-        else {
-            printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO3\n");
-        }
+            if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
+                printf("simpleIOGenericIO/GGIO1.SPCSO3 operated successfully\n");
+            }
+            else {
+                printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO3\n");
+            }
 
-        MmsValue_delete(ctlVal);
+            MmsValue_delete(ctlVal);
 
-        /* Wait for command termination message */
-        Thread_sleep(1000);
+            /* Wait for command termination message */
+            Thread_sleep(1000);
 
-        ControlObjectClient_destroy(control);
+            ControlObjectClient_destroy(control);
 
-        /* Check if status value has changed */
+            /* Check if status value has changed */
 
-       stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO3.stVal", IEC61850_FC_ST);
+            stVal = IedConnection_readObject(con, &error, "simpleIOGenericIO/GGIO1.SPCSO3.stVal", IEC61850_FC_ST);
 
-        if (error == IED_ERROR_OK) {
-            bool state = MmsValue_getBoolean(stVal);
+            if (error == IED_ERROR_OK) {
+                bool state = MmsValue_getBoolean(stVal);
 
-            printf("New status of simpleIOGenericIO/GGIO1.SPCSO3.stVal: %i\n", state);
+                printf("New status of simpleIOGenericIO/GGIO1.SPCSO3.stVal: %i\n", state);
 
-            MmsValue_delete(stVal);
+                MmsValue_delete(stVal);
+            }
+            else {
+                printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO3 failed!\n");
+            }
         }
         else {
-            printf("Reading status for simpleIOGenericIO/GGIO1.SPCSO3 failed!\n");
+            printf("Control object simpleIOGenericIO/GGIO1.SPCSO3 not found in server\n");
         }
 
         /***********************************************
@@ -156,56 +175,66 @@ int main(int argc, char** argv) {
 
         control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO4", con);
 
-        ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
+        if (control)
+        {
+            ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
 
-        ctlVal = MmsValue_newBoolean(true);
+            ctlVal = MmsValue_newBoolean(true);
 
-        if (ControlObjectClient_selectWithValue(control, ctlVal)) {
+            if (ControlObjectClient_selectWithValue(control, ctlVal)) {
+
+                if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
+                    printf("simpleIOGenericIO/GGIO1.SPCSO4 operated successfully\n");
+                }
+                else {
+                    printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO4!\n");
+                }
 
-            if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
-                printf("simpleIOGenericIO/GGIO1.SPCSO4 operated successfully\n");
             }
             else {
-                printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO4!\n");
+                printf("failed to select simpleIOGenericIO/GGIO1.SPCSO4!\n");
             }
 
+            MmsValue_delete(ctlVal);
+
+            /* Wait for command termination message */
+            Thread_sleep(1000);
+
+            ControlObjectClient_destroy(control);
         }
         else {
-            printf("failed to select simpleIOGenericIO/GGIO1.SPCSO4!\n");
+            printf("Control object simpleIOGenericIO/GGIO1.SPCSO4 not found in server\n");
         }
 
-        MmsValue_delete(ctlVal);
-
-        /* Wait for command termination message */
-        Thread_sleep(1000);
-
-        ControlObjectClient_destroy(control);
-
-
         /*********************************************************************
          * Direct control with enhanced security (expect CommandTermination-)
          *********************************************************************/
 
         control = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO9", con);
 
-        ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
-
-        ctlVal = MmsValue_newBoolean(true);
+        if (control)
+        {
+            ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);
 
-        if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
-            printf("simpleIOGenericIO/GGIO1.SPCSO9 operated successfully\n");
-        }
-        else {
-            printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO9\n");
-        }
+            ctlVal = MmsValue_newBoolean(true);
 
-        MmsValue_delete(ctlVal);
+            if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
+                printf("simpleIOGenericIO/GGIO1.SPCSO9 operated successfully\n");
+            }
+            else {
+                printf("failed to operate simpleIOGenericIO/GGIO1.SPCSO9\n");
+            }
 
-        /* Wait for command termination message */
-        Thread_sleep(1000);
+            MmsValue_delete(ctlVal);
 
-        ControlObjectClient_destroy(control);
+            /* Wait for command termination message */
+            Thread_sleep(1000);
 
+            ControlObjectClient_destroy(control);
+        }
+        else {
+            printf("Control object simpleIOGenericIO/GGIO1.SPCSO9 not found in server\n");
+        }
 
         IedConnection_close(con);
     }

programming_language: C++