工控安全入门之 Ethernet/IP

Ethernet/IP

与 Modbus 相比,EtherNet/IP 是一个更现代化的标准协议。由工作组 ControlNet International 与 ODVA 在 20 世纪 90 年代合作设计。EtherNet/IP 是基于通用工业协议(Common Industrial Protocol,CIP)的。CIP 是一种由 ODVA 支持的开放工业协议,它被使用在诸如 DeviceNet 和 ControlNet 以及 EtherNet/IP 等串行通信协议中。美国的工控设备制造商 Rockwell/Allen-Bradley 已经围绕 EtherNet/IP 进行了标准化,其他厂商如 Omron 也在其设备上支持了 EtherNet/IP。EtherNet/IP 已经变得越来越受欢迎,特别是在美国。尽管 EtherNet/IP 比 Modbus 更现代化,但仍然存在协议层面的安全问题。EtherNet/IP 通常通过 TCP/UDP 端口 44818 运行。此外,EtherNet/IP 还有另一个端口 TCP/UDP 端口 2222。使用这个端口的原因是 EtherNet/IP 实现了隐式和显示两种消息传递方式。显式消息被称为客户端/服务器消息,而隐式消息通常被称为 I/O 消息。

图 5-12 Ethernet/IP分组结构

EtherNet/IP 是为了在以太网中使用 CIP 协议而进行的封装。EtherNet/IP 的 CIP 帧封装了命令、数据点和消息等信息。CIP 帧包括 CIP 设备配置文件层、应用层、表示层和会话层四层。数据包的其余部分是 EtherNet/IP 帧,CIP 帧通过它们在以太网上传输。EtherNet/IP 分组结构如图 5-12 所示。

CIP 规范对数据包结构有很多的规定,这意味着每个使用 EtherNet/IP 的设备必须实现符合规范的命令。下面是 EtherNet/IP 首部中封装的 CIP 帧字段:

图 5-13 CIP字段

  • Command
    两字节整数,对应一个 CIP 命令。CPI 标准要求,设备必须能接收无法识别的命令字段,并处理这种异常。

  • Length
    两字节整数,代表数据包中数据部分的长度。对于没有数据部分的请求报文,该字段为0。

  • Session Handle
    会话句柄(session handle)由目标设备生成,并返回给会话的发起者。该句柄将用于后续与目标设备的通信。

  • Status
    Status 字段存储了目标设备执行命令返回的状态码。状态码 “0” 代表命令执行成功。所有的请求报文中,状态码被置为 “0”。其它的状态码还包括:

0x0001 无效或不受支持的命令
0x0002 目标设备资源不足,无法处理命令
0x0003 数据格式不正确或数据不正确
0x0065 接收到无效的数据长度
  • Sender Context
    命令的发送者生成这六字节值,接收方将原封不动的返回该值。

  • Options
    该值必须始终为 0,如果不为零,数据包将被丢弃。

  • Command-specific data 该字段根据接收/发送的命令进行修改。

如果请求发送方是工程师站,大多数会话中执行的第一条命令是 “List Identity” 命令。如下所示的数据包,命令字段是 0x63,代表 “List Identity” 命令,上下文是 “0x00006a0ebe64”。这个命令与 Modbus 功能码 43 非常相似,可以查询设备信息,如供应商、产品、序列号、产品代码、设备类型和版本号等。使用在 Github 项目 pyenip 中找到的 Python 脚本 ethernetip.py,你可以查询 Ethernrt/IP 设备的信息。默认情况下,这个脚本不会解析一些响应,你需要取消脚本底部的 testENIP() 函数的注释后,它才会发送和接收 “List Identity” 命令。在执行脚本的同时,你可以使用 Wireshark 查看请求和响应的数据包。

图 5-14 Ethernet/IP查询设备信息

我们在这个例子中没有提供脚本代码,因为它大约有 1000 行代码。你可以通过访问这里来获取脚本。

设备信息泄露

  • 流行程度:10
  • 利用难度:8
  • 影响面:3
  • 威胁评分:7

Digital Bond 在项目 Redpoint 中实现了一个和 pyenip 很像的脚本,可以用来从远程设备中获取信息。Redpoint 脚本使用了上一节提到的 “List Identity” 命令字,并使用 NES 脚本来解析请求。这个脚本有一个有意思的地方,它的 “Conmmand Specific Data” 部分包含了一个套接字地址(ip 地址和端口号)。这是暴露的远程设备的真实 ip 地址和端口号,即使它位于 NAT 设备之后。

图 5-15 CompactLogix系统扫描结果

通过 Shodan 搜索( https://www.shodan.io/search?query=port%3A44818 ),我们发现大量的设备暴露的 IP 字段和实际扫描的 IP 地址不同。所以我们得出结论,大多数的 Ethernet/IP 设备部署在内部网络中,而不是直接暴露在互联网上。如下图 5-15所示的是使用 nmap 扫描 CompactLogix 控制系统的扫描结果,可以看到暴露的设备 ip 和扫描 ip 不匹配,说明目标系统位于路由器或防火墙之后。

上图显示了一些信息,包括设备的制造商 “Rockwell”。设备的制造商在响应中是一个两字节的制造商 ID,它映射了一组支持 Ethernet/IP 的厂商名单。但是,这个厂商名单不是公开的。我们在深入研究 Wireshark 捕获的数据包后,发现数据包被 Wireshark 解析后,制造商 ID 被替换成了制造商名称。这说明 Wireshark 拥有如何映射制造商ID和名称的信息。通过对 Github 上 Wireshark 源代码的一些搜索,我们发现了如下代码片段,它告诉我们该如何解析制造商 ID。在解析工控协议的时候,Wireshark 常常是一个强大而好用的资源。

图 5-17 制造商ID和制造商名称的对应关系

使用像 “List Identity” 这样的命令,你可以简单的重放数据包,几乎不用修改数据包。会话句柄将被设置为 0,意味着没有会话生成,因为该命令只是简单的发送命令和接收系统响应。为了进一步与设备进行通信,需要发送注册会话命令(0x65)。这个命令会设置会话句柄 ID,这个 ID 将用于后续会话的通信。如下图 516所示,注册会话的请求使用标准ID “0x00000000”,目标设备返回了它生成的会话句柄 “0x03A566BB”

图 5-16 会话句柄生成过程

Ethernet/IP 中间人攻击

  • 流行程度:5
  • 利用难度:8
  • 影响面:8
  • 威胁评分:7

Ethernet/IP 具有和大多数工控协议相似的问题。资讯和培训公司 Kenexis 发布了针对 Ethernet/IP 的中间人攻击示例演示。这些示例可以在它们的 Github 项目主页上找到( https://github.com/kenexis/PortableICS-MITM )。与 Modbus 不同,简单的数据包重放对 Ethernet/IP 的某些指令无效。这使得攻击变得稍微复杂了一些。然而,对于大多数攻击者而言,只要对 Ethernet/IP 的协议稍有了解,这点困难将是微不足道的。一旦会话句柄通过协商被确定,只要通过手动改变序列号,就可以实现像之前 Modbus-vcr 工具那样的中间人攻击。

Ethernet/IP 高危命令字

  • 流行程度:5
  • 利用难度:8
  • 影响面:8
  • 威胁评分:7

就像 Modicon 利用功能码 90 来终止 CPU,一些 Ethernet/IP 设备也支持类似的命令字。Digital Bind 的 Basecamp 项目中,发布了一个 Metasploit模块,可以被用来终止一个 Allen-Bradley ControlLogix 控制系统中的大量 PLC,以及其它的一些坏坏的事情,比如使以太网卡崩溃。

Digital Bond 的 Ruben Santamarta 在撰写 Basecamp 项目的 Writeup“Attacking ControlLogix”时写道“我们发送的每个数据包必须包含会话句柄。这就是全部,然后我们 Hack 了控制器。在协议层面没有更多的安全机制了。” [译者注:reversemode.com 上的文档我下载不下来,有能够下载的朋友求分享]。Ruben 指出,只要了解 Session Handle 即可轻松攻击 Ethernet/IP。是这个攻击奏效的另一个关键是 Allen-Bradley 实现的一个命令字。Allen-Bradley 在 NOP(0x00)命令中实现了终止 CPU 的功能。

这个命令在 CPI 或 Ethernet/IP 的规范中没有记录,是 Allen-Bradley/Rockwell 控制器的私有实现。通过对大量设备的测试,我们发现,在一些旧的固件中,不仅 ControlLogix CPU 被终止,而且设备崩溃,需要重新启动硬盘。对于当前的型号,PLC 必须拔下并重新插入才能再次运行。极少数情况下,PLC 需要重新编程。

我们还是坚持一贯的建议,如果你想测试你的 Ethernet/ip 设备,请只对非生产设备执行这些测试,并确保你已经被授予对设备执行 exploit 的许可,因为在设备上执行这些测试的后果是不可测的。

工控安全入门之 Ethernet/IP的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【JVM学习笔记】动态代理

    基于JDK的动态代理例子如下 接口 Subject public interface Subject { public abstract void request(); } 实现类RealSubjec ...

  2. DevOps - 构建本地开发环境

    1 - 构建个人本地开发环境 在个人计算机中搭建一个精简版的.与生产环境基本一致的本地开发环境,既不会占用团队公共环境的资源,也可以缩短等待时间,从整体上提高效率. 本地开发环境的适用场景: 从应用程 ...

  3. android#定制ListView的界面

    内容摘自<第一行代码>——郭霖 只能显示一段文本的ListView实在是太单调了,我们现在就来对ListView的界面进行定制,让它可以显示更加丰富的内容.首先需要准备好一组图片,分别对应 ...

  4. 【POJ - 3641】Pseudoprime numbers (快速幂)

    Pseudoprime numbers Descriptions 费马定理指出,对于任意的素数 p 和任意的整数 a > 1,满足 ap = a (mod p) .也就是说,a的 p 次幂除以  ...

  5. Attention is all you need 详细解读

    自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合rnn和attention的模型.传统的基于RNN的Se ...

  6. 【并行计算-CUDA开发】CUDA shared memory bank 冲突

    CUDA SHARED MEMORY shared memory在之前的博文有些介绍,这部分会专门讲解其内容.在global Memory部分,数据对齐和连续是很重要的话题,当使用L1的时候,对齐问题 ...

  7. code review规则

    简单可行的code review规则 前言 曾经有一段垃圾代码放在我的面前,我没有拒绝,等我真正开始接手的时候我才后悔莫及,程序员最痛苦的事莫过于此! 每当接手别人的代码,都有一种想重新写一遍的感觉, ...

  8. JS、JQUERY 获取浏览器和屏幕各种高度宽度

    好长时间没有更新博客了... 把我最近积累的一点知识点放上博客,以后以备不需之要,也给大家整理一下.. Javascript: IE中:document.body.clientWidth ==> ...

  9. 第五周课程总结&实验报告(四)

    第五周课程总结 本周主要学习了 1.抽象类 抽象类的定义格式 abstract class抽象类名称{ 属性; 访问权限返回值类型方法名称(参数){ //普通方法 [return返回值]; } 访问权 ...

  10. getBoundingClientRect()方法

    是在<javascript高级程序设计>中看到了这个方法.getBoundingClientRect在IE5中就有,但似乎不怎么引起我们注意. 返回值:它返回一个clientRect对象, ...