关于libnmap 的一些应用

随笔描述

nmap 可以进行端口的扫描,在安全或运维中可以说是一款不错的神奇吧,在大部分LINUX 里面都自带了nmap 这款工具,他不仅仅是端口扫描,自身还提供许多插件可以使用。

官方文档

nmap 官方文档
github文档

说说libnmap

libnmap是一个python库,使python开发人员能够操纵nmap进程和数据。

如果您需要实现以下操作,则libnmap是您要查找的内容:

  1. 定期自动或安排nmap扫描
  2. 操纵nmap扫描结果进行报告
  3. 比较和差异nmap扫描生成图
  4. 批处理扫描报告
    ...
    上述用例将在libnmap模块的帮助下轻松实现。

nmap 的模块

github
lib目前提供以下模块:

  • 过程:使您能够启动nmap扫描
  • 解析:使您能够从文件,字符串...中解析nmap报告或扫描结果(到目前为止只有XML)
  • 报告:使您能够操作解析的扫描结果,并以json格式对扫描结果进行序列化
  • diff:使您能够看到两次扫描之间发生了什么变化
  • common:包含基本的nmap对象,如NmapHost和NmapService。要注意的是,每个对象都可以与另一个类似的对象“diff()ed”。
  • 插件:使您能够直接在“NmapReport”对象中支持扫描结果的数据存储。从报告模块:

开始应用

简单的例子

rom libnmap.process import NmapProcess
from libnmap.parser import NmapParser

nm = NmapProcess("127.0.0.1",options="-sV  -p 22")
nm.run()

nmap_report = NmapParser.parse(nm.stdout)

for scanned_hosts in nmap_report.hosts:
    print scanned_hosts
x=[ [a, [ b.address for b in nmap_report.hosts for c in b.get_open_ports() if a==c[0] ] ] for a in sorted(set([ b[0] for a in nmap_report.hosts for b in a.get_open_ports()]),key=int) ]
print  x
y=sorted(set([ b[0] for a in nmap_report.hosts for b in a.get_open_ports()]), key=int)
#print y

运行的结果:

结果

主要参数的介绍

  • NmapProcess 开始一个扫描任务
  • NmapParser 对扫描的结果进行处理,实例化

端口信息

开放指定端口号的主机

  • 显示所有开放指定端口号的主机。生成一个包含主机地址(string)的列表。下面以 443 端口为例,你可以修改成你自己需要的值。

[ a.address for a in nmap_report.hosts if (a.get_open_ports()) and 443 in [b[0] for b in a.get_open_ports()] ]
开放端口数量


- 显示一系列主机开放端口的数量。生成一个包含端口数量(int)的列表,并进行排序。

sorted(set([ b[0] for a in nmap_report.hosts for b in a.get_open_ports()]), key=int)

### 主机开放端口对应的服务,按端口号进行分组

- 显示所有主机开放的端口号,按端口号进行分组和排序。生成一个包含多个列表的列表(即列表的每个元素也为列表),其中每个成员列表第一个元素为端口号(int),第二个元素为一个包含开放对应端口主机 IP 地址(string)的列表。

[ [a, [ b.address for b in nmap_report.hosts for c in b.get_open_ports() if a==c[0] ] ] for a in sorted(set([ b[0] for a in nmap_report.hosts for b in a.get_open_ports()]),key=int) ]

###SSL/TLS 和 HTTP/HTTPS

- 使用 SSL 的主机和端口
显示所有使用 SSL 的主机和端口。这是通过查找是否有服务使用了 “SSL” 通道或者相关脚本检测的结果中包含 pem 证书。生成一个包含一系列列表的列表,每个成员列表中包含主机地址(string)和端口号(int)。

[ [a.address, b.port] for a in nmap_report.hosts for b in a.services if b.tunnel=='ssl' or "'pem'" in str(b.scripts_results) ]


- 下面的内容包含上述相同的信息,但不在是一个包含列表的列表,而是使用 join 函数创建了一个包含 “主机:端口号”(string) 的列表。

[ ':'.join([a.address, str(b.port)]) for a in nmap_report.hosts for b in a.services if b.tunnel=='ssl' or "'pem'" in str(b.scripts_results) ]
包含 web 服务的主机和端口


- 显示所有的 web 服务及其对对应的端口号和协议(http 或 https)。这会生成一个包含多个列表的列表,其中每个成员列表包含协议(string)、地址(string)和端口号(int)。但这里会有些问题,nmap 在报告使用 https 的网站时,有些时候会显示服务是 “https”,而有时则会显示为使用 “ssl” 通道的 “http”,所以我调整了下数据格式以便统一输出。

[ [(b.service + b.tunnel).replace('sl',''), a.address, b.port] for a in nmap_report.hosts for b in a.services if b.open() and b.service.startswith('http') ]

- 这里还是相同的信息,只不过是在原先包含协议、主机和端口号的列表中增加了url(string)。

[ (b.service + b.tunnel).replace('sl','') + '://' + a.address + ':' + str(b.port) + '/' for a in nmap_report.hosts for b in a.services if b.open() and b.service.startswith('http') ]

### 其他服务信息

未知服务

- 显示所有 nmap 无法识别的服务。生成一个包含多个列表的列表,其中每个成员列表包含地址(string)、端口号(int)和 nmap 扫描的端口指纹(string)。生成这些信息,主要是为了方便后续人工审查那些特定的服务,而不会参与到任何自动化的过程中。

[ [ a.address, b.port, b.servicefp ] for a in nmap_report.hosts for b in a.services if (b.service =='unknown' or b.servicefp) and b.port in [c[0] for c in a.get_open_ports()] ]

### nmap 识别出的软件

- 显示 nmap 扫描中识别出的所有软件。生成按产品字母排序的列表。

sorted(set([ b.banner for a in nmap_report.hosts for b in a.services if 'product' in b.banner]))

### 软件对应的主机和端口号,按产品分组

- 显示扫描出软件对应的主机和端口,按产品分组。生成一个包含多个列表的列表,其中每个成员列表的第一个元素为软件的名称(string),随后是另一个列表包含地址(string)和端口号(int)。

[ [ a, [ [b.address, c.port] for b in nmap_report.hosts for c in b.services if c.banner==a] ] for a in sorted(set([ b.banner for a in nmap_report.hosts for b in a.services if 'product' in b.banner])) ]

- 同上相同的信息,只是输出略有不同。同样还是生成一个包含多个列表的列表,成员列表的第一个元素还是软件的名称(string),但第二个是一个包含 “主机:端口号” 的列表。

[ [ a, [ ':'.join([b.address, str(c.port)]) for b in nmap_report.hosts for c in b.services if c.banner==a] ] for a in sorted(set([ b.banner for a in nmap_report.hosts for b in a.services if 'product' in b.banner])) ]


### 搜索指定关键词相关的主机和端口
- 显示所有与给定关键词相关联的主机和端口,从 nmap 扫描结果的原始文本中查找包含产品名称、服务名称等等。下面以 “Oracle” 为例。生成一个包含多个列表的列表,其中每个成员列表包含主机地址(string)和端口号(int)。

[ [a.address, b.port] for a in nmap_report.hosts for b in a.services if b.open() and 'Oracle' in str(b.get_dict()) + str(b.scripts_results) ]

## 扫描结果生产JSON 对象

from libnmap.parser import NmapParser
from libnmap.reportjson import ReportDecoder, ReportEncoder
import json
nmap_report_obj = NmapParser.parse_fromfile('/root/ip.xml')

create a json object from an NmapReport instance

nmap_report_json = json.dumps(nmap_report_obj, cls=ReportEncoder)
print(nmap_report_json)

create a NmapReport instance from a json object

nmap_report_obj = json.loads(nmap_report_json, cls=ReportDecoder)
print(nmap_report_obj)


![结果](http://upload-images.jianshu.io/upload_images/3941016-7e499ab039f3d1e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 函数化例子

!/usr/bin/env python

-- coding: utf-8 --

from libnmap.process import NmapProcess
from libnmap.parser import NmapParser, NmapParserException

start a new nmap scan on localhost with some specific options

def do_scan(targets, options):
parsed = None
nmproc = NmapProcess(targets, options)
rc = nmproc.run()
if rc != 0:
print("nmap scan failed: {0}".format(nmproc.stderr))
print(type(nmproc.stdout))

try:
    parsed = NmapParser.parse(nmproc.stdout)
except NmapParserException as e:
    print("Exception raised while parsing scan: {0}".format(e.msg))

return parsed

print scan results from a nmap report

def print_scan(nmap_report):
print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
nmap_report.version,
nmap_report.started))

for host in nmap_report.hosts:
    if len(host.hostnames):
        tmp_host = host.hostnames.pop()
    else:
        tmp_host = host.address

    print("Nmap scan report for {0} ({1})".format(
        tmp_host,
        host.address))
    print("Host is {0}.".format(host.status))
    print("  PORT     STATE         SERVICE")

    for serv in host.services:
        pserv = "{0:>5s}/{1:3s}  {2:12s}  {3}".format(
                str(serv.port),
                serv.protocol,
                serv.state,
                serv.service)
        if len(serv.banner):
            pserv += " ({0})".format(serv.banner)
        print(pserv)
print(nmap_report.summary)

if name == "main":
report = do_scan("127.0.0.1", "-sV")
if report:
print_scan(report)
else:
print("No results returned")

## 把nmap扫描结果存储到数据库
- 主的运行的脚本

import xml.etree.ElementTree as ET
import MySQLdb
import datetime
nmapdb = MySQLdb.connect(host="134.96.111.202", user="root", passwd="admin2017", db="nmap")
cursor = nmapdb.cursor()
hostsql = "INSERT INTO hosts (timeofscan,ipaddress,hostname,osname,accuracy) values(%s,%s,%s,%s,%s);"
portsql = "INSERT INTO ports (timeofscan,ipaddress,protocol,portid,state,reason,reason_ttl,servicename) values(%s,%s,%s,%s,%s,%s,%s,%s);"
tree = ET.parse('/root/ip.xml')
root = tree.getroot()
for host in root.iter('host'):
hosts=[]
timescan = int(host.get('starttime'))
timeof = (datetime.datetime.fromtimestamp(timescan).strftime('%Y-%m-%d %H:%M:%S'))
for address in host.iter('address'):
addr = address.get('addr')
for hostnames in host.iter('hostnames'):
if len(hostnames.findall('hostname')) > 0:
for hostname in host.iter('hostname'):
hostn = hostname.get('name')
else:
hostn = "none"
for os in host.iter('osmatch'):
osname = os.get('name')
accuracy = os.get('accuracy')
hosts.append(timeof)
hosts.append(addr)
hosts.append(hostn)
hosts.append(osname)
hosts.append(accuracy)
cursor.execute(hostsql,hosts)
for port in host.iter('port'):
ports=[]
ports.append(timeof)
ports.append(addr)
ports.append(port.get('protocol'))
ports.append(port.get('portid'))
for state in port.iter('state'):
ports.append(state.get('state'))
ports.append(state.get('reason'))
ports.append(state.get('reason_ttl'))
for service in port.iter('service'):
ports.append(service.get('name'))
cursor.execute(portsql,ports)
nmapdb.commit()
cursor.close()
nmapdb.close()


-  数据库sql 文件

CREATE DATABASE IF NOT EXISTS nmap;

USE nmap;

CREATE TABLE IF NOT EXISTS hosts (
id int(11) NOT NULL AUTO_INCREMENT,
timeofscan datetime NOT NULL,
ipaddress varchar(15) NULL,
hostname varchar(40) NULL,
osname varchar(200) NULL,
accuracy int(4) NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `ports` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `timeofscan` datetime NOT NULL,
    `ipaddress` varchar(15) NULL,
    `protocol` varchar(20) NULL,
    `portid` int(10) NULL,
    `state` varchar(20) NULL,
    `reason` varchar(20) NULL,
    `reason_ttl` int(10) NULL,
    `servicename` varchar(20) NULL,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

TRUNCATE hosts;
TRUNCATE ports;


### 后话可以配合数据库web 做图表展示



![图表展示](http://upload-images.jianshu.io/upload_images/3941016-c96442d3c8518567.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


![数据库信息](http://upload-images.jianshu.io/upload_images/3941016-112525984c212336.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)



![nmap web开发](http://upload-images.jianshu.io/upload_images/3941016-d784216cc2c7d489.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

























最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • nmap使用指南(终极版) 原创2017-09-09hl0rey信安之路 一、目标指定 1.CIDR标志位 192...
    用电热毯烤猪阅读 11,988评论 1 49
  • Nmap扫描原理与用法 1Nmap介绍 Nmap扫描原理与用法PDF:下载地址 Nmap是一款开源免费的网络发现(...
    y0ungta1a阅读 5,383评论 0 50
  • Nmap输出的是扫描目标的列表,以及每个目标的补充信息,至于是哪些信息则依赖于所使用的选项。“所感兴趣的端口表格...
    令狐冲233阅读 1,940评论 0 4
  • 入冬之后有过三场雪,每一次都把整个世界包裹在白色的礼盒里,炫的让人睁不开眼睛。 每次天气昏昏沉沉的...
    朕是正阅读 212评论 1 0
  • 拉大片的老头 在端村有一个去世的老艺人,说起他,八十年代出生的小孩都认识。他经常拉着一个大片车出现在大街上,集...
    浅一点不惊浓艳阅读 463评论 0 3