首页
社区
课程
招聘
[原创][工控安全]CodeSys V3 协议及授权机制分析
2023-2-8 13:56 24502

[原创][工控安全]CodeSys V3 协议及授权机制分析

2023-2-8 13:56
24502

前言

  Codesys是全球最著名的软PLC内核软件研发厂家德国的3S(SMART,SOFTWARE,SOLUTIONS)公司发布的一款与制造商无关IEC 61131-1编程软件及工控设备内核(runtime SDK)。CodeSys被大量的应用在工控领域中,市场占有率35%,被誉为“工控界的安卓”。
图片描述
  CodeSys属于私有协议,官方从未披露其报文格式和实现细节。为此,研究人员不得不从逆向工程的角度去分析该协议(除非购买昂贵的授权获取到相关源码)。如今CodeSys V2版本逐步被淘汰,取而代之是V3版本,本文将会从逆向角度介绍该协议的格式以及授权机制。
CodeSys覆盖的客户如下所示(只列出一部分,详细情况参考官网 http://www.codesys.cn/list-Partner.html):
图片描述

协议格式

V2与V3

  CodeSys V2版本的协议相对简单,如下图所示。报文头是以“\xbb\xbb”打头,紧接着就是长度字段,后面接着功能码,图中的功能码为92,最后就是数据部分,从结构上来说,V2的协议相对简单。
图片描述
V3 与V2的协议完全不同,该协议架构如下图所示,该协议栈分为四层:
1.块驱动层——Block Driver layer
2.数据报层——Datagram layer
3.通道层——Channel layer
4.服务层——Services layer
图片描述

研究方法

  通过获取到了某个使用CodeSys V3 PLC固件,使用IDA进行分析,分析出协议的处理流程和功能码含义。
图片描述
  CodeSys V3通过ServerRegisterServiceHandler注册对应service_group处理的handler(相当于传统意义上上的功能码):
图片描述
所有注册的服务如下图所示(图示为本人编写的LUA解析插件的内容),可以看到CodeSys协议包含相当多的功能,包括用户管理,日志管理,文件传输等功能。
图片描述

CodeSys V3

  为了帮助理解和研究CodeSys协议,本人不得不实现一个Wireshark解析插件来解析数据报文,下面简要介绍每个layer来分析V3数据包格式。

块驱动层

  块驱动层的组件的主要任务是创建通过物理或软件接口进行通信的能力。任何块驱动程序组件都是一个“输入点”,用于接收数据包和传输数据包的点。
图片描述
图片描述

数据报层

  该层的主要目的是路由数据包,检测 CODESYS 网络中的节点,并将数据传输到下一层。
图片描述
图片描述
简单介绍上面关键字段的含义:
Magic 字段:
通过 CODESYS协议生成的数据包的魔数。该字段的大小为一个字节。
Hop count 字段:
表示在网络上接收到的数据包所经过的CodeSys节点数。每当一个 CODESYS 网络节点收到一个数据包并将其重定向到另一个 CODESYS 网络节点时,它就会递减hop_count的值。如果一个节点收到了一个数据包但不是它的最终接收者并且hop_count字段的值等于 0,则节点将丢弃此数据包。本质上,该字段让 CODESYS 节点的网络免于无休止地转发数据包。
packet_info字段:
表示数据包相关设置。
priority字段:
指定处理数据包的优先级。以下数值用于指定优先级:0 – 低,1 – 正常,2 – 高,3 – 紧急
length_data_block字段:
表示接收者可以接受的最大数据大小。
Service id 字段:
服务ID,指示特定服务器必须处理接收到的数据。

通道层

  通道是 CODESYS 网络节点之间的一种通信机制,它保证通信的同步、传输数据完整性的验证、消息传递的通知以及大量数据的传输。
图片描述
图片描述
Packet_type字段:
BLK(0x1)包类型,表示数据传输。
flags字段:
BLK数据包类型的数据包标志。
channel id 字段:
用于数据传输的通道 ID。
Blk_id 字段:
当前 BLK 消息的 ID。此 ID 每次由通过信道发起通信开始的一方递增。
Ack_id字段:
最后一条 ACK 消息的 ID。该 ID 每次都由响应方更改。在应用层接收到最后一个数据传输到服务的数据包后,响应端将该ID进行更改。
Remaining_data_size 字段:
remaining_data 所包含的预期数据的大小。
Checksum 字段:
该字段是对remaining_data中包含的数据进行校验,CRC32算法用于计算校验和。

服务层

  该层的主要任务是查询请求的服务并传输其操作设置。服务层的任务包括对在该层传输的数据进行编码、解码、加密和解密。
图片描述
图片描述
protocol_id字段:
使用的协议的ID。此ID指示哪个协议处理程序修改了数据以及应使用哪个协议将数据传输到服务。
Header size 字段:
protocol_header的大小。该字段的值不包含先前字段和当前字段的大小。
Service group字段:
被查询服务的ID。如果在ID中设置了最高有效位,则意味着该消息是来自服务的响应。
Service ID 字段:
命令的ID,这个ID决定了服务执行的功能。
session_id 字段:
会话的ID,包含接收到的会话或空会话的值。
data size 字段:
protocol_data字段中数据的大小。

授权流程

  CodeSys 在新版V3通讯协议中已经默认开启授权机制,用户必须设置账号密码才可以进一步使用。在设置密码成功后,用户必须登录后才能对PLC进行控制管理以及编程组态等操作。但是具体的算法之前从未有人披露过,下面我将简单介绍其流程和相关算法。

密码哈希存储

  新版CodeSys V3通讯协议账号相关信息默认存放于UserDatabase文件中,旧版本的CodeSys V3的密码是MD5加密的,新版做了改进,使用了scrypt算法来进行存放。该算法在CryptoDeriveKey中实现,如下所示:
图片描述
UserDatabase文件内容如下,其中“admin”为用户名,后面接着的是密码哈希信息。
图片描述

  • “d819a24df7bdc985”指的是scrypt的盐salt。
  • “02f6……5cfd” 指的是scrypt算出的密码哈希。
  • “512,8,1”指的是scrypt的N,r,p参数。
      使用scrypt原因主要为该算法不仅计算所需时间长,而且占用的内存也多,使得并行计算多个摘要异常困难,因此利用彩虹表进行暴力攻击更加困难。
      当然即使算法设计的再健全,也挡不住用户使用弱口令。在最新版的组态软件并没有强制要求密码强度,使得用户也可以设置诸如“123456”等弱口令密码。这就导致安全意识不强的用户会将密码设置成弱口令。
    图片描述
      通过编写py脚本将scrypt哈希信息转换为标准的hashcat的scrypt hash格式,之后可以利用hashcat对该哈希进行爆破攻击,当然前提是获取到哈希文件(可结合一个任意文件下载漏洞)
    图片描述
      生成得到的哈希如下所示:
      
    1
    SCRYPT:512:8:1:2BmiTfe9yYU=:Avat90uq9ScoWI3p+46HI8solorDp225o6Qi68wud34=
      运行hashcat.cat命令:hashcat.exe -m 8900 -a 0 scrypt.hash dict.txt,爆破成功率依赖于字典以及密码的复杂度,可以使用高性能的GPU,加快爆破速度。
    图片描述

    授权协议流程

    客户端先通过CmpDevice的2号服务ID请求PLC获取公钥和challenge:
    图片描述
    PLC将会随机生成一个密钥对和一个32字节的challenge,响应包将包含公钥和challenge。
    公钥信息如下所示:
    图片描述
    32 字节challenge信息如下:
    图片描述
    客户端在接收以上信息后,使用CryptoAsymmetricEncrypt函数加密密码,该函数如下所示:
    图片描述
    使用python描述password_info生成算法:
    图片描述
  • RSA加密使用的是PKCS1_OAEP,其中的哈希算法为SHA256。
  • XOR算法是简单的逐位异或算法。
    最后,客户端再次通过CmpDevice的2号服务ID下发到PLC中:
    图片描述
    如果密码正确的话将会返回app key,每次进行操作都需要携带该授权key。
    图片描述

    风险分析

      从流程可以知道,如果没有加密的情况下,攻击者可以通过中间人的方法替换公钥并解密出原始密码。为了保证编程软件和PLC的通信安全,建议启用安全通信(基于TLS)。

About RCE

  密码保护是保护CodeSys PLC的重要防线,一旦攻击者突破这层防线,就可以利用注入代码的方法插入任意shellcode执行RCE。这是由于CodeSys为了实现可编程功能,会将用户编写的代码统一编译成机器码,并且由RunTime调度执行,执行的过程没有在VM或者sandbox中,这就导致攻击者可以插入任意的机器码(例如LINUX平台上的反弹shell)来完全接管PLC。
图片描述
如下所示,使用该方法在PLC开启了Vxworks上的Telnet服务(原先是关闭的):
图片描述

总结

  本文详细介绍了CodeSys V3的协议格式和授权流程,并分析了密码保护机制的安全性问题,然而设计是美好的,但是工业现场实践过程中往往存在很多问题。
1.由于很多厂商购买的CodeSys 需要每年花费高额的费用来获取更新支持,绝大多数厂商在购买源码后不在进行更新,这导致目前很多PLC使用的CodeSys版本仍然停留在非常老的版本,仍然受N-day的影响。
2.电气工程师安全意识缺乏,很多部署在现场的PLC根本没设置密码。
3.在厂家都已经停止维护的情况下,CodeSys V2 版本仍然被大量使用,该版本的RCE漏洞更多(N-day以及0-day)。

 

参考链接:
https://ics-cert.kaspersky.com/reports/2019/09/18/security-research-codesys-runtime-a-plc-control-framework-part-2/


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2023-2-8 14:02 被wmsuper编辑 ,原因: 更改标题
收藏
点赞5
打赏
分享
最新回复 (8)
雪    币: 2956
活跃值: (4826)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
舒默哦 1 2023-2-8 14:51
2
0
前排
雪    币: 4016
活跃值: (5833)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
fjqisba 2023-2-8 17:51
3
1
现实就是互联网上到处都是漏洞,就等着有心之人攻击
雪    币: 3906
活跃值: (5528)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
badboyl 2 2023-2-13 10:54
4
0
晴天师傅被收编了?
雪    币: 15
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_fwlzqupj 2024-1-29 18:11
5
0
这个协议有没有用C#实现的技术栈
雪    币: 15
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_fwlzqupj 2024-1-31 17:36
6
0
博主您好,能不能把解析Codesys V3协议的Wireshark解析插件分享一下,万分感谢!
雪    币: 19270
活跃值: (28900)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2024-2-1 09:28
7
1
感谢分享
雪    币: 12586
活跃值: (14290)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
wmsuper 7 2024-2-20 11:09
8
1
mb_fwlzqupj 博主您好,能不能把解析Codesys V3协议的Wireshark解析插件分享一下,万分感谢!
可以看看微软开源的解析插件:https://github.com/microsoft/CoDe16/tree/main/Wireshark%20Dissector
雪    币: 15
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_fwlzqupj 2024-2-24 11:05
9
0
wmsuper 可以看看微软开源的解析插件:https://github.com/microsoft/CoDe16/tree/main/Wireshark%20Dissector
好的,谢谢!
游客
登录 | 注册 方可回帖
返回