0x1 简介
DNP(Distributed Network Protocol,分布式网络规约)是一种应用于自动化组件之间的通讯协议,常见于电力、水处理等行业。SCADA可以使用DNP协议与主站、RTU、及IED进行通讯。
DNP协议标准由IEEE提出,参考了IEC 870-5、以及其他一些IEC协议。主要为了解决SCADA行业中,协议混杂、没有公认标准的问题。
DNP协议有一定的可靠性,这种可靠性可以用来对抗恶劣环境中产生的电磁干扰、元件老化等信号失真现象,但不保证在黑客的攻击下、或者恶意破坏控制系统的情况下的可靠性。
DNP协议提供了对数据的分片、重组、数据校验、链路控制、优先级等一些列的服务,在协议中大量使用了CRC校验来保证数据的准确性。以下是一些DNP协议的特点:
• DNP3.0规约是一种分布式网络协议,适用于要求高度安全、中等速率和中等吞吐量的数据通信领域。
• DNP3.0规约以IEC870-5标准为基础,该规约非常灵活,满足目前和未来发展的要求,且与硬件结构无关。
• DNP3.0规约采用网络通信方式。
• DNP3.0规约支持点对点、一点多址、多点多址和对等的通信方式。
• DNP3.0规约支持问答式和自动上报数据传输方式。
• DNP3.0规约支持通信冲突碰撞避免/检测方式,能保证数据传输的可靠性。
• DNP3.0规约支持传送带时标的量,尤其有利于配电自动化系统采集分时电度值和分析事故原因。
• 灵活采取适当的扫描方式,DNP3.0规约可以在一定程度上实现实时优先级。
0x2 协议格式
DNP3.0规约的文本共分4部分:数据链路层规约,传输功能,应用层规约及数据对象库。
0x2.1 数据链路层规约
数据链路层规约文件规定了DNP3.0版的数据链路层,链路规约数据单元(LPDU)以及数据链路服务和传输规程。
数据链路层采用一种可变帧长格式:FT3。
一个FT3的帧被定义为一个固定长度的报头,随之以可选用的数据块。每个数据块附有一个16位的CRC校验码。固定的报头含有2个字节的起始字,1个字节的长度,1个字节的控制字,1个16位的目的址,1个16位的源地址和1个16位的CRC校验码。
0x2.2 传输功能
这部分定义对于DNP数据链路层充当伪传输层的传输层功能。伪传输层功能专门设计用于在原方站和副方站之间传送超出链路规约数据单元(LPDU)定义长度的信息。
0x2.2.1 传输层报头数据块
其中:传输层报头——传输控制字,1个字节;数据块——用户数据,1~249个字节。
0x2.3 应用规约
这部分定义了应用层报文(APDU)的格式。这里,主站被定义为发送请求报文的站,而外站则为从属设备。被请求回送报文的RTU或智能终端(IEDs)是事先规定了的。在DNP内,只有被指定的主站能够发送应用层的请求报文,而外站则只能发送应用层的响应报文。
0x2.3.1 应用报文格式
其中:请求(响应)报头——标识报文的目的,包含应用规约控制信息(APCI);对象标题——标识后随的数据对象;数据——在对象标题内的指定类型的数据对象。
0x2.3.2 应用报文报头字段的定义
请求报头分应用控制、功能码两个字段。每个字段为8位的字节;响应报头分应用控制、功能码、内部信号字3个字段。每个字段也为8位的字节。
0x2.3.3 对象标题
报文的对象标题制定包含在报文中的数据对象或是被用来响应此报文的数据对象。
应用报文中,对象、限定词、变程的灵活使用,可以表示多种数据类型和数据表示格式,满足用户的不同需要。这也是DNP3.0规约的一大优点。
注:以上摘自网络
0x3 DNP设备识别方法
DNP3可通过TCP/UDP进行封装,以便在以太网上运行,支持DNP3协议的从设备默认会开放TCP的20000端口用于通信。DNP3协议在设计之初依然是没有考虑到安全、认证等的一些因素,以致后来出现了Secure DNP3(主要加强了认证)。在DNP3目前的应用、传输上个人的观点还是要比MODBUS可靠,DNP3在主站会话上需要约定目的地址、源地址,而从设备收到后需要验证目标地址,然后再进行处理,如果目的地址不相同则会根据在协议栈实现的处理上来决定是否不响应和关闭连接,或者返回异常功能报文等。想要精准识别运行在tcp的20000端口的服务是否为DNP3,可以使用DNP链路层协议(协议格式如下图),
将其封装成需要发送的识别报文,这样便可以枚举出想要通信设备的目的地址,又能准确判断该端口运行有DNP3服务,并且报文构造相对简单。
在协议的控制字方面可以使用协议中的9号功能码请求链路状态,相应的设备如果响应回复一般则会返回11,如下图为控制字格式:
如下图为功能码取值:
需要注意的是正因为设备对非法连接(目的地址)请求的处理方式不一样,在应用到实际的全网扫描中不可能全部尝试到所有的地址(目的地址长2个字节,范围在0-65535),另外还需要实现协议的CRC的算法。这样从实现到扫描整体的代价都会比较大。
那么我们可以看一下Shodan在DNP协议的识别这块是如何做的,如下图是在公网监听了tcp/20000端口后收到的包。
我们可以看到Shodan在针对DNP3协议在公网扫描识别上,也还是采用了枚举的方式,并且看似有些暴力,再根据下图你会发现Shodan总共尝试了101个地址,
故你会在Shodan检索port:20000时发现设备的源地址(Source address/对应主站的目的地址)都没有超过100。
那我们实现针对DNP的扫描插件时也可参照Shodan的做法,在组包时定义一段范围的地址来进行批量探测,并且探测1-100的目的地址组包大小有1010个字节,在批量扫描探测时还要受网络收发延时影响。所以Shodan目前能检索到的数据也不足1000,现在看来貌似也没有相对好的做法。
根据Shodan的套路这个扫描规则还是很好制定的,我们可以定义一个探测包,再定义判断返回报文的长度、包头部是否为DNP的协议头0x05,0x64,然后解析源、目的地址、功能码,非常简单就能实现一个与Shodan一模一样的针对DNP3协议扫描的基于NMAP的NSE插件。
0x4 调试及工具分享
如下工具可以快速帮你熟悉、调试、仿真、测试DNP3协议:
opendnp3
opendnp3是automatak开源的基于IEEE-1815 (DNP3)的开源协议栈。
Aegis™
Aegis™是automatak开源的一个针对工控协议进行模糊测试(Fuzz)的框架,其中包含对DNP3协议模糊测试的模块,官方的Project Robus项目曾经发布过多个应用在DNP3协议健壮性上的漏洞,官方在发布MODBUS模块后貌似没有再继续开源了。
Protocol Test Harness
Protocol Test Harness是Triangle MicroWorks公司开发的一款协议仿真、调试软件,软件可以仿真多种工控协议包括DNP3,可以方便你完成调试、仿真。