python处理nmap扫描结果

本文主要介绍如何用 python处理nmap扫描结果,并做进一步的数据处理。

一、环境搭建

  • windows 10
  • mongodb
  • nosqlbooster
  • python3.7.3

1.1mongodb server

mongodb 是一个流行的非关系型数据库,其采用文档格式来存储数据,具有较好的灵活性,用Python语言读写数据库非常简单方便,其社区版本可以免费使用,下载地址为https://www.mongodb.com/download-center/community

下载mongodb server
安装过程请注意

1.2 nosqlbooster

nosqlbooster是一个mongodb的可视化管理工具,是收费的,如果仅仅是增删改查的话,其免费的功能已够用了。
官网的下载地址为https://www.nosqlbooster.com/downloads

nosqlbooster下载界面

1.3 pymongo

pymongo是Python连接mongodb数据库的第三方包,可以使用pip进行安装

pip install pymongo

简单的使用可参考 https://pypi.org/project/pymongo/
文档 https://api.mongodb.com/python/current/

二、解析Nmap扫描结果

使用下面的命令会以xml格式来保存nmap的扫描结果
nmap -sS x.x.x.0/24 -oX xxx.xml
使用python的Beatusoup库来解析xml文件,将解析出来的结果存入Mongodb数据库,方便查询和利用。
代码如下
parse_xml.py

#-*- coding:utf-8 -*-
# author: wlj 
# time: 2020/2/28 10:15
# 解析nmap xml格式的扫描结果,存入mongodb数据库
import os
from bs4 import BeautifulSoup
from pymongo import MongoClient

#连接本地的mongodb server
mongo = MongoClient("localhost", 27017).asset.nmap_result

#解析nmap扫描结果的xml文件
def parse_xml(xml_filename):
    soup = BeautifulSoup(open(xml_filename,'r').read(),'lxml')
    #遍历所有的host标签
    for host in soup.find_all('host'):
        #找到存活的主机
        if host.status['state'] == 'up':
            #主机的IP地址
            ip = host.address['addr']
            #用于保存端口信息的列表
            ports=[]
            #遍历所有的port标签
            for port in host.ports.find_all('port'):
                #将port标签下的协议、端口号、状态、服务名称添加进ports
                ports.append({
                    'protocol':port['protocol'],
                    'portid': port['portid'],
                    'state': port.state['state'],
                    'service': port.service['name']
                })
            #写入mongodb
            mongo.update_one(
                {'ip':ip},
                {
                    '$set':{
                        'ports':ports
                    }
                },
                upsert=True #若该IP的记录不存在,将其创建,存在的话,对其更新
            )
            print(ip)

def main():
    #递归遍历当前目录
    for root,dirs,names in os.walk('.'):
        for name in names:
            #若文件以.xml结尾
            if name.endswith('.xml'):
                #构造完整的文件名
                filename = root + os.sep + name
                parse_xml(filename)

main()

结果

mongodb数据库

三、提取web站点的title

本节使用requests来获取所有的web站点的title和banner信息,代码如下 。
get_web_title.py

#-*- coding:utf-8 -*-
# author:wlj
# time: 2020/2/28 13:27
# 从mongodb数据库中获取开放80端口的IP,请求主页,获取reponse和网站title
import requests,re,chardet
from requests.packages import urllib3
from pymongo import MongoClient
import threading
from queue import Queue
urllib3.disable_warnings()


#全局变量
#HTTP请求使用的headers
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'
}

#任务队列
task_queue = Queue()
#互斥量,用于控制线程对task_queue变量的访问
threadLock = threading.Lock()
#存储website信息的表
mongo_website = MongoClient("localhost", 27017).asset.website

#根据url获取网页的title
def get_web_title(url):
    try:
        if url.startswith('https'):#若为https协议
            r = requests.get(url,headers=headers,verify=False,timeout=5)
        else:#若为http协议
            r = requests.get(url,headers=headers,timeout=5)
    except:#出错的话直接返回
        return

    if r.status_code == 200:
        #使用正则表达式提取页面title
        title = re.findall(r'<title>(.*?)</title>',r.text)
        home_title = ''
        if title:
            #print(r.encoding)
            #使用chardet来推测页面使用的编码方式
            dect_encoding = chardet.detect(r.text.encode(r.encoding))['encoding']
            #print(dect_encoding)
            
            #提取页面的title
            try:
                home_title = title[0].encode(r.encoding).decode(dect_encoding)
            except:
                home_title = title[0]
            else:
                pass
        #将页面信息存入mongodb 
        mongo_website.update_one(
            {'url':url},#url
            {'$set':{
                'title':home_title,#主页title
                'response_headers':r.headers #返回的reponse头
            }},
            upsert=True #若该记录不存在,则插入,存在的话更新
        )
        print(url,home_title)
                
#自定线程类    
class myThread (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while True:
            # 获取锁,用于线程同步
            threadLock.acquire()
            #任务队列为空的话
            if task_queue.empty():
                # 释放锁,开启下一个线程
                threadLock.release()
                #跳出循环
                break
            
            else:#任务队列不为空的话
                #从队列中的取出一个url
                url = task_queue.get()    
                #输出当前队列的大小
                print('queue size',task_queue.qsize())           
                # 释放锁,开启下一个线程
                threadLock.release()
                #获取url的title
                get_web_title(url)

#主函数
def main():
    #namp_result表
    mongo = MongoClient("localhost", 27017).asset.nmap_result
    #从mongodb中提取中所有开放80端口的ip,构造url
    for url in ['http://'+x['ip']  for x in mongo.find({'ports.portid':'80'},{'ip':1})]:
        #将这些url插入队列
        task_queue.put(url)
    
    #线程池
    threads = []
    #创建线程
    for i in range(20):
        t = myThread()
        t.start()
        #将新创建的线程加入线程池
        threads.append(t)
    #等待所有的线程执行完毕后,继续执行主函数
    for t in threads:
        t.join()

    print('completed!')

main()

结果

web站点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值