前几天在TSRC换了本《白帽子讲WEB扫描》,昨天凑空拜读了一遍。整体读下来的感觉是,书中关于WEB漏洞扫描器设计与开发所需的知识描述得比较全面,包括一些坑点也有涉及。但对于每一方面的内容描述得不够深入不够细致,适合从0开始学习设计开发漏洞扫描器的工程师,给其提供一些设计思路,避免一些不必要的坑点。当然设计开发扫描器本身就是一个很复杂的工程,作者也不可能在一本书中详细描述,再者有些坑还得自己踩过才知道。
本篇文章作为《白帽子讲WEB扫描》一书读后感,或者说读后总结,也算是本人对漏洞扫描器设计与开发的一次总结。在正式开始总结之前,先感谢下本书作者:刘漩,本文很多内容均借鉴此书,若有转载本文,请务必说明出处。
本文涉及到的知识点比较多,我先列个大致介绍目录,请容我慢慢补充完善.....因为篇幅有限,有些内容本文也只做简单介绍(比如爬虫开发),后面我会对每块内容单独成文详细介绍。
关于为何要开发一款漏洞扫描器,以及不同扫描器(白、黑、灰)的区别、其作用、有何优缺点等问题,此处省略一万字……
本文主要介绍以下两种扫描器的设计与开发:1)基于URL的WEB漏洞扫描器、2)基于指纹的漏洞扫描器。目前市面上很多商业扫描器是包含这两种扫描功能的,但为了能更清楚的知道其原理,我觉得有必要分别介绍。有必要说明一下的是,本文介绍的扫描器均是主动型扫描器
,即会主动发起http请求的。至于被动型扫描器,其主要利用http代理(burpsuite)或者流量镜像(绿盟某扫描器)的方式进行扫描,即不会主动发起请求,只是获取请求的内容进行分析。
从本节标题至少可以读出两点信息:第一漏洞扫描器的输入源是URL,第二漏洞扫描主要针对WEB。开发这样一款扫描器至少需要解决以下两个问题:
如何采集输入源(即采集网站URL)
基于流量清洗
基于日志提取
基于爬虫爬取
如何调用扫描插件(即对URL进行扫描)
一般在甲方开发扫描器会涉及到此块内容,因为基于流量获取url是对业务影响最小,且覆盖面最全的一个方案。而一般乙方开发的商业扫描器很多没有涉及到流量清洗,因为部署等难点。
可以从企业入口主交换机上镜像一份流量到某台服务器上,再通过一些工具从服务器网卡上获取流量,清洗后提取url、post_body、response等数据。获取流量的工具有很多,比如justniffer,suricata等。
一般流量中是没有https数据的,因为无法解密;流量中包含用户认证信息,如何优雅地处理,使之对用法没有影响。
一般在甲方开发扫描器会涉及到此块内容,因为基于日志获取url也是对业务影响很小,且覆盖面比较全的一个方案。
怎么在服务器上配置nginx收集日志就不说了,如果对于nginx不熟悉,可移步学习:https://thief.one/2017/08/22/1/
一般不包含post_body,以及response数据,因为每天产生的日志量非常庞大,如果需要存储这么多数据的话,成本很高,所以一般在服务器上只记录url、时间戳等简单信息。
区别于一般的网络爬虫,漏洞扫描涉及到的爬虫是针对同一个站点爬取所有URL的爬虫。想要开发一款好用的爬虫,前提是必须对HTTP协议熟悉。本文不展开介绍http协议,只总结开发爬虫过程中一些注意的点。
注意不是所有请求都用HEAD,而是一部分不需要响应主体的请求可以用HEAD代替GET。head请求唯一区别与get请求的是其不会返回响应主体,只有响应头。
有些网站有最基础的反爬策略(检测请求头),或者有些页面需要登录凭证(cookie认证),因此在爬虫中也需要在请求头中加上cookie。
当我们每次请求一个域名时,都会先向dns服务器获取域名对应的ip地址,而这个解析记录一般情况下是不太会变的,因此可以一开始爬取的时候解析一次,然后缓存到系统内,后面的请求直接从系统中获取,可以节省资源。
涉及获取不同标签内的url,以及处理动态链接、静态链接,同源策略,重复url去除等。
页面跳转主要分为服务端跳转、客户端跳转,具体介绍可移步:https://thief.one/2016/10/10/%E9%BB%91%E5%B8%BDSEO%E4%B9%8B%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC/。客户端跳转对用户是可见的,即在第一次请求时,响应码为301或者302,在响应头的Location中返回了跳转的地址,第二次请求跳转的地址,再返回结果;而服务端请求对用户不可见,即只有一次请求,跳转是在服务端处理的。
一般网页不存在,响应码便是404。但有些网站为了对用户友好,当访问不存在的页面是会跳转到一个存在的页面(响应码302、301),或者页面直接显示主页内容(响应码200),或者显示404提示页面(响应码200)。针对这些复杂的情况,仅仅对响应码进行判断显然是不够的,需要结合响应码跟页面内容。
解决方案:先访问一些不存在的页面,获取页面内容,标为C1;再访问目标页面,若响应码为404则表示页面不存在,若不为404,则比较页面源码C2与C1的相似性,若相似也表示不存在。
关于如何判断一个页面为404页面的详细内容,请移步:https://thief.one/2018/04/12/1/
去除重复的URL,以免重复抓取相同的页面,当然对于一些相似的URL也需要处理。处理方案可以是将url hash以后存入内存中,比如python的list对象中,然后判断新的url的hash在不在此list中,不存在则将url放入队列进行爬取。
具体可使用汉明距离计算,这对识别404页面有很大的帮助。
有些时候由于网络延迟,会导致请求断开,这时候就需要重试,直到次数达到重试次数阀值。
如果单纯只是抓取页面中的URL,会少了很多请求,比如点击事件、表单发送等。获取表单信息比较简单,只要匹配页面中的form标签,以及其内部的input标签。当需要爬虫能够自动填充这些字段内容,比如电话字段,需要填充正确的电话号码,因为大部分网站会在前后端对数据格式进行校验。这就需要维护一个表单字段库,对于每个常见的字段都设置了常用值。
目前很多网页通过ajax发送请求,因此也要求我们的爬虫能够解析ajax请求。包括一些页面上的事件,也需要爬虫去触发。
web2.0与web1.0最大的区别,就是增加了很多动态的内容,很多页面内容是js动态生成的。因此这便要求我们的爬虫有解析js的能力。这里推荐几个模块,phantomjs、chromeheadless等。
简单来说,漏洞扫描器主要分为输入与扫描两大块功能,光有输入源还不行,必须得有扫描能力,而扫描能力主要依靠扫描插件的堆积。
从流量中可以获取到一些url,以及post的数据信息(其中包含了认证),由于我们设计的是主动型扫描器,需要主动发起请求,因此如何去优雅地重放这些请求变成了一个难题。由于有些网站cookie过期时间很长,重放请求势必会造成对业务的影响,而不使用cookie,则很多页面无法访问到。
一种解决方案可以是对cookie进行替换,换成测试账户的cookie,这样就对用户没有影响了,但是其中的坑也很多。
从本节标题也至少可以看出两个信息:第一漏洞扫描器的输入源是服务指纹,第二漏洞扫描针对WEB+服务。
开发这样一款扫描器至少需要以下两个步骤:
采集输入源(即采集系统指纹)
端口扫描
指纹扫描
指纹匹配
调用扫描插件(即匹配指纹进行漏洞扫描)
可以使用python的socket模块开发tcp扫描,或者用nmap、masscan、zmap等开源工具进行扫描。
可以使用nmap扫描,因为nmap内含了很多指纹探针,可以识别出大部分服务指纹信息。针对web指纹,则需要先发起http请求,获取响应内容,再借助web指纹库识别,或者借助开源的指纹扫描器,比如Whatweb等。
只有指纹没有指纹库也是不行的,指纹好比是一些身份信息,而我们最终是要定位到某个人,因此还需要有一个指纹库,将指纹信息与人对应起来。
以上简单介绍了设计开发两种扫描器所需要解决的问题,而站在整体角度看,需要解决的问题还远远不够。比如当需要扫描的系统非常庞大时,如何进行分布式的部署,这就要求我们的扫描框架满足分布式部署的需求。
热门文章推荐: