巡风源码浅析之 Vulscan 分析篇

巡风是一款适用于企业内网的漏洞快速应急、巡航扫描系统,通过搜索功能可清晰的了解内部网络资产分布情况,并且可指定漏洞插件对搜索结果进行快速漏洞检测并输出结果报表。

开源地址:

https://github.com/ysrc/xunfeng

0x00: VulScan 介绍

查看介绍前,请先查看《巡风源码浅析之 Nascan 分析篇》 的 0x01:分析准备,文章地址如下:

https://landgrey.me/xunfeng-nascan-analysis/

VulScan 部分的目录结构可抽象为:

其中主要的逻辑都在 VulScan.py 中,其它放置了几个外部模块 nmb、pyasn1 和 smb;

扫描插件有两种,放置在 vuldb 文件夹下,一是 python 脚本型插件,一是 json 文件型插件;

本文主要分析 VulScan.py 文件并选取一个 python 脚本型插件、一个 json 文件型插件做简要说明,和 Nascan 相比,这部分代码少很多,逻辑也不复杂,所以会啰嗦一点,可能更适合新手学习。

0x01: VulScan 分析

脚本开头执行了下面几行代码

sys.path.append(sys.path[0]+ '/vuldb') sys.path.append(sys.path[0] + "/../") from Config import ProductionConfig

主要是将 vuldb 目录和上级目录加入系统路径中,可以直接 from Configimport ProductionConfig 和导入 python 脚本型插件。

然后进行了数据库连接和一些变量初始化工作。

看一下程序入口:

init() 函数首先进行插件初始化加载,如果发现数据库中已经存储有插件数据,就不继续执行了。

if na_plugin.find().count() >= 1: return

插件信息如果没有存储到数据库中,用 os.listdir() 函数列出插件目录下的文件, 按文件名后缀对两种类型插件分类。

对于 python 脚本插件,用 __import__ (动态导入),然后统一调用插件中的 get_plugin_info() 方法,将插件详细的描述信息存入数据库:

res_tmp =import(plugin_name)

对 json 文件型插件,用 json.loads() 函数加载文件内容

json_text =open(sys.path[0] + '/vuldb/' + plugin_name, 'r').read() plugin_info = json.loads ( json_text )

删除关于检测部分的漏洞,然后也是只将描述信息存入数据库:

delplugin_info['plugin'] na_plugin.insert(plugin_info)

初始化插件后,将密码字典、运行线程数、超时时间、ip 地址白名单从数据库中取出

PASSWORD_DIC,THREAD_COUNT, TIMEOUT, WHITE_LIST = get_config()

开启了一个监控线程,监控是否加载任务,并及时更新密码字典、运行线程数、超时时间、ip 地址白名单:

thread.start_new_thread(monitor,())

有下面这么一段代码,主要是设置 load 值,为下面的不同延时值提供依据,并且写入数据库 Heartbeat 集合中,表示当前有无插件被调用 ( 1 正被调用,0 没有调用)。

再回到程序入口 main 中,到达 while True 语句块中,一直检测当前是否有任务进来:

当任务进来时:

sys.modules.keys() 存储了已经加载的模块,再调用已加载模块是取得其中的缓存,没有重新导入模块。

再看下面两行清除插件缓存的代码:

del sys.modules[PLUGIN_DB.keys()[0]] PLUGIN_DB.clear()

用 del 删除以前导入的模块缓存,以便重新导入时能导入最新版的 python 脚本插件;

参数用 PLUGIN_DB.keys()[0] 是因为:在 VulScan 扫描逻辑中,是以插件来分类扫描任务的。

即一个插件被多个目标调用,而不是一个目标调用多个插件。所以,最多同时只存在一种类型的插件,也就 keys() 的值一直都是一个,没必要使用 for 循环,全部 del 一遍。

PLUGIN_DB.clear() 是清除内存中 dict() 类型的变量缓存。

做了那么多工作,其实我们还没开始扫描~ 下面代码才真正开始扫描呐,吃不吃惊?前面说了一堆废话……

遍历目标,一个目标开一个线程,但是只有当前运行的总线程数 ( thread._count() ) 小于设置的总线程数 ( THREAD_COUNT ) 时,才会继续开新的线程,避免目标过多,开的线程太多卡死!

然后检测了 ip 地址是否为白名单中的地址,如果不是才会继续进行下去;将任务 id、ip 地址和端口号、使用的插件传入 VulScan 进行正式扫描。

vulscan() 类如下:

主要看一下关于 json 文件型插件的漏洞检测函数 poc_check() 和主扫描函数 start(),其它看看标注的注释就好了:)

poc_check() 函数的主要流程:

start() 函数扫描主流程:

里面用 setattr() 函数给 python 脚本插件增加了 PASSWORD_DIC 这个属性,以便可以直接在插件中调用密码字典

setattr(plugin_res,"PASSWORD_DIC", PASSWORD_DIC)

后面调用了每个插件的 check() 方法,执行插件,并获得扫描信息

self.result_info= PLUGIN_DB[plugin_filename].check(str(self.task_netloc[0]),int(self.task_netloc[1]), TIMEOUT)

VulsSan.py 文件基本就那么多内容。

0x02: 插件形式简单分析

选一个 python 插件 crack_postgres.py 看下。

python 脚本型插件里面必须要有的两个函数是:用来返回插件说明信息的 get_plugin_info() 函数:

和执行扫描逻辑返回扫描结果的check()函数:

其它都是非必要函数,可以写在同一个脚本中,供这两个函数调用,最后漏洞利用成功返回相关信息。

其中值得注意的 check() 函数里这行语句,PASSWORD_DIC 这个变量在 crack_postgres.py 中并没有定义,而是上面说的 VulScan.py 中用setattr() 为每个 python 脚本插件定义的。

for pass_ inPASSWORD_DIC:

选个 json 文件型插件 Docker_Remote_API_20161220120458.json 分析下:

plugin 子字典类型中存储者关于漏洞扫描的信息,其它都是说明性的参看信息。

plugin 中的几个键代表的意思如下:

url: 要访问的漏洞URL地址

tag: 漏洞标签

analyzing: 分析模式(keyword表示根据关键词判断漏洞)

analyzingdata: 分析的具体数据(这里是指关键词是什么)

data: POST请求要用到的数据

method: 使用的HTTP请求方法

0x03: 总结

思想亮点在于

1、设置了 python 插件的统一格式,有两个必须的函数,用来统一调用,为每个插件都 setattr 密码字典;

2、对较简单 web 漏洞检测的设置 json 格式形插件,总体设置了三种检测漏洞的方式,比较灵活;

3、监控线程用的场合比较好,实时检测数据库中的变化 ( 用户操作的变化 );

难点在于

1、VulScan.py 里面有个 plan 值变量,结合代码并试运行之后,才能确定是表示任务设置的周期(天数);

2、还有个 status 变量值,取值范围【 0,1,2 】,衡量是否到达固定扫描周期的比值,用来触发再次的;

以上都是在下的片面的愚见,若有错误或描述不当之处,还请指正。

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2017-12-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏散尽浮华

nginx负载均衡(5种方式)、rewrite重写规则及多server反代配置梳理

Nginx除了可以用作web服务器外,他还可以用来做高性能的反向代理服务器,它能提供稳定高效的负载均衡解决方案。nginx可以用轮询、IP哈希、URL哈希等方式...

94260
来自专栏王二麻子IT技术交流园地

Linux常用命令100个用法

平时用linux时,我有一个习惯就是把遇到的,比较有用,并且容易忘的命令,放到一个文本文件中,没事的时候可以拿出来看看,这样可以加深映像,时间长了这些命令的用法...

26950
来自专栏Linux驱动

第4阶段——制作根文件系统之分析init进程(2)

本节目标: (1) 了解busybox(init进程和命令都放在busybox中) (2) 创建SI工程,分析busybox源码来知道init进程做了哪些事情 ...

26790
来自专栏游戏杂谈

express的路由配置优化

1、不便于以后的扩展和维护,如果需要监听的URL越来越多,它看上去就会越来越糟糕了;

15020
来自专栏小尘哥的专栏

springboot中使用tk.mybatis代码生成器

tk.mybatis是对mybatis的进一步封装,它对基本的单表的增删改查又做了进一步封装,springboot中的使用之前已经写过了,如果没用过,请参考我之...

37320
来自专栏积累沉淀

Linux软连接和硬链接

1.Linux链接概念 一种在共享文件和访问它的用户的若干目录项之间建立联系的一种方法 Linux链接分两种,一种被称为硬链接(Hard Link),另一种...

37890
来自专栏hbbliyong

错误提示之(MVC3.0):HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确 MVC误设起始页

MVC3.0框架开发项目: 有时在程序运行的时候会出现“HTTP 404。您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检...

45160
来自专栏张善友的专栏

应用IBatisNet+Castle进行项目的开发

       最近在做一个项目,项目的需求不够明确,这是做项目的大忌,但是没有办法。项目的架构采用Dotnet平台使用C#进行开发,为了加快项目的开发进度,采用...

192100
来自专栏无题

分布式缓存一致性hash算法

在设计分布式缓存集群的时候,需要考虑集群的伸缩性,也就是当向集群中增加服务器的时候,要尽量减小对集群的影响,而一致性hash算法就是用来解决集群伸缩性。 当服...

36320
来自专栏有趣的django

10.Flask上下文

 应用上下文和请求上下文都是存放在一个‘LocalStack’的栈中,和应用app相关的操作就必须要用到应用上下文,比如通过current_app获取当前的这个...

10110

扫码关注云+社区

领取腾讯云代金券