首页 > 代码库 > 工控安全入门之Modbus(转载)

工控安全入门之Modbus(转载)

工控安全这个领域比较封闭,公开的资料很少。我在读《Hacking Exposed Industrial Control Systems》,一本16年的书,选了的部分章节进行翻译,以其抛砖引玉。

MODBUS

Modbus是20世纪70年代后期由Modicon(现为施耐德电气)为了配合其可编程逻辑控制器(PLC)一起使用,创建的基于串行的控制协议。Modbus是最常见的工业控制协议,主要是因为Modbus是一种开放的简单而强大的协议,可以在没有任何版税的情况下开放使用。自从引入Modbus以来,协议已被移植到以太网上工作。为了实现这一点,基于串行的协议被封装(基本上是“封装”)在TCP数据的头部,并且通过默认TCP端口502在以太网络上传输。由于其易于使用,Modbus可以在各种工厂甚至于变电站中找到。

Modbus 分组帧可以分为两部分:应用数据单元(ADU)和协议数据单元(PDU)。ADU 由地址,PDU 和错误检查方法组成。PDU 由功能码和Modbus帧的数据段组成。图51是 Modbus 串行协议的示例,也称为 Modbus RTU。(译者:注意 ADU 包含 PDU,两者是包含关系)

技术分享

图51 Modbus RTU

Modbus RTU 协议与 Modbus 的所有其他实现不同,包括 Modbus+,Modbus ASCII,Modbus TCP/IP,TCP/IP上 的 Modbus 以及 Modbus 的其他较不常见的实现。我们的重点将是 Modbus TCP/IP。Modbus TCP/IP 和 Modbus over TCP/IP 之间的一个主要区别是 ModbusTCP/IP 在数据包的有效载荷内没有校验和,就像在 Modbus RTU 中一样。

Modbus TCP/IP 由 ADU 和 PDU 组成,非常类似于 Modbus RTU。然而,在 Modbus TCP/IP中,

技术分享

图52 MBAP和PDU

ADU 由 Modbus 应用头(MBAP)和 PDU 组成。MBAP 头由事务 ID,协议ID,长度和单元 ID 组成。PDU 与 Modbus RTU 中的 PDU 具有相同的结构,具有功能码和数据有效载荷。数据包中的功能代码(FC)是帮助确定数据包性质的项目。例如,此处显示的功能代码为0x2b(43),为读取设备标识FC。这个FC向设备请求特定的信息,例如PLC的制造商和PLC型号。

针对不同的 FC,数据包的数据部分代表不同的信息。对于读取设备标识FC,该数据告诉设备请求的是哪部分标识。利用 Nmap,您可以使用 modbus-discover Nmap 脚本(https://nmap.org/nsedoc/scripts/modbus-discover.html)进行爆破收集。modbus-discover Nmap 脚本还会尝试收集Slave ID信息。从站 ID 信息通过 FC 17(0x11)读取。Modbus 标准包含了大多数设备将支持的功能代码。这些功能码在 Modbus 标准中定义,如图53所示。

技术分享

图53 Modbus 功能码

作为较旧的协议,Modbus 缺少大多数现代化的安全功能,甚至无法抵御诸如未经身份验证的命令发送和数据包重放之类微不足道的攻击。使用每个功能代码,数据包的数据部分发生变化,因此它包含正在请求的适当信息。作为示例,在功能码1的 Modbus 线圈的读取请求中,数据包的数据部分包含参考号,即开始读取的点和要读取的线圈数。图54是 Wireshark 中的一个示例 数据包:

技术分享

图54 Modbus 请求响应示例

有多种读写Modebus线圈和寄存器的技术。你可以使用像Python这样的编程语言来手工处理数据包,因为数据包非常简单,而且有pymodbus这样的库来帮助你构建,接收和解析数据包。另一个使数据包操作变得简单的工具是scapy(http://www.secdev.org/projects/scapy/)。当然,在大多数情况下,最简单和快速的方法是使用已经实现Modbus协议的客户端工具。这里推荐一个适合渗透测试人员使用的工具,modbus-cli(https://github.com/tallakt/modbus-cli)。它允许你使用简单的命令来读写线圈和寄存器,如下图55所示:

对Modbus设备进行渗透测试的一个难点,是需要找出每个线圈和寄存器对应的功能是什么。与很多协议不同,Modbus协议不会记录读写的值的意义。根据你的目标,你可以执行更多的测试,来收集更多设备执行逻辑的信息。利用CybatiWorks(https://cybati.org/cybatiworks)等模拟器系统,您可以尝试在非生产系统上执行测试和收集信息。通过使用人机界面(HMI),更改线圈和寄存器的影响变得更加明显。下面我们使用CybatiWorks模拟一个交通灯控制面板的示例,它的HMI非常简单,您可以看到系统处于自动模式。

技术分享

图55 查看寄存器

技术分享

图56 存储模式信息的寄存器

技术分享

图57 Cybatiworks模拟器

通过修改设置和遍历查询寄存器的值,你可以定位哪个寄存器与系统的模式设置相关联(这个过程比较像做游戏破解时CE的行为)。这个过程会花一些时间,而且当你查询系统中无效的地址时还会导致错误。如下图57所示,通过上述步骤,我们发现设置寄存器%MW4的值为1,令系统处于自动模式,以使指示灯以给定的频率发生变化。

你可能想要更改系统的模式,从而使设备不会定时的改变交通指示灯。为了达到这个效果,你可能想要修改寄存器%MW4的值为零。但在这个例子中,这个设备并不能通过一次数据写来关闭自动模式。通过测试,我们认为这种现象可能是设备的内部逻辑导致的。要想关闭自动模式,一个特定的指示灯需要先被打开。我们使用写入命令,反转所有寄存器的值,但除了%MW3。之所以保留%MW3,是因为%MW3映射到了HMI上的闪烁按钮,无论其它寄存器是什么状态,只要%MW3被置位,所有指示灯将闪烁。完成上述步骤后,再将%MW4置为零,将禁用HMI中的设置。下图58显示了写命令发出后,值的修改状况

技术分享

图 58 写命令后的寄存器值

Modbus协议的中间人攻击

  • 流行程度:10

  • 难度:8

  • 影响面:8

  • 威胁评分:9

由于设计中缺乏安全进制,Modbus协议易受中间人(Man in The Middle,MiTM)攻击的影响,也包括数据包重放攻击。前文提到的对Cybati交通灯系统的攻击方式,就可以用于中间人攻击。在攻击中,攻击者还可以通过欺骗HMI来使交通灯系统看起来没有异常,从而延迟厂商发现问题。用多种开源或商用的工具可以用于在Modbus网络上执行中间人攻击。Modbus VCR(https://github.com/reidmefirst/modbus-vcr/)是开源的免费工具,它使用Ettercap记录Modbus流量,然后重放该流量,使系统看起来就像在处理正常的流量。

施耐德PLC高危命令字

  • 流行程度:10

  • 难度:8

  • 影响面:8

  • 威胁评分:9

Modbus协议的实现中常常包含一些厂商实现的非标准的功能码。一个典型的例子是施耐德PLC中的0x5a(90)功能码。和大多数专有协议一样,你必须使用工程软件来分析协议的工作原理。工控安全研究和顾问公司Digital Bond在知名项目ProjectBasecamp中最早在一个Metasploit模块(https://www.rapid7.com/db/modules/auxiliary/admin/scada/modicon_command)中,指出功能码 0x5a 的问题。该功能码实现了Modbus标准未允许的功能,如终止 CPU 的工作。这个高危功能码是通过记录工程软件(Unity Pro)与 Modicon PLC 的通信流量来发现的。

技术分享

图59 Unity Pro菜单项

通过数据包重放,可以看到这个命令字终止了Modicon PLC所有的运行逻辑。对于需要实时控制的系统,这样的攻击可能导致灾难性后果。

记录工程软件和PLC之间的通信可以从协议中提供一些可用的信息。执行功能代码90的情况下,PLC泄露了令人惊讶的信息,如图510所示,包括最后加载程序到设备的机器主机名。当检查捕获自PLC和工程软件的流量时,Modbus中常常是未编码的字符串,从而易于从设备的响应中解析。

技术分享

在示例中,项目名称为“Project“,十六进制值为”\x50\x72\x6f\x6a\x65\x63\x74“。进一步检查数据包,十六进制”\x08\x00\x00“是小端序似乎是项目修订号,通过程序解释后,会显示为0.0.8。”\x0c\x3b\x0c\x0e\x01\xde\x07“是项目文件上次修改的日期。下面显示的日期时间戳记以小时,分,秒,日,月和年为单位,也是小端序。

技术分享

图511 时间戳

施耐德PLC识别

  • 流行程度:10

  • 难度:8

  • 影响面:3

  • 威胁评分:7

依然使用相同的技术,Digital Bond的项目Project Redpoint(https://github.com/digitalbond/Redpoint/blob/master/modicon-info.nse)能够从PLC搜集更多的信息,包括PLC部署在工业设施内部的位置。使用Modbus Nmap脚本收集信息有助于构建设备画像,这些设备通过功能码43和功能码90与Modbus进行通信。我们可以使用协议内置的命令(功能码43和功能码90),安全地从设备获取信息。

工控安全入门之Modbus(转载)