0×00、前言
在企业安全建设过程当中,我们也不断在思考,做一个什么样的端口扫描才能企业业务需求。同时,伴随着企业私有云、混合云以及公有云业务部署环境的不断变化,我们适当也要对扫描策略做调整。前期的端口扫描设计在http://www.freebuf.com/articles/rookie/128526.html
在本文各个部分又所变动。
0×01、详细设计
@1、各个模块之间的交互:
一开始都是把产品想的特别完美,
(1) Web控制端
(2) worker工作节点
(3) 存储扫描结果(maybe: HDFS)
这样实现起来比较麻烦,当时说使用celery做调度,后来发现,celery对django有版本要求,超过1.10版本不成。等等现实问题。其实celery也是redis做调度数据同步。有时间可以自己做。
其实Web控制端和worker可以使用数据库做交互。用户通过Web控制端设置扫描策略和查看报表。Worker读取数据库中的配置信息,执行扫描任务,把扫描结果存储到数据库。
@2、功能需求
在对端口扫描功能的选型上,为啥选择nmap,
(1) 很多商用扫描器也是集成nmap扫描结果,例如:rapid7 Vulnerability Management。
(2) nmap扫描速度,肯定没有masscan、Zmap快,但是扫描结果有对服务banner和版本的探测,更重要的是有操作系统的探测。在云平台部署zmap等无状态扫描,会瞬间发出大量数据包,公有云EIP带宽QoS超过会立刻丢弃,对扫描结果有很大影响。
(3) libnmap 对扫描结果解析的相对完美,方便的提取我想要的数据到数据库中。
端口扫描后,我们还能做什么?
(1) 个人认为第一需求就是对新暴发的漏洞做企业内部评估。前几天的WannaCry就是445端口对外开发又可能触发MS-17-010的RCE。这里我集成了巡风漏洞扫描组件。
(2) 评估高危端口变化趋势,也是衡量企业安全管理人员工作成果的一个手段。
(3) 对企业内部部门漏洞分布有清晰的了解
0×02、交互设计
与用户交互部分,因为是安全管理员用,所以简单做。Axure是一个好的交互工具,可以帮助你梳理业务逻辑。
按照模块分:
(1)扫描配置
(2)扫描报表
0×03、前端实现
(1)开发环境建立:
brew install nodejs
npm install webpack –g
npm install --global vue-cli vue init webpack CloudPScan cd CloudPScan npm install npm install vue-resource npm install element-ui 设置代理 config/dev.index.js
module.exports = {
//...
dev: {
proxyTable: {
// proxy all requests starting with /api to http://127.0.0.1:8000
'/api': {
target: 'http://127.0.0.1:8000', changeOrigin: true, } } }
(2)创建页面路由
import Vue from 'vue'
import Routerfrom 'vue-router' import LoginViewfrom '@/components/LoginView' import MainViewfrom '@/components/MainView' import ScanSettingViewfrom '@/components/ScanSettingView' import ScanReportViewfrom '@/components/ScanReportView' import ElementUIfrom 'element-ui' import 'element-ui/lib/theme-default/index.css' import VueResourcefrom 'vue-resource' Vue.use(ElementUI) Vue.use(Router) Vue.use(VueResource) export default new Router({ routes: [ { path: '/', name: 'LoginView', component: LoginView } , { path: '/MainView', name: 'MainView', component: MainView, children: [{ name: 'ScanSettingView', path: '/ScanSettingView', component: ScanSettingView }, { name: 'ScanReportView', path: '/ScanReportView', component: ScanReportView }] } ] })
(3)登陆页面
<template>
<div class="logincontainer" align="center"> <div class="form-signin" > <img alt="云平台扫描系统"> </div> <div class="form-signin--form" align="center"> <el-tabs> <el-form label-position="center" @submit.native.prevent="doLogin" auto-complete="on" label-width="80px"> <el-form-item label="用户" :required ='true'> <el-input v-model="params.username" auto-complete="on"></el-input> </el-form-item> <el-form-item label="密码" :required ='true'> <el-input type="password" v-model="params.password" auto-complete="on"></el-input> </el-form-item> <el-form-item> <el-button type="primary" native-type="submit" style="width:180px;text-align:center;">登录</el-button> <p v-if="fail" class="alert alert-danger"> {{ msg }} </p> </el-form-item> </el-form> </el-tabs> <div class="sl-login_copyright"> GSGSoft Research <br/>© 2017 GSGSoft Tech. </div> </div> </div> </template>
<script>
export default { name: 'LoginView' , data: function () { return { fail: true , msg: '' , params: { username: '' , password: '' } } } , methods: { doLogin () { //这个地方的处理就忽略了,其实就是请求查询数据库是否匹配提交的账号和密码,如果匹配然后跳转 this.$router.replace({ path: '/MainView' }) } } , created () { } } </script>
(4)扫描配置
<template>
<div>
<p> <div class=panel-back> <h4>扫描设置</h4> <el-form :model="params" label-width="68px" label-position="left" @submit.native.prevent="submit"> <el-row :gutter="50"> <el-col :span="4"> <el-form-item label="任务名称"> <el-input size="small" type="text" v-model="params.task_id"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="开始IP"> <el-input size="small" type="text" v-model="params.ipconf_startip"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="结束IP"> <el-input size="small" type="text" v-model="params.ipconf_endip"></el-input> </el-form-item> </el-col> <el-col :span="4"> <el-form-item label="调度周期"> <el-input size="small" type="text" v-model="params.looptime"></el-input> </el-form-item> </el-col> <el-col :span="4"> <el-button size="small" type="primary" @click.native="submit()">添加</el-button> </el-col> </el-row> </el-form> </div> </p> <p> <div class=panel-back> <h4>扫描任务</h4> <el-table :data="logs" style="width: 100%"> <el-table-column property="task_id" label="任务名称" width="160"> </el-table-column> <el-table-column label="扫描状态" inline-template > <el-progress :stroke-width="12" v-bind:percentage='scanstate' ></el-progress> </el-table-column> <el-table-column property="ipconf_startip" label="扫描开始IP" width="130"> </el-table-column> <el-table-column property="ipconf_endip" label="扫描结束IP" width="130"> </el-table-column> <el-table-column inline-template property="cops" label="操作"> <div> <el-button size="small" @click.native="StartTask(row)">启动</el-button> <el-button size="small" @click.native="DeleteTask(row)">删除</el-button> <el-button size="small" @click.native="VulTask(row)">漏洞</el-button> </div> </el-table-column> </el-table> <p> <el-pagination