摘要:01.概述 最近入手了一个新版本西门子S7-1200PLC,固件版本为V4.2.3,通信协议为S7comm-Plus,已经全面支持通信过程的认证和数据加密。其实,早在2016年4月PLC蠕虫被提出之后,V4.0及其之后的固件版本已全面启用S7comm...
最近入手了一个新版本西门子S7-1200PLC,固件版本为V4.2.3,通信协议为S7comm-Plus,已经全面支持通信过程的认证和数据加密。其实,早在2016年4月PLC蠕虫被提出之后,V4.0及其之后的固件版本已全面启用S7comm-Plus协议,安全性有较大的提升,简单粗暴的重放攻击再也不那么凑效了。2019年8月的blackhat大会上,以色列研究人员成功开发出模拟TIA Portal的伪工作站,可成功与新版本的西门子PLC(S7-1200、S7-1500)进行交互,并进行启/停、逻辑篡改等各种操作,这似乎意味着PLC蠕虫在高版本的PLC中同样可以实现。
要实现对新版本PLC的攻击,研究S7comm-Plus协议、理解整个通信握手、认证加密过程是必经之路,国内绿盟、启明已通过对核心通信DLL文件进行逆向分析,实现了对PLC的启/停攻击。
本文主要详述了作者通过对blackhat2017、2019的相关论文的研读,多次试验以及初步逆向、动态调试分析,形成的对S7comm-Plus协议的一些个人理解。文章仅供交流学习,不足之处望指正以促共同进步。
整个试验研究的基本环境配置如下:Win7x64虚拟机、
PLC:S7-1200, 6ES7 212-1BE40-0X0B
Firmware: V4.2.3
Software:TIA Portal V14
S7Comm-Plus Wireshark dissector plugin:V0.0.8
文章中将协议分为了P2-、P2、P3等三个版本,不同版本的TIA Portal软件与不同PLC组合,通信使用了不同的协议版本:
因此,可根据目标PLC固件版本选择合适的TIA版本进行安装。
S7Comm-plus协议的TCP/IP实现依赖于面向块的ISO传输服务,其OSI模型如下:
1、Handshakeinitiation: 通信握手初始化,即CR/CC数据包部分;
2、Challenge:TIA与PLC建立S7Comm-Plus Connection,PLC端生成20个字节随机数,反馈给TIA端;
3、StructSecurityKey:TIA与PLC建立S7Comm-Plus Connection,TIA端根据随机数(Challenge)并结合公钥,生成认证数据;
4、ACK:TIA与PLC建立S7Comm-PlusConnection,PLC端使用私钥对认证数据(StructSecurityKey)进行解密,认证成功后,回复TIA端OK,通信建立成功;
5、Function:TIA端向PLC发送带有功能操作的数据(如PLC启/停);
以上每一个步骤的数据交互中,均带有相同的“session id”,对通信过程进行抓包,具体数据如下所示:
对通信建立过程(即S7Comm-Plus connection)中的认证过程进一步分析:
1、TIA向PLC发送M1开启会话,使用了“CreateObject”功能码创建了“ClassServerSession”的对象:
2、PLC响应TIA的请求,回复M2,M2包含 PLC固件版本和20个字节的随机数ServerSessionChallenge,同时包含了session id:
3、TIA收到M2后,根据随机数(20个字节的随机数,在实际计算的过程中只选取了中间的16个字节,首位各2个未参与实际计算)并结合公钥,使用了复杂的加密算法(包括基本的异或XOR,Hash如SHA-256,MACs如HMAC-SHA-256、CBC-MAC,AES-CTR mode, AES-ECB mode、ECC)生成认证数据,响应PLC并回复M3,认证数据中需要关注的重点部分为“StructSecurityKey”的结构,该结构中长度为180字节的“SecurityKeyEncryptedKey”又为重中之重字段:
4、PLC收到M3后,使用私钥对加密数据进行解密、认证,认证成功则向TIA回复M4数据包(上图中长度为86的数据包)。
5、认证成功之后,TIA向PLC发送带有功能操作的数据包,TIA使用私有算法(使用了会话密钥)对数据包内容计算得到32个字节的IntergrityPart字段,PLC收到功能码数据包后,首先校验IntergrityPart字段,验证通过则执行相应功能码动作。
3.2、加密字段
从基本通信过程可以看出,M3数据包中的加密字段生成是与PLC成功建立通信的关键,随后计算IntergrityPart部分是成功操纵PLC的关键。数据加密的过程是一个复杂的密码学算法实践过程,从上图中可以看出,Wireshark插件已经对数据中的大部分字段进行了正确解释,但是少数字段,如“StructSecurityKey”中的“SecurityKeyEncryptedKey”字段未被完全识别,在此结合文章和实际数据包,对180字节的“SecurityKeyEncryptedKey”中的进行具体识别。
Wireshark识别的结构和文章中对该字段的分解如下图所示:
Magic byte:0xFEE1DEAD为magic,4个字节为固定不变,且为小端模式;
Length:字段的长度,即为180;
Symmetric key checksum:8个字节,即文章中提到的KDK ID Header;
Public key checksum:8个字节,即文章中提到的Public key ID Header;
此8个字节,对于所有相同型号和固件的S7-1200PLC计算出的结果均相同,因为西门子对同类同型号的PLC使用了相的Public key,而此处的checksum即是Public key计算SHA-256并取前8个字节。在实验中,通过动态调试可以获取S7-1200PLC的Public key如下图内容所示的40个字节:
文章中亦指明了PLC的Public key信息存储于TIA的安装目录:Siemens/Automation/Portal V14/Data/Hwcn/Custom/Keys) ,但其文件为加密方式存放。
对各个加密数据字段进行一一对应和识别之后,回过头再来看整个密钥生成算法和交换过程,思路慢慢变得清晰稍许:
梳理一下整个过程中的关键点:
1、识别输入数据:最明显的输入数据是PLC Public key,这个是可以直接获取的,另外是PreKey,PreKey为TIA随机生成的20个字节随机数,可在动态调试中从内存中抓取;Challenge,可从M2数据中获取;
2、各种复杂的密码算法:关于其中的类椭圆曲线加密算法,使用了一个固定的40个字节key,代表了160位的椭圆曲线点,椭圆曲线的基点G硬编码于OMSp_core_managed.dll文件中,动态调试过程中亦可从内存抓取,S7-1500和S7-1200的分别G如下所示:
基于对西门子最新的S7Comm-Plus通信协议的初步分析,整个过程使用了非常复杂的认证加密手段,想要破解和绕过并非一件简单的事情。但是,由于通信过程中认证是单方面的,即TIA对PLC进行了认证,而PLC未对TIA进行认证,因此可以伪造TIA与PLC建立通信;另外,相类型、固件版本的PLC使用了相同的private-public密钥对,则意味着完成对一个S7-1200的成功攻击,即实现了对所有S7-1200的攻击。
虽然通信过程中的认证加密异常复杂,文章中已经实现了对新版本S7-1500PLC的攻击,攻击思路总结如下:
1、通过动态调试抓取加密认证所需要的输入数据,如TIA产生的随机数和M2返回的Challenge;
2、定位到相应的加密函数;
3、使用加密函数对输入数据进行计算,得到正确的数据包字段,对字段进行组合成完整数据包发往PLC校验。(此处有两种思路:① 文章中指出使用Python的Ctypes模块包裹核心通信DLL:OMSp_core_managed.dll,构造正确的输入参数,实现整个加密认证过程;② 对加密过程进行动态调试,厘清加密认证过程,定位相关功能函数,同时配合逆向分析将功能函数抠取,构造函数的输入参数,完成整个加密认证过程。)
【转载声明】
本文属于博智安全非攻研究院原创技术文章,已在安全客发表(https://www.anquanke.com/post/id/206579)转载请注明原始出处和作者。