Talos Vulnerability Report

TALOS-2021-1300

CODESYS Development System ComponentModel Profile.FromFile() Unsafe Deserialization vulnerability

July 26, 2021
CVE Number

CVE-2021-21863

Summary

An unsafe deserialization vulnerability exists in the ComponentModel Profile.FromFile() functionality of CODESYS GmbH CODESYS Development System 3.5.16 and 3.5.17. A specially crafted file can lead to arbitrary command execution. An attacker can provide a malicious file to trigger this vulnerability.

Tested Versions

CODESYS GmbH CODESYS Development System 3.5.16
CODESYS GmbH CODESYS Development System 3.5.17

Product URLs

https://store.codesys.com/codesys.html

CVSSv3 Score

8.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-502 - Deserialization of Untrusted Data

Details

The CODESYS Development System is the IEC 61131-3 programming tool for industrial control and automation technology, available in 32- and a 64-bit versions.

This vulnerability may be triggered by opening the application, exporting a project, viewing the project information window, or other actions which cause the application to load profile files.

The vulnerable method is _3S.CoDeSys.Core.Components.Profile.FromFile()

public static Profile FromFile(string stPath)
{
    if (stPath == null)
    {
        throw new ArgumentNullException("stPath");
    }
    string text;
    bool flag;
    Class14.smethod_0(stPath, out text, out flag);
    if (flag)
    {
        return new Class15().method_1(stPath);
    }
    Profile result;
    using (FileStream fileStream = File.OpenRead(stPath))
    {
        result = (new BinaryFormatter().Deserialize(fileStream) as Profile); // [1]
    }
    return result;
}

The BinaryFormatter.Deserialize method is never safe when used with untrusted input [2]. The deserialization that occurs at [1] is vulnerable to exploitation via manipulation of profile files.

[2] https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

Crash Information

Partial Call Stack

ComponentModel.dll!_3S.CoDeSys.Core.Components.Profile.FromFile(string stPath = @"C:\Program Files\CODESYS 3.5.16.40\CODESYS\Profiles\Informational\bin_hack.profile")
ComponentModel.dll!_3S.CoDeSys.Core.Components.ProfileList.GetProfile(string stProfile = "bin_hack")
objectcommands.plugin.dll!_3S.CoDeSys.ObjectCommands.ExportDialog.OnLoad(System.EventArgs e = {System.EventArgs})
...

Serialization Exception

$exception {System.Runtime.Serialization.SerializationException: Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
at System.Runtime.Serialization.Formatters.Binary.BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at _3S.CoDeSys.Core.Components.Profile.FromFile(String stPath)
at _3S.CoDeSys.Core.Components.ProfileList.GetProfile(String stProfile)} System.Runtime.Serialization.SerializationException**

Profile Load Exception

$exception {_3S.CoDeSys.Core.Components.ProfileLoadException: The profile 'bin_hack' could not be loaded.
(Reason: Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.)
at _3S.CoDeSys.Core.Components.ProfileList.GetProfile(String stProfile)} _3S.CoDeSys.Core.Components.ProfileLoadException

Timeline

2021-05-18 - Vendor Disclosure
2021-07-13 - Vendor Patched

2021-07-26 - Public Release

Credit

Discovered by Patrick DeSantis of Cisco Talos.