工控渗透框架——PLC密码检测
时间:2020-06-05 作者:安帝科技
前言
上一篇《信息收集篇》中我们讲了如何使用ISF框架发现工控设备,那么有些小伙伴就会问了,发现工控设备之后能做些什么呢?答案是很多,比如:查看设备有没有密码保护?有密码保护能不能破解?破解后都能做些什么等等问题。为了让大家循序渐进地学会工控相关的安全攻防,我们需要先学习一些工控的相关知识。本篇我们就来讲讲与暴力破解相关的基础知识,为后续暴力破解做好准备。
首先,为了能让工业机器相对“智能”,就需要一个可以控制这些机器的设备来控制它,而这个设备应该具备通用性和可复用性,这就是plc。一个通用的,可重复改写的逻辑控制设备。人们可以通过编写一些程序下载到plc中,然后plc通过读取这些程序以达到“智能”控制的效果。
好了,大家都知道plc的基本功能后,那么就会有一个永恒的问题,一般有用的东西就会涉及到安全问题,既然你能通过编写程序让plc控制设备,那么就会有别有用心的人也想控制它,所以,这里就涉及到plc的保护机制。plc的保护机制和我们常用的手段一样,就是通过设置密码进行保护。了解完这些基本知识之后,让我们来看一下plc是怎么进行密码设置的,设置后是怎么保护plc的。还是和以前一样,我们通过工控实验箱来演示,实验箱实物图如下:
注:实验箱中各设备的功能与连线这里就不多介绍了,不知道的同学可以看上篇文章。
连接PLC
实验箱通电后,用一根网线将电脑与实验箱进行互联,然后就可以使用“STEP 7-MicroWIN SMART”配置plc,以及编写程序,下载程序等操作。(不同厂家和不同型号的PLC需要不同的控制软件,我们的PLC型号是SMART200)。
点击“PLC”—“查找CPU”,扫描到一台PLC设备(为什么是扫描的是CPU而不是扫描PLC呢?请自行百度)。
通过扫描识别到PLC后,点击“确定”该软件就与plc成功连接,当前界面就是PLC编程界面。
密码配置
双击“CPU ST20”打开“系统块”设置页面,在“安全”标签中密码设置选项中就可以设置密码了,密码保护一共分为4个级别,S7200 SMART CPU 的默认密码级别是“完全权限”(1 级):
完全权限(1 级):提供无限制访问CPU所有功能。
读取权限(2级):用户可以不受限制地读取和写入CPU数据和上传程序。下载程序、强制存储器位置或对存储卡进行编程时需要密码。
最低权限(3级):用户可以不受限制地读取和写入CPU数据和上传程序。上传或下载程序、强制存储器位置或对存储卡进行编程时需要密码。
不允许上传(4 级):该级别的密码保护将阻止程序上传(即使输入正确的密码)。该选项不允许项目比较。其它CPU功能的保护方式与最低权限密码相同。
知道了PLC密码保护的相关知识后,我们随便找一个密码级别(这里我们使用只读),设置好密码后下载程序到PLC中,然后再次通过下载程序就需要输入密码(上面密码保护级别里说过,只读级别下载时需要输入密码),结果如下图所示:
PLC密码保护检测
废话不多说,直接上图:
是不是很简单,如果还想验证其它密码保护级别,可以通过上面的步骤重新修改PLC的密码保护级别,然后再通过ISF中的s7_200_password_check模块进行验证。说到这个模块仔细的同学应该已经发现,上一篇文章里提到的从github中clone的ISF项目里没有s7_200_password_check模块啊,你这个模块是哪里来的?
ISF模块添加
如上面细心网友发现的那样,github中的ISF项目确实没有今天要讲的这个模块,这也就是我们为什么要开发这个框架的原因,它是一套攻击框架,大家可以根据自己对PLC的研究成果,添加不同的功能模块,最后将所有的攻击模块都集成到这个框架中,我们就可以拥有一个强大的工控攻击工具。
接下来我们就通过上面的案例讲解一下,如何给ISF添加一个PLC密码检测模块,Iet’s go!
首先,你需要在ISF的module目录(例:/home/one/soft/isf/module/exploits/Siemens)下创建两个文件,名字任意(例:s7_200_password_check.pys7_200_password_check.xml)
py文件
xml文件是用来配置py文件的参数,以及关联ISF框架的,而真正完成扫描或攻击功能的模块是在py里面编写的,下面我们来看s7_200_password_check.py模块是如何编写的。
#encoding:utf-8
Importsocket
Importtime
fromcore.exploit import *
classCheck_passwd(BaseExploit):
register_info = {
‘ID’: ‘ICF-2020-F0010009’,
‘Name’: ‘s7-200检查’,
‘Author’: ‘one’,
‘License’: ISF_LICENSE,
‘Create_Date’: ‘2020-06-04’,
‘Description’: ”’可以显示密码状态”’,
}
register_options = [
mkopt_rport(102)
]
def exploit(self,*args,**kwargs):
self.ip = self.TargetIp
self.default_port =int(self.TargetPort)
if self.default_port != 102:
return False
try:
sock =socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((self.ip,self.default_port))
pp=”0300001611e00000000100c0010ac1020100c2020101″.decode(“hex”) sock.send(str(pp))
data = sock.recv(1024)
pp=”0300001902f08032010000662100080000f0000001000101e0″.decode(“hex”) sock.send(str(pp))
data = sock.recv(1024)
time.sleep(0.1)
pp=”0300001f02f080320100000004000e00000401120a100200020000030005d0″.decode(“hex”) sock.send(str(pp))
data = sock.recv(1024)
data2 =data.encode(“hex”)
str_tmp = data2[-1:]
print data2
if str_tmp == ‘1’:
print “完全读取!”
return True
elif str_tmp == ‘2’:
print(“只读!”)
return False
elif str_tmp == ‘3’:
print(‘最低权限!’)
return False
elif str_tmp == ‘4’:
print(“不允许上传!”)
return False
else:
print(“异常状态!”)
return False
except Exception as e:
print e,”执行错误”
return False
MainEntry(Check_passwd,__name__)
代码解释:
import:三个导入自然不用说了
Check_passwd:构建模块时,一定要使用类,而不是函数,其次一定要继承
BaseExploitexploit:这个方法就是在ISF中配置完各种参数后,用于执行扫描或攻击的方法pp:这里发送的数据大家先不用关心,后续文章会慢慢教大家怎么解析PLC协议
str_tmp:用sock发送完3组数据,并接收返回值后,取出最后一位进行判断,看到这里大家应该就能明白上面4种密码保护级别的1234是什么意思了吧
MainEntry:是将ISF框架接收到的参数发送给当前类,然后将检测结果显示出来
总结:
好了今天的内容就讲到这里,是不是很简单,有没有想继续学下去的冲动,那就关注我们,一步一步用实例为你打开另一扇门。