安全平台扫描功能关于插件扫描

0x01 需求


openssl漏洞,struts2漏洞,这些都是一些爆发型的事件漏洞。在复查自身是否存在问题,或者说受影响面有多大的时候,谁有好的自动化工具,谁就最快解决问题。当然,针对特殊的人群,定制化的py脚本也能解决问题,只是相对来说,这个过程会比较麻烦,假如,正好你今天请假,没有上班,且目前只有一个实习生在工作岗位上,处理这个问题,可能瞬间他就懵了。这个时候,我们就要考虑有一个完整的一体化的安全自动化插件检测框架。(例如: tangscan之类的)

0x02 开发


最早参考的是sqlmap的开发模型进行研究,因为sqlmap做得很强大,起码我是这么认为的。so,同时想用一些新的东西提高下自己的能力。
先说下整个扫描器应该分为以下两块:

  • web api 模块
  • 执行模块
    从api上,应该跟sqlmap一样,接受任务、执行任务、返回结果之类的。当然,我也是这样设计的。
    截取部分代码,作为样例:
# 默认方法
@route('/',method='GET')
def index():
    if reqIp(request.environ.get('REMOTE_ADDR')):
        return '
欢迎访问SPScanner V3.0
\n' else: return json.dumps({'status':-5}) # 添加任务方法 @route('/scan/add',method='POST') def addtask(_ip='',_web=''): try: if reqIp(request.environ.get('REMOTE_ADDR')): _type = int(request.forms.get('type')) _ip = request.forms.get('ip') _web = request.forms.get('web') task_id = createHashID() insert_task_sql = 'INSERT INTO task(ID,TYPE,TASKVAL,TASKSTATUS,RESPORTID,TASKID)VALUES(null,?,?,?,?,?);' if _type == 1: for ip in _ip.split(','): report_id = createHashID() dbconn.execute(insert_task_sql,(1,ip,0,report_id,task_id)); dbconn.commit() return json.dumps({'status':1,'taskid':task_id}) elif _type == 2: for url in _web.split(','): report_id = createHashID() dbconn.execute(insert_task_sql,(2,url,0,report_id,task_id)); dbconn.commit() return json.dumps({'status':1,'taskid':task_id}) else: return json.dumps({'status':0}) else: return json.dumps({'status':-5}) except Exception, e: return json.dumps({'status':-1}) # 删除任务方法 @route('/scan/del',method='POST') def deltask(): try: if reqIp(request.environ.get('REMOTE_ADDR')): _taskid = request.forms.get('taskid') select_task_sql = "SELECT * FROM task where TASKID = '?';" data = dbconn.execute(select_task_sql,(_taskid)) if len(data) > 0: delete_task_sql = "DELETE FROM task WHERE TASKID = '?';" dbconn.execute(delete_task_sql,(_taskid)) dbconn.commit() return json.dumps({'status':1}) else: return json.dumps({'status':0}) else: return json.dumps({'status':-5}) except Exception, e: return json.dumps({'status':-1}) # 获得任务状态方法 # 返回任务完成的百分比 @route('/scan/status',method='POST') def getstatus(): try: _taskid = request.forms.get('taskid') select_task_sql = "SELECT * FROM task WHERE TASKID = '%s';" % _taskid alldata = dbconn.execute(select_task_sql) if len(alldata) > 0: all_count = len(alldata) finish_task_sql = "SELECT * FROM task WHERE TASKSTATUS = '1' AND TASKID = '%s';" % _taskid finish_count = dbconn.execute(finish_task_sql) penten = int(float(len(finish_count)/len(alldata))*100) return json.dumps({'status':1,'penten':penten}) else: return json.dumps({'status':0}) except Exception, e: return json.dumps({'status':-1}) # 读取任务报告 @route('/scan/report',method='POST') def getreport(): try: reportdict = {} _taskid = request.forms.get('taskid') select_task_sql = "SELECT RESPORTID FROM task WHERE TASKID = '%s';" % _taskid alldata = dbconn.execute(select_task_sql) if len(alldata) > 0: for taskitem in alldata: reportid = taskitem[0] select_report_sql = "SELECT * FROM report WHERE RESPORTID = '%s';" % reportid reportdata = dbconn.execute(select_report_sql) for reportitem in reportdata: reportdict[reportitem[0]] = { 'vulname': reportitem[1], 'vullevel': reportitem[2], 'vulref': reportitem[3], 'vulsdesc': reportitem[4], 'vulddesc': reportitem[5], 'vulrespheader': reportitem[6], 'vulresqheader': reportitem[7], 'vulresquest': reportitem[8] } reportdict['status'] = 1 return json.dumps(reportdict) else: return json.dumps({'status':0}) except Exception, e: return json.dumps({'status':-1})

在数据库这块,默认我选择sqlite,因为我觉得用这个做为本地的agent足够了,在后面读取了报告之后,把结果存到redis/MYSQL,其实才是最靠谱的做法。当然,你需要把这个东西做成守护进程执行~

0x03 目录结构


目录结构基本上比较清晰,命名规范都比较标准,之前犯过的一些错误都会尽可能的避免,所以这个版本基本上都是按照标准化来coding,目的在于长久使用和维护。

├── TaskService.py ==> (任务处理service)
├── WebApiService.py ==> (web服务service)
├── conf ==> (配置)
│   ├── Global_Conf.py
│   ├── Http_Request_Conf.py
│   ├── Plugin_Path_Conf.py
├── daemon ==> (守护进程)
│   ├── pscanner_taskservice
│   └── pscanner_webapiservice
├── lib ==> (基础库)
│   ├── common
│   │   ├── Http_Request.py
│   │   ├── coredata.py
│   │   ├── execute.py
│   │   ├── general.py
│   │   └── special.py
│   ├── core
│   │   ├── Scan_Exploit.py
│   │   ├── Scan_Frame.py
│   │   ├── Scan_Print.py
│   └── objects
│       └── task.py
├── log ==> (日志管理)
│   ├── access
│   ├── error
│   └── info
├── plugins ==> (插件库)
│   ├── system
│   │   ├── M_4cc4d9c6fed65e0dc01adcebbf2f2158.py
│   └── website
│       ├── E_514f056a3ff58eb000f1a94fae988b7b.py
│       ├── E_e8773f08f8f10c34dec6ae699ca1b111.py
│       ├── G_29e34bc8c04565ec9b88c26cdb5ebbc8.py
│       ├── O_2e7e01af7a74ccaee996632665d6a6af.py
├── run.py ==> (扫描器console版本入口)
└── setup.py ==> (环境安装脚本)

0x04 关于 Web Service API:


该api主要用于分布式使用,调度器通过发起http请求将任务下发执行,在扫描结束后将任务报告结果提取。

请求类型 请求地址 请求参数 作用说明
GET / 无请求值 默认页面
POST /scan/add 扫描ip:ip,扫描web:web,扫描类型:type 创建一个扫描任务
POST /scan/del 任务id:taskid 删除扫描任务信息
POST /scan/status 任务id:taskid 读取扫描任务状态
POST /scan/report 任务id:taskid 读取扫描任务报告

0x05 next


下一章讲核心功能设计。。。

你可能感兴趣的:(安全平台扫描功能关于插件扫描)