工控安全这个领域比较封闭,公开的资料很少。我在读《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(转载)的更多相关文章

  1. 工控安全入门之 Ethernet/IP

    工控安全入门之 Ethernet/IP Ethernet/IP 与 Modbus 相比,EtherNet/IP 是一个更现代化的标准协议.由工作组 ControlNet International 与 ...

  2. 工控安全入门(三)—— 再解S7comm

    之前的文章我们都是在ctf的基础上学习工控协议知识的,显然这样对于S7comm的认识还不够深刻,这次就做一个实战补全,看看S7comm还有哪些值得我们深挖的地方. 本篇是对S7comm的补全和实战,阅 ...

  3. 工控安全入门(二)—— S7comm协议

    在上一次的文章中我们介绍了施耐德公司的协议modbus,这次我们把目标转向私有协议,来看看另一家巨头西门子的S7comm.首先要说明,这篇文章中的内容有笔者自己的探索,有大佬们的成果,但由于S7com ...

  4. 工控安全入门(六)——逆向角度看Vxworks

    上一篇文章中我们对于固件进行了简单的分析,这一篇我们将会补充一些Vxworks的知识,同时继续升入研究固件内容. 由于涉及到操作系统的内容,建议大家在阅读本篇前有一定操作系统知识的基础,或者是阅读我的 ...

  5. 工控安全入门(一)—— Modbus协议

    modbus基础知识 modbus协议最初是由Modicon公司在1971年推出的全球第一款真正意义上用于工业现场的总线协议,最初是为了实现串行通信,运用在串口(如RS232.RS485等)传输上的, ...

  6. 工控安全入门之Ethernet/IP

    这一篇依然是协议层面的,协议层面会翻译三篇,下一篇是电力系统中用的比较多的DNP3.这一篇中大部分引用的资料都可以访问到,只有一篇reversemode.com上的writeup(http://rev ...

  7. 工控安全入门(五)—— plc逆向初探

    之前我们学习了包括modbus.S7comm.DNP3等等工控领域的常用协议,从这篇开始,我们一步步开始,学习如何逆向真实的plc固件. 用到的固件为https://github.com/ameng9 ...

  8. 工控安全入门(七)—— plc的网络

    上一篇我们详细分析了bootram和Vxworks的基本启动流程,这篇文章中我们把视线转到plc的网络部分,同时来复现我们第一个.第二个工控安全漏洞. VxWorks的网络设备驱动 一般我们说有三种设 ...

  9. 工控安全入门(四)—— DNP3协议

    我们之前看过了法国施耐德的Modbus.德国西门子的S7comm,这次就让我们把目光投到美洲,看看加拿大的HARRIS的DNP3有什么特别之处. 这次选用的流量包部分来自w3h的gitbub: htt ...

随机推荐

  1. PP学习笔记02

    SPRO SAP参考IMG MM03 物料视图 生产计划编制 需求管理 已计划的独立需求 需求类型 策略组 定义策略 策略组 主要策略(独立需求 ) 客户需求类型 需求类 (计划标识符.消耗标识.需求 ...

  2. hdu 4685(强连通分量+二分图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...

  3. BZOJ1861[Zjoi2006]书架——非旋转treap

    题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...

  4. Java生成数独函数

    突然想写一下生成算法.代码注释的比较多,应该比较好理解 使用了递归 import java.util.ArrayList; public class Sudoku { static int sudok ...

  5. Android 判断是否有声音在播放

    在Android中,我们可以通过AudioManager来判断是否有声音在播放. 实例1: 源码地址: PhoneWindowManager.java (frameworks\base\policy\ ...

  6. [luogu3978][bzoj4001][TJOI2005]概率论【基尔霍夫矩阵+卡特兰数】

    题目描述 为了提高智商,ZJY开始学习概率论.有一天,她想到了这样一个问题:对于一棵随机生成的n个结点的有根二叉树(所有互相不同构的形态等概率出现),它的叶子节点数的期望是多少呢? 判断两棵树是否同构 ...

  7. 【转】C语言字符串与数字相互转换

    在C/C++语言中没有专门的字符串变量,通常用字符数组来存放字符串.字符串是以“\0”作为结束符.C/C++提供了丰富的字符串处理函数,下面列出了几个最常用的函数. ● 字符串输出函数puts. ● ...

  8. 修复Mysql主从不同步shell

    使用第三方工具MySQL Enterprise Monitor,MySQL企业版监控工具.MONyog – MySQL Monior and Advisor,MONyog大家都不陌生,windows下 ...

  9. 哈夫曼树Huffman

    哈夫曼树处理这样的一种问题: 给出一棵n个叶子的k叉树,每个叶子有一个权值wi,要求最小化∑wi*di di表示,第i个叶子节点到根节点的距离.(一般是边数) 处理方法比较固定. 贪心的思路:我们让权 ...

  10. react中跨域请求天气预报接口数据

    背景故事:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能, 如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之上 ...