工控DNP3协议及安全风险细解

admin 2022年4月22日23:28:41评论1,305 views字数 3886阅读12分57秒阅读模式


    在开始分析之前,我们得先了解一下DNP3协议的规约,以便我们在下文更容易的分析其DNP3存在的安全问题以及构造出攻击DNP3协议的EXP,文中难免出现错误地方,如有不对的地方,还望大家斧正。

 

为了能够更详细的表达出DNP3规约,所以在本文分析中大量引用了原DNP3规约的描述文档

 

DNP3.0规约的文本共分为个部分数据链路层、传输层、应用层。

一、数据链路层规约

 

数据链路层规约文件规定了DNP3.0版的数据链路层链路规约数据单元(LPDU)以及数据链路服务和传输规程。数据采用一种可变帧长格式: FT3

 

FT3 帧长格式:

 

一个 FT3帧被定义为一个固定长度的报头,随后是可以选用的数据块,每个数据块附有一个16位的CRC校验码。固定的报头含有2个字节的起始字,一个字节的长度 (LENGH) ,一个字节的链路层控制字(CONTROL) ,一个16位的目的地址,一个16位的源地址和一个16位的 CRC校验码。


工控DNP3协议及安全风险细解


05 64 为数据开始的字节,也可以说是报文头

12为长度,这里Dnp3的长度计算有些不一样,它包括链路报文头中的5个字节,加上传输层和应用层的长度以及除去CRC校验码字节。

c4 链路控制字节

  第一位为 表明发送的方向

  第二位为 表示发送的设备是主设备还是从设备

  第三位为 如果是请求则为纠错,如果是回应则为保留位

  第四位为 这一位是说明第三位是否有效、在图上为0则为未开启。

  后四位为 功能码

    对于主设备来说

0,链路重置

1,进程重置

3,请求发送数据

4,直接发送数据

9,查询当前链路的状态

    对于从设备来说

0,同意

1,拒绝

11,回应当前链路状态

03 00 目的地址

04 00 源地址

15 2d 校验码

二、传输层规约

这部分定义对于DNP数据链路层充当伪传输层的传输层功能。伪传输层功能专门设计用于在原方站和从方站之间传送超出链路规约数据单元 (LPDU) 定义长度的信息。其格式如下:

TH传输层报头

数据块

 

 

工控DNP3协议及安全风险细解

 

TH传输层报头:

第一位是final,标识是否为最后一个包

第二位是first,标识是否为最后一个包

后六位为seq,表明当前是第几个包

 

数据块:

应用用户数据1-249个字节由于数据链路层FT3 帧格式中的长度字的最大限制255,因此传输层数据块的最大长度为255-5(链路层control + source + destination-1TH= 249

当应用用户数据长度大于249 字节时,传输层将以多帧报文方式传送,并每帧前加TH控制字。如1234=249+249+249+249+238, 5进行传送。


三、应用层规约

本文本定义了应用层报文(APDU)的格式。

主站被定义为发送请求报文的站,而从站则为从属设备。被请求回送报文RTU或智能终端 (IEDS)是事先规定了的。在DNP中,只有被指定的主站能够发送应用层的请求报文,而从站则只能发送应用层的响应报文。

 

应用报文格式:

 

Request Header

请求报文

Object Header

对象标题

Data

数据

Object Header

对象标题

Data

数据

 

1. 应用响应报文格式:

 

Response Header

请求报文

Object Header

对象标题

Data

数据

Object Header

对象标题

Data

数据

 

请求(响应)报头:标识报文的目的,包含应用规约控制信息(ACPI)

对象标题:标识随后的数据对象

数据:在对象标题内的指定的数据对象

 

 

2应用报文报头字段的定义:

 

请求报头有两个字段。每个字段为8位的字节说明如下:

 

 

Application Control

应用控制

Function Code

功能码

 

响应报头有三个字段。前两个字段为8位的字节,第三个字段为两个字节,说明如下:

 

Application Control

应用控制

Function Code

功能码

Internal Indication

内部信号字

工控DNP3协议及安全风险细解


应用控制:一个字节的长度,格式如下:

FIR :此位置“ 1” , 表示本报文分段是整个应用报文的第一个分段

FIN :此位置“ 1” , 表示本报文分段是整个应用报文的最后一个分段

CON :此位置“1” , 表示接受到本报文时,对方须要给予确认,为“0”则不需要

序号:表示分段的序号,1-15

功能码:标识报文的目的,一个字节的长度

例如:请求报文:

0x01 -- 读,请从站读所指定的数据对象

0x02 -- 写,向从站写入指定的数据对象

……

上图数据包分析此处为写信号write (0x02)

内部信号:

共两个字节, 16位,每一位分别表示从站的当前的各种状态。

 

 

3.对象标题 (Object Header):

报文的对象标题指定包含在报文中的数据对象或是被用来响应此报文的数据对象。格式如下:

Object

对象

Qualifier

限定词

Range

变程(范围)

 

对象( Object):

两个字节,指定对象组以及跟在标题后面的对象的变化。对象段的格式如下:

Group

对象组

Variation

变体

 

对象段规定一个对象组和在该组内的对象变体。对象的组别与变体结合起来可以唯一的规定报文所指定的对象。对象组指定数据的基本形式(如:模拟输入

),对象变体指定数据的形式(16位模拟输入或32位模拟输入)。

下图可以看到数组为1个,所以为0x01

工控DNP3协议及安全风险细解

32 01 这里表达的意思为要读取的数据的基本类型,上图的数据包为Time的类型

 

07 为限定词。限定词为一个 8位的字节段,规定交程段的意义。变程说明数据对象的数量,起点和终点的索引成所讨论的对象的标识符。

限定词段的格式如下

R

Index Size

索引规模

Qualifier Code

4位限定词码

 

R:保留位,置为零。

索引规模( Index Size):

3个Bits,规定前置于每个数据对象的索引规模或对象的规模。

在请求报文中,当限定词码 (Qualifier Code) 等于 11时,1、2、3分别代表数据对象前的索引是1、2、4个字节。0无效 4、5、6、7保留。

 

限定词码 (Qualifier Code) :

4个Bits,用以规定变程 (Range) 意义。当限定词码取值 0~5时,变程段包含1个开始范围 (Start Range) 和1个结束范围 (Stop range)。当限定词码取值 6时,则 Range 段的长为零 (即无变程段 ),因为所指定的是所要求的数据类型的全部数据对象。当限定词码取值为 7~ 9 时,则变程段由一个计数值所组成,它指明所讨论的数据对象的数目。

限定词段中限定词码和索引规模的有效组合主要有“0x00,0x01,0x02,0x03,0x04,0x050x40,0x43,0x51, 0x54,0x62,0x65,0x07,0x17,0x27,0x37,0x08,0x18,0x28, 0x38,0x09,0xl9,0x290x39,0xlb,0x2b,0x3b。

上图可以看到,此处的限定词码(Qualifier Code)0x07

我们用一张图来概括

工控DNP3协议及安全风险细解


好了,到这个地方,DNP3协议规约大致就是这样,那么下面我们来看看它的安全问题。

 

安全风险分析:

 

DNP3协议和大多数工控协议一样,在TCP上进行传输时都是未作加密处理的,所以存在中间人攻击和数据重放攻击等安全风险。

本文以文件读取为例子,来讲讲通过协议构造任意文件读取。

 

 

通过下图我们可以知道,读取文件的函数操作码为0x19

工控DNP3协议及安全风险细解


按照读取文件的大致过程为

打开文件(Open)->读取文件(Read)->关闭文件(Close)

所以,我们需要发送三次完整的数据包就可以读取到文件了,

 

现在我们来构造数据包

10个字节为固定字节,所以我们分成两段,第一段定义为Header,第二段定义为Body

 

Header:数据头(0564)+数据包总长度(后面总长度)+链路控制c4+目的源地址+校检码

Body这个地方只有几处需要注意的地方,其他的地方直接置0即可,然后就是一些固定的格式操作码,我们不用改变它,所以构造出来的格式就为

 

链路控制c1+打开文件操作码(19)+数组01+后面字节总数+文件名偏移地址+文件名长度+文件句柄+文件操作码+文件缓冲区+文件名

 

解决完这些格式之后呢,我们就只需要再解决CRC校检的问题就可以了

DNP3使用的是dnp16的校检,也就是每隔16位就检查一次,我们这里用python来解决这个,在python里面有个包叫做crccheck,它里面已经有了dnp16这个校检函数,所以我们可以直接拿来用,最后根据规约格式,就可以很轻松编写出代码来

我们打开DNP3服务器,将开放20000端口

工控DNP3协议及安全风险细解


利用我们写好的工具进行测试,就可以成功读取win.ini文件,这里只能读取一部分文件,想要读取全部文件需要计算偏移

工控DNP3协议及安全风险细解


通过抓包,我们可以看到具体的流量情况


工控DNP3协议及安全风险细解


具体的通信过程为:

1. 请求打开文件

工控DNP3协议及安全风险细解


2. 然后DNP3服务器返回文件句柄等信息

工控DNP3协议及安全风险细解


3. 我们拿着这个句柄去读取文件的内容

工控DNP3协议及安全风险细解


4. 最后返回我们读取的文件信息

工控DNP3协议及安全风险细解


5. 关闭文件句柄

工控DNP3协议及安全风险细解


总结

通过对DNP3协议的大致分析,我们可以知道,DNP3TCP上传输时如果通信双方没有约定一定的加密技术,那么很容易被发包伪造数据,对设备进行攻击。


引用:

https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-dnp.c

https://www.anquanke.com/post/id/187221

https://www.docin.com/p-630530021.html?docfrom=rrela


原文始发于微信公众号(花茶安全攻防Team):工控DNP3协议及安全风险细解

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月22日23:28:41
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   工控DNP3协议及安全风险细解http://cn-sec.com/archives/933620.html

发表评论

匿名网友 填写信息