首页
论坛
课程
招聘
[原创]被动式FUZZ在工控漏洞挖掘中的应用
2020-11-27 10:28 8490

[原创]被动式FUZZ在工控漏洞挖掘中的应用

2020-11-27 10:28
8490

背景

在如今的工业系统漏洞挖掘中,大规模自动化的fuzz技术越来越流行,fuzz技术成为挖掘工业系统漏洞的有利工具。然而,这种技术往往针对的是服务端,例如fuzz目标为PLC,模拟器,HMI,上位机的服务等。而针对客户端的fuzz技术确很少人提及。本文从实战出发,以施耐德的上位机软件unity pro作为例子,通过被动式fuzz技术发现存在UMAS客户端协议栈中的漏洞。

Unity Pro

Unity Pro是M340/M580对应的上位机软件,通过该上位机软件可以进行PLC编程,上传和下载工程。该软件和PLC之间是通过施耐德私有的UMAS协议进行通信,由于该协议比传统的modbus复杂得多,有可能在协议栈的实现会出现安全性问题。
图片描述
UMAS协议
UMAS协议是modbus协议的上层协议,使用的是90功能码,也称“施耐德90功能码”协议。该协议比普通的modbus协议权限要大,能执行更多敏感操作,比如启动或者停止等。对于施耐德PLC来说,曾经爆出很多个存在于UMAS协议上的问题,然而基本上是服务端协议处理导致的拒绝服务。对于服务端的fuzz,最简单就是使用boofuzz一类工具进行fuzz,但是对于客户端,就需要另一种方法进行fuzz。UMAS协议如下图所示:
图片描述

Fuzz概述

主动fuzz

顾名思义,主动fuzz是针对服务端主动发包,通过预定义的一些协议字段填充变异值进行fuzz,或者直接变异发送的数据。
图片描述

被动fuzz

之所以叫被动fuzz,是因为是在服务器对客户端发数据包响应的时候,通过中间人攻击的方式修改响应包数据,而不是主动变异数据包来发送。通过这种方法可以直接fuzz客户端,发现客户端在处理数据的时候的安全性问题。
图片描述

fuzz实战

中间人

前面介绍了被动式fuzz是通过中间人来实现的,那么在unity pro中如何进行中间人攻击?通过简单设置连接ip为127.0.0.1。
图片描述
然后在本机上运行中间人攻击脚本,由于我们是修改响应数据的,所以只在响应那块改就行,发送数据那块不需要修改。
图片描述

变异

变异策略可以是多种多样的,比如最简单的比特位反转,在这种情况下,本人采用的是最简单的单比特反转,随机修改某一位,这里值得注意的是应该修改UMAS协议中的payload部分,而不是数据包头。
图片描述

自动化

最简单的方法就是使用一些模拟按键的方法触发客户端的操作,执行一些读/写值,上载和下载工程这些操作,这样可以完全实现自动化而不需要人工操作。当然,如果为了追求更高的fuzz速度,可以通过注入dll的方法调用不同的发包函数来自动化该流程,不过这种方法需要大量的逆向工程。为了简单起见,我们选取最简单的模拟按键,编写按键脚本进行自动化操作。
图片描述

发现漏洞

在不到5分钟的情况下,通过我写的被动式fuzz使得unity pro客户端直接崩溃。
图片描述
通过调试分析发现该漏洞是堆缓冲区溢出,可能会导致拒绝服务甚至远程代码执行,总得来说这个漏洞危害是比较大的。该漏洞已经上报给施耐德官方,目前施耐德已经确认了该漏洞的存在。

利用场景

在实际的攻击中,在不同场景下可以利用该漏洞:
1.当攻击者控制了网关之后,可以通过该漏洞对unity pro客户端发起攻击。
2.当攻击者通过内网中的IP劫持,如ARP攻击来劫持会话从而发起攻击。
3.通过社工的方法欺骗受害者连接恶意的PLC服务端也可以对该漏洞进行利用。

总结

本文通过施耐德unity pro作为例子,详细介绍了使用被动式技术发掘客户端漏洞的技术。可以看到出来,虽然施耐德在服务端修复了很多漏洞,但是客户端由于很少人去进行深入研究,所以客户端仍存在着相对较多潜在的安全问题。本文是为数不多的对工控软件使用被动fuzz技术的文章,希望给大家带来一些技术上的启发。


【看雪培训】《Adroid高级研修班》2022年夏季班招生中!

收藏
点赞4
打赏
分享
最新回复 (10)
雪    币: 9472
活跃值: 活跃值 (9055)
能力值: ( LV12,RANK:240 )
在线值:
发帖
回帖
粉丝
pureGavin 活跃值 2 2020-11-27 10:58
2
0
mark,感谢分享
雪    币: 20
活跃值: 活跃值 (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PanTotoro 活跃值 2021-12-22 23:18
3
0
大佬,工控fuzz或者工控漏洞挖掘如何入门?需要学习那些前置知识?
雪    币: 10662
活跃值: 活跃值 (10983)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
wmsuper 活跃值 5 2021-12-23 09:46
4
0
PanTotoro 大佬,工控fuzz或者工控漏洞挖掘如何入门?需要学习那些前置知识?
1.提取固件、逆向客户端对协议格式逆向
2.编写fuzz模板 ,这里用boofuzz
3.对设备进行fuzz 
4.发现漏洞后使用硬件调试方法定位崩溃点 
5.在工控设备中的RTOS系统进行利用漏洞(RCE)
雪    币: 20
活跃值: 活跃值 (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PanTotoro 活跃值 2021-12-23 11:03
5
0
wmsuper 1.提取固件、逆向客户端对协议格式逆向 2.编写fuzz模板 ,这里用boofuzz 3.对设备进行fuzz 4.发现漏洞后使用硬件调试方法定位崩溃点 5.在工控设备中的RTOS系统进行利 ...
谢谢大佬,我基本上属于0基础。然后fuzz模板很多也看不懂,只会跟着帖子照猫画虎,最后很多细节都不明白,也不知道如何将模糊测试用例发送到工控设备,现有工具也不知道它们怎么发送的,更不清除如何调试崩溃点。有些大神写的帖子非常深奥,会跳过很多东西,我在实际做的过程中感觉很没有头绪。目前我主要做工业协议fuzzing和协议逆向,比如Modbus TCP,EtherCAT,以及一些未知协议,例如发那科工业机器人协议,暂时不准备研究软件fuzzing,很多情况下无法获取固件。大部分相关文献里都不提供源代码,很多都是空话,感觉要放弃了。
雪    币: 220
活跃值: 活跃值 (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pickist 活跃值 2021-12-23 14:14
6
0
大佬,求中间人抓包脚本
雪    币: 10662
活跃值: 活跃值 (10983)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
wmsuper 活跃值 5 2021-12-23 16:05
7
0
pickist 大佬,求中间人抓包脚本
# coding:utf-8
import select
import socket
import struct
import hexdump
import binascii
import random
from socketserver import StreamRequestHandler, ThreadingTCPServer
PLC_IP='10.65.60.81'
PLC_PORT=502

def modify_pkt(data):
    
    return data
class SocksProxy(StreamRequestHandler):
    def handle(self):
        print('Accepting connection from {}'.format(self.client_address))
        port = PLC_PORT
        address=PLC_IP

        try:

            remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote.connect((address, port))
            bind_address = remote.getsockname()
            print('Connected to {} {}'.format(address, port))
        
        except Exception as err:
            logging.error(err)

        self.exchange_loop(self.connection, remote)
        self.server.close_request(self.request)
    def exchange_loop(self, client, remote):
        while True:
            # 等待数据
            r, w, e = select.select([client, remote], [], [])
            if client in r:
                # 上位软件发给下位机的数据
                data = client.recv(4096)
                
                if remote.send(data) <= 0:
                    break
            if remote in r:
                data = remote.recv(4096)
                # 修改下位机发给上位软件的数据
                data=modify_pkt(data)
                hexdump.hexdump(data)
                if client.send(data) <= 0:
                    break
if __name__ == '__main__':
    
    server=ThreadingTCPServer(('0.0.0.0', PLC_PORT), SocksProxy)
    server.serve_forever()


最后于 2021-12-23 16:06 被wmsuper编辑 ,原因:
雪    币: 10662
活跃值: 活跃值 (10983)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
wmsuper 活跃值 5 2021-12-23 16:15
8
0
PanTotoro 谢谢大佬,我基本上属于0基础。然后fuzz模板很多也看不懂,只会跟着帖子照猫画虎,最后很多细节都不明白,也不知道如何将模糊测试用例发送到工控设备,现有工具也不知道它们怎么发送的,更不清除如何调试崩溃点 ...
1.如果是零基础建议从fuzz 最简单的modbus开始,自己实现一个fuzz模板都是入门级的。
2.复杂的工控协议有签名算法和加密算法,对这些协议进行fuzz必须从逆向算法开始。
3.目前国内大的工控安全研究环境就是这样,大多数都是为了过等保,连基础的对工控漏洞挖掘的技术很少人会去分享,更别说源码了,可以多多关注国外工控安全团队的安全研究。
雪    币: 20
活跃值: 活跃值 (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PanTotoro 活跃值 2021-12-23 19:12
9
0
wmsuper 1.如果是零基础建议从fuzz 最简单的modbus开始,自己实现一个fuzz模板都是入门级的。 2.复杂的工控协议有签名算法和加密算法,对这些协议进行fuzz必须从逆向算法开始。 3.目前国内大 ...
嗯,谢谢大佬。我也做协议逆向,不过国内做这个的太少了,稍微深一点的研究资料也完全看不懂,外文文献也不知道他们到底在干嘛。我试着做一做协议fuzzing和逆向,不行就暂时放弃转异常检测了。
雪    币: 40
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
GreatDane 活跃值 2021-12-29 16:07
10
0
unitypro.exe和ratsrv之间通过Windows ALPC通信,模拟鼠标点击触发法入门简单但是拓展性差,可以尝试编程模拟ALPC client(unitypro)去控制ratsrv去测试rat.dll中的全部function,这可能更”自动化“,拓展性自然也更好。
雪    币: 220
活跃值: 活跃值 (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pickist 活跃值 2021-12-30 10:07
11
0
wmsuper pickist 大佬,求中间人抓包脚本 #&nbsp;coding:utf-8 import&nbsp;select imp ...
感谢大佬
游客
登录 | 注册 方可回帖
返回