巡风在隔离网络环境下的离线更新方案

20161219234034

0x00 前言

离线更新系统组件是企业在隔离网络环境下的一种常见的特殊需求,一般由于安全管理的需要,隔离网络内的主机虽然能够被外部网络访问,但自身却因为无法访问互联网而不能及时获取最新的系统更新,针对这种场景,离线更新是较为折中的方式,巡风目前缺乏这方面的实现。

本文尝试通过对巡风漏洞插件体系的梳理,建立一种简单可行的离线更新方案,从而使巡风在隔离网络环境下畅快的使用。

0x01 巡风的漏洞扫描插件模型

在之前的短文中,笔者对巡风的源码进行了初步的梳理分析,从而了解到,巡风漏洞扫描引擎建立了两种扫描场景:针对Web服务和针对任意性服务,这两种场景虽有互通交叉的情况,但在使用时若能够做到坚持采用巡风建议的插件开发形式会收到高效的反馈,毕竟遵循简洁高效才是我们安全运维的生存之道。

巡风通过抽象设计,极简地完成了Web测试的完整流程,而对整个Web请求和响应结果的检测也均通过JSON来进行定义和维护,这帮助我们专注于Web测试过程中在数据处理上的细节,而其提供的基于关键词、正则表达式和MD5 hash值的规则检测模式也丰富了测试的弹性;另一方面对于非Web类服务,巡风除了约定函数接口外并没有做更多的约束,更多的工作需要自行通过Python编程实现,对于复杂的情况,混合编程也是Python允许的,脚本化的方式虽然灵活但需要我们对于各类脚本需要有足够的掌控性,相信这一点巡风官方应该有相应的安全考虑。

巡风的两种插件模型差距较大,未来也不排除其它的插件形式,如何对不同类型的插件进行统一的管理和使用,最基本的方法就是设计一些共有的信息(元数据),并在插件调用上(检测引擎)进行合理的区别处理。巡风的插件元数据会同时存放在MongoDB数据库和插件文件自身内部,而保持元数据的一致也主要依赖于文件名的判别。所有插件文件都会存在数个字段对自身进行描述,包括:name(插件名称)、info:(描述说明)、level(威胁级别)、type(威胁分类/插件类型)、author(作者)、url(参考网址)和keyword(关键词),相应的用途可以在WebAdminUI上进行体会,建议新开发的插件正确的使用好这些信息,这对漏洞和资产的管理大有裨益。

通过分析可以确定,巡风插件更新会同时涉及MongoDB数据库和插件文件,自行实现离线更新就是要同时维护好插件元数据的一致性,下面笔者给出一种可行的实现方案。

0x02 离线更新功能的实现

本文给出的离线功能在实现上初步定为基于包文件或目录的形式,过程要简洁,同时需要保持巡风的正常可用。

(一)功能修改

1.修改文件views/templates/layout.html(本文提到的所有路径均相对于巡风的主目录),定位“扫描引擎”下方,添加:

<li><a href="/updater"><i class="zmdi zmdi-view-dashboard"></i> <span>更新</span></a></li>

2.修改文件views/View.py,添加代码:

# 离线环境下的更新
@app.route('/updater')
@logincheck
@anticsrf
def Updater():
 update_dir = os.path.join(file_path, 'newplugins')
 if (os.path.isdir(update_dir)):
 for file in os.listdir(update_dir):
 plugin_file = os.path.join(file_path, file)
 if (os.path.exists(plugin_file)):
 app.logger.debug('%s exists in %s' % (file, file_path))
 else:
 origin_file = os.path.join(update_dir, file)
 os.rename(origin_file, plugin_file)
 (filename, ext) = os.path.splitext(file)
 
 json_string = {'add_time': datetime.now(), 'count': 0, 'source': 1}
 if ext == '.py':
 module = __import__(filename)
 mark_json = module.get_plugin_info()
 json_string['filename'] = filename
 else:
 json_text = open(plugin_file, 'r').read()
 mark_json = json.loads(json_text)
 json_string['filename'] = filename
 mark_json.pop('plugin')
 
 json_string.update(mark_json)
 #app.logger.debug(json_string)
 Mongo.coll['Plugin'].insert(json_string)

return render_template('updater.html')

3.新增文件views/templates/updater.html,内容如下:

{% extends "layout.html" %}
{% block css %}
 <link href="static/buss/css/main.css" rel="stylesheet" type="text/css"/>
 <link href="static/plugin/sweetalert/sweetalert.css" rel="stylesheet" type="text/css"/>
 <link href="static/plugin/multiselect/css/multi-select.css" rel="stylesheet" type="text/css"/>
{% endblock %}
{% block webinfo %}
 <div class="container">
 <div class="row" style="margin-bottom: 20px">
 <div class="col-sm-12">
正在后台自动更新
 </div>
 </div>
 </div>
{% endblock %}

4.创建目录vulscan/vuldb/newplugins

(二)使用方法

经过以上修改后,巡风已经具备基于目录的插件离线更新能力,日常运维中我们仅仅需要将所有的巡风插件复制到newplugins目录,并执行更新功能即可;修改后的巡风会自动过滤已经有的插件(同样基于文件名),将新的插件维护对应的位置。

0x03 总结

在巡风的离线更新上,笔者仅仅进行了简单的尝试,也没有在UI上进行细化,包括缺少通过WebUIAdmin进行插件打包和上传至newplugins目录的功能,大家可以根据需要进行添加。当然更希望巡风官方能够将离线更新功能加入到代码实现中。

*作者:LazyTricks,MottoIN原创投稿。未经允许禁止转载!

原创文章,作者:LazyTricks,如若转载,请注明出处:http://www.mottoin.com/97143.html

发表评论

登录后才能评论

评论列表(2条)

  • Littleheary
    Littleheary 2017年5月12日 下午1:14

    大神,求看到。我使用了你的方法,但是插件数量依然没有更新,还是没有增加进去呀。

    • LazyTricks
      LazyTricks 2017年5月12日 下午1:26

      你好,文中所提的离线更新方法经过很多人验证均有效,本文在排版时存在“代码对齐”的问题,因此我已经将完整的源码(基于巡风官方源码修改)包发送到你邮箱,并附上了使用文档,完善过的离线更新功能比本文写作时的效果更好,如有疑问,欢迎交流

联系我们

021-62666911

在线咨询:点击这里给我发消息

邮件:root@mottoin.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code