深度长文,看完的我敬你是条汉子。
前言
人工智能技术下的分支有很多,有机器学习、深度学习、强化学习、联邦学习等。笔者直观的理解,强化学习较其他人工智能技术而言,擅长决策和多步决策,大名鼎鼎的AlphaGo就是用强化学习做决策的,而“决策”二字才更能体现人的智能,也即强化学习更可能接近人的智能。
纵观强化学习发展史和应用史,在应用于网络空间安全领域方面,笔者找到为数不多的一些资料。这里挑选出三个有代表性的例子来实践,分别是强化渗透测试、强化入侵检测、强化攻击绕过和反绕过策略,其中有强用强化学习疑似灌水的例子,也有有实际意义的强化学习的安全应用。
强化渗透测试
先来看看第一例,记得今年三月份面试头条的时候,向面试官提到过Black Hat上有一款基于深度强化学习的自动化渗透工具,当时没有仔细研究,只是觉得这种应用属实新颖,如今深入分析后,发现pr的意义大于实践的意义。
关于这款名为DeepExploit的工具,在网上找到几篇分析,但大多是翻译了这款工具的readme.md,又或是没有强化学习领域的背景知识,没有分析到核心算法,即深度强化学习到底怎么被使用来打造自动化渗透工具。
先看看这款工具公开的Presentation:
- February 17th,2018: SECCON YOROZU 2018
- August 9th,2018: Black Hat USA 2018 Arsenal
- August 10th,2018: DEF CON 26! AI Village
- October 24th,2018: CSS2018
- November 3rd,2018: AV TOKYO 2018 Hive
- December 6th,2018: Black Hat EURO 2018 Arsenal
初次看到这里,笔者的内心是激动的,终于看到强化学习被成功用来强化渗透测试了。但是仔细一看介绍,是要配合metasploit来渗透,可以说是基于深度强化学习的metasploit渗透工具,更具体的说,这款工具只是帮助使用者使用metasploit渗透时,根据目标机器状态快速决策出大概率能执行成功的payload。那么这里就有个比较明显的问题是:这款工具的天花板受限于metasploit本身的能力。
当掌握DeepExploit的基本描述后,接着(不分析源码)来试用一下。先在kali中按readme安装好DeepExploit,再利用metasploitable2安装了一个靶机,接着使用DeepExploit来做攻击训练,观察其工作流程。
先通过Nmap扫描端口和服务信息
再载入metasploit的exploit模块和payloads,并基于这两者构造exploit_tree,exploit_tree可以看成是json格式的metasploit漏洞库
接着对Web端口及服务做精细化分析,通过爬虫和分析HTTP响应包,规则匹配,提取Web服务信息,这其中包括了对CMS进行指纹识别
然后根据端口选择metasploit中可以利用的exploit模块
最后开始训练,找到了靶机的漏洞
到这里为止,训练结束,测试的时候一击即中。看上去可以完美地结束了,然而到这里还是没法回答笔者心中的疑惑:深度强化学习到底是怎么被用来帮助metasploit做决策的。我们的分析才刚开始。
在开始之前,首先得补习一下强化学习的基本知识。强化学习的学习思路和人类似,是在实践中学习,比如学习走路,如果跌倒了,大脑就会给出一个负反馈和负奖励值,说明走路的姿势不对,然后我们从跌倒的状态中爬起来,继续行走,如果正常走了一步没有跌倒,大脑就会给出一个正反馈和正奖励值,我们就会知道这是一个好的走路姿势,不断重复此过程。
强化学习大概有8个基本要素:环境的状态S、个体的动作A、环境的奖励R、个体的策略π、个体在策略π和状态S时,采取行动后的价值V、奖励衰减因子γ、环境的状态转换模型P、探索率ϵ。这其中环境的状态S、个体的动作A和环境的奖励R是比较简单且基本的三要素。总的来说,强化学习就是个体agent和环境的不断交互不断进化的过程。基于环境此时的状态S,个体agent根据策略π和价值V选取一个动作A并执行,得到下一个状态S'和奖励值R,不断循环,直到满足特定条件退出。
强化学习和监督学习最大的区别是它没有监督学习准备好的训练数据和输出值,强化学习只有奖励值。同时强化学习的每一步与时间顺序前后关系紧密,而监督学习的训练数据之间一般是独立的,没有这种前后的依赖关系。
有了强化学习的基本知识后,结合源码继续来分析DeepExploit。笔者分析完自问自答列出了9个问题,搞清楚这些问题,基本上就可以真正掌握这款工具了。
- 主循环结构?主循环迭代5000次&&内循环迭代20次?5000是指主循环总共最大能执行5000步,每次选择payload算一步。20次是指固定exploit模块,对每个exploit,最多可以选择20次payload。
- 用的什么强化学习算法?A3C,Asynchronous Advantage Actor Critic,一种分布式训练的强化学习高级版算法。如果选择10个线程,那么每个线程都可以迭代主循环的5000次。
- 此场景下,强化学习八大基本要素之一的动作要素,作者是如何定义的?动作是选择exploit还是payload?针对端口的可利用exploit模块们,随机固定exploit模块,动作空间是此exploit模块下可以利用的payloads。
- 状态是如何定义的?以端口为索引,状态为:系统类型,产品/服务名称,版本号,exploit模块索引,target索引。笔者发现作者定义的状态可能有问题,作者定义的状态有五个参数,其中四个参数都是固定不变的,只有一个target索引在变,分析了代码,发现target索引的变化完全是随机的,不是由动作action引发的状态变化,同时各个状态之间可能也没有必然的内在联系。
- 如何训练和测试?前期准备:Nmap扫描,获取端口信息,载入exploit和payload得到exploit tree,针对web端口精细化操作,例如通过爬虫和分析HTTP响应包,使用静态规则和ML得到产品名称和版本,根据端口,选择msf中available的exploit modules。之后开始训练:以单线程为例,开启主循环:设置初始状态(状态为:系统类型,产品/服务名称,版本号,exploit模块索引(exploit模块),target索引(攻击的目标类型),同时随机选择一个端口、exploit module,target),开启循环:选择当前状态的动作(选择此时exploit module对应的payload list中的一个payload作为动作执行),得到下一个状态(target索引会随机改变),循环,跳出,跳到主循环,循环,跳出主循环。
- 如何多次增量训练?即训练记忆如何持久化?每次训练加载以往训练结果,即神经网络中的参数,再训练更新参数,做决策。
- 有哪些问题/局限性?天花板的问题,DeepExploit的上限受制于metasploit框架的天花板。状态的问题,上面已经说到的状态的定义可能有问题,那么这个问题可能会导致的问题是,第一次迭代可能需要执行一百次动作来获取可以执行成功的payload,第二次迭代可能需要执行十次动作来获取payload,最后可能一次迭代就可以获取payload。我们想要的结果其实就是一个动作,一个payload,而不是一条动作链。这直接导致了这种训练与传统的暴力破解找payload有什么区别呢?看上去在用强化学习解决问题,但是实际运行的思想可能和穷举型的暴力破解的思想差不多。平行世界的问题,训练VS测试永远是个难题,但在此处问题更甚,搭建的漏洞环境VS真实漏洞场景,感觉在过家家,搭建100个靶机训练可能都解决不了一个实际问题。作者的本意可能是想仿照AlphaGo,通过输入大量棋盘数据,学习人类对弈,通过更多的渗透师使用,学习渗透师们在各种实际场景下如何做决策,来缓解此问题。
- 可以怎样改进?在天花板范围下,尽量挖掘出最大潜力,比如不止是做payload的决策,也可以做exploit模块的决策,根据端口直接选择大概率能利用成功的exploit模块和payload。升高天花板,可以开发自己的漏洞脚本,自定义exploit和payload。状态的问题还没想好如何优化,可能这个场景就不太适合使用强化学习,因为个体对环境(目标机器)执行动作(exploits和payloads),环境的状态可能一直一成不变或是状态之间无内在联系。
- 实际意义如何?选取的问题点比较小,只是做payload的决策,同时程序总体执行的时间很长。pr的意义>实战意义,实际意义可能不大。
针对一些疑惑,笔者给DeepExploit的作者发了封邮件,希望能得到作者的解惑。
强化入侵检测
再来看看第二例,国外有研究者使用强化学习来做入侵检测。作者使用NSL-KDD数据集,得到特征数据和标签数据。把特征定义为状态,标签定义为动作,也即把入侵检测问题抽象成强化学习问题:对某一条流量的状态(特征数据)做出是否告警的动作(标签0代表不告警,标签1代表告警),整个算法流程能跑的通,性能也还可以。但是这里笔者觉得可能有两个问题,其一是问题的抽象,直观来说流量应该定义为动作action,机器本身的状态定义为状态,不过作者这种定义一定程度上也能说得通。其二是状态的问题,作者直接选取下一条数据的特征作为下一个状态,也就是说无论对上一条数据做出的动作action是0还是1,都不影响下一个状态,每时每刻的状态不受动作影响,都是固定的。笔者认为这种把入侵检测问题抽象成强化学习的建模方式不太合适,仿佛又回到了有监督学习。如果把是否告警改成是否拦截,选择拦截动作的话,那么下一个状态数据可能就会变化了,这也许更契合强化学习的问题抽象,但是这种建模方式可能会导致业务问题,同样也不是最理想的强化学习建模。
强化安全策略
最后看强化学习安全应用比较成功的第三例,国内外有研究者使用强化学习来做攻击绕过和反绕过的策略选择。比如兜哥的书《Web安全之强化学习与GAN》中,有三个相关的例子,分别是智能提升恶意程序检测能力、智能提升WAF的防护能力和智能提升垃圾邮件检测能力。这三个例子核心思想大体相同,定义payload的特征数据为状态,定义常见攻击绕过方式为动作,比如waf中的16进制编码,大小写混淆,插入注释等。原始状态连续经过几个动作,比如原始状态->动作a->状态a(原始状态执行动作a)->动作b->状态b(状态a执行动作b)->动作c->状态c(状态b执行动作c)->每一个状态都会被传统机器学习模型检测,如果检测到的话,继续执行绕过动作得到下一个状态,直到绕过成功。如果绕过成功的话,每一步执行的动作ation组合起来,就是一条可以绕过传统机器学习模型检测的一环扣一环的bypass链路。强化学习在安全方面的这种应用就比较有意义,相较于传统的爆破,这种是“聪明的爆破”。同时可以将最后传统机器学习模型不能成功检测的状态数据(特征数据),作为训练数据,对机器学习模型重新训练,以提升模型防御bypass的能力。
尽管强化学习更可能接近于人的智能,理论上来说强化学习的天花板远高于机器学习、深度学习等技术,但是因为各种各样的原因,导致强化学习在安全领域的应用还很局限,这其中的原因和解决方法需要大家一起来挖掘。
Ref
- Deep Exploit:Fully automatic penetration test tool using Deep Reinforcement Learning
- gym-network_intrusion
- Reinforcement Learning for Anomaly Detection
- anomaly-detection-through-reinforcement-learning
- 《Web安全之强化学习与GAN》
- DeepExploit工具调研
- 刘建平Pinard的强化学习优质Tutorial:偏理论(笔者感受)
- 莫烦的强化学习优质Tutorial:简单易懂(笔者感受)