zoukankan      html  css  js  c++  java
  • Nmap 扫描并生成HTML报告

    Nmap扫描器,支持生成扫描报告,配合转换模板,可实现自定义转换报告,非常方便。

    扫描报告,可以生成如下格式,这是Nmap中自带的格式。

    nmap -PR -oX lyshark.xml 192.168.1.0/24      # 以XML格式输出扫描结果
    nmap -PR -oN lyshark.log 192.168.1.0/24      # 以标准格式输出扫描结果
    nmap -PR -oG lyshark.log 192.168.1.0/24      # 以Grep可识别的格式输出
    

    1.扫描并生成xml执行命令 nmap -PR -sV -oX lyshark.xml 192.168.1.0/24

    1. 输出漂亮的html报告,下载模板mode.xsl模板,模板内容如下
    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat"/>
      <xsl:template match="/">
        <html lang="en">
          <head>
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" />
            <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap.min.css"/>
            <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
            <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
            <script src="https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap.min.js"></script>
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>
            <style>
              .target:before {
                content: "";
                display: block;
                height: 50px;
                margin: -20px 0 0;
              }
              @media only screen and (min-1900px) {
                .container {
                   1800px;
                  }
              }
              .footer {
                margin-top:60px;
                padding-top:60px;
                 100%;
                height: 180px;
                background-color: #f5f5f5;
              }
            .navbar-right {
    		 float: right!important;
    		 margin-right: -15px;
    	   }
            </style>
            <title>Nmap Scanner 扫描报告</title>
          </head>
          <body>
    	  <!--导航栏-->
            <nav class="navbar navbar-default navbar-fixed-top">
              <div class="container-fluid">
                <div class="navbar-header">
                  <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-home"></span></a>
                </div>
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav">
                    <li><a href="#summary">概要信息</a></li>
                    <li><a href="#scannedhosts">主机信息</a></li>
                    <li><a href="#onlinehosts">在线主机</a></li>
                    <li><a href="#openservices">服务信息</a></li>
                  </ul>
                </div>
              </div>
            </nav>
    
    	 <!--内容区-->
            <div class="container">		
    		 <h2 id="summary" class="target">扫描概要</h2>
              <div class="target">
    			<p >Nmap 版本:<xsl:value-of select="/nmaprun/@version"/></p>
                <p >Nmap命令:<xsl:value-of select="/nmaprun/@args"/></p>
    			<p >开始时间:<xsl:value-of select="/nmaprun/@startstr"/> </p>
    			<p >结束时间:<xsl:value-of select="/nmaprun/runstats/finished/@timestr"/></p>
              </div>
    		  
              <h2 id="scannedhosts" class="target">主机信息<xsl:if test="/nmaprun/runstats/hosts/@down > 1024"><small> (offline hosts are hidden)</small></xsl:if></h2>
              <div class="table-responsive">
                <table id="table-overview" class="table table-striped dataTable" role="grid">
                  <thead>
                    <tr>
                      <th>状态</th>
                      <th>IP</th>
                      <th>主机名</th>
                      <th>开放TCP端口数</th>
                      <th>开放UDP端口数</th>
                    </tr>
                  </thead>
                  <tbody>
                    <xsl:choose>
                      <xsl:when test="/nmaprun/runstats/hosts/@down > 1024">
                        <xsl:for-each select="/nmaprun/host[status/@state='up']">
                          <tr>
                            <td><span class="label label-danger"><xsl:if test="status/@state='up'"><xsl:attribute name="class">label label-success</xsl:attribute></xsl:if><xsl:value-of select="status/@state"/></span></td>
                            <td><xsl:value-of select="address/@addr"/></td>
                            <td><xsl:value-of select="hostnames/hostname/@name"/></td>
                            <td><xsl:value-of select="count(ports/port[state/@state='open' and @protocol='tcp'])"/></td>
                            <td><xsl:value-of select="count(ports/port[state/@state='open' and @protocol='udp'])"/></td>
                          </tr>
                        </xsl:for-each>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:for-each select="/nmaprun/host">
                          <tr>
                            <td><span class="label label-danger"><xsl:if test="status/@state='up'"><xsl:attribute name="class">label label-success</xsl:attribute></xsl:if><xsl:value-of select="status/@state"/></span></td>
                            <td><xsl:value-of select="address/@addr"/></td>
                            <td><xsl:value-of select="hostnames/hostname/@name"/></td>
                            <td><xsl:value-of select="count(ports/port[state/@state='open' and @protocol='tcp'])"/></td>
                            <td><xsl:value-of select="count(ports/port[state/@state='open' and @protocol='udp'])"/></td>
                          </tr>
                        </xsl:for-each>
                      </xsl:otherwise>
                    </xsl:choose>
                  </tbody>
                </table>
              </div>
              <script>
                $(document).ready(function() {			  
    			 $('#table-overview').DataTable({
    				 language: {
    					 "sProcessing": "处理中...",
    					 "sLengthMenu": "显示 _MENU_ 项结果",
    					 "sZeroRecords": "没有匹配结果",
    					 "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
    					 "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
    					 "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
    					 "sInfoPostFix": "",
    					 "sSearch": "搜索:",
    					 "sUrl": "",
    					 "sEmptyTable": "表中数据为空",
    					 "sLoadingRecords": "载入中...",
    					 "sInfoThousands": ",",
    					 "oPaginate": {
    						 "sFirst": "首页",
    						 "sPrevious": "上页",
    						 "sNext": "下页",
    						 "sLast": "末页"
    					 },
    					 "oAria": {
    						 "sSortAscending": ": 以升序排列此列",
    						 "sSortDescending": ": 以降序排列此列"
    					 }
    				 }
    			 });			  
                });
    			
              </script>
    		  
              <h2 id="onlinehosts" class="target">在线主机</h2>
              <xsl:for-each select="/nmaprun/host[status/@state='up']">
                <div class="panel panel-default">
                  <div class="panel-heading">
                    <h3 class="panel-title"><xsl:value-of select="address/@addr"/><xsl:if test="count(hostnames/hostname) > 0"> - <xsl:value-of select="hostnames/hostname/@name"/></xsl:if></h3>
                  </div>
                  <div class="panel-body">
                    <xsl:if test="count(hostnames/hostname) > 0">
                      <h4>Hostnames</h4>
                      <ul>
                        <xsl:for-each select="hostnames/hostname">
                          <li><xsl:value-of select="@name"/> (<xsl:value-of select="@type"/>)</li>
                        </xsl:for-each>
                      </ul>
                    </xsl:if>
                    <h4>端口信息</h4>
                    <div class="table-responsive">
                      <table class="table table-bordered">
                        <thead>
                          <tr>
                            <th>端口</th>
                            <th>协议</th>
                            <th>状态</th>
                            <th>探测手段</th>
                            <th>服务</th>
                            <th>组件</th>
                            <th>版本</th>
                            <th>附件信息</th>
                            <th>CPE 信息</th>
                          </tr>
                        </thead>
                        <tbody>
                          <xsl:for-each select="ports/port">
                            <xsl:choose>
                              <xsl:when test="state/@state = 'open'">
                                <tr class="success">
                                  <td title="Port"><xsl:value-of select="@portid"/></td>
                                  <td title="Protocol"><xsl:value-of select="@protocol"/></td>
                                  <td title="State"><xsl:value-of select="state/@state"/></td>
    							  <td title="Reason"><xsl:value-of select="state/@reason"/></td>
                                  <td title="Service"><xsl:value-of select="service/@name"/></td>
                                  <td title="Product"><xsl:value-of select="service/@product"/></td>
                                  <td title="Version"><xsl:value-of select="service/@version"/></td>
                                  <td title="Extra Info"><xsl:value-of select="service/@extrainfo"/></td>
                                  <td title="CPE Info"><xsl:value-of select="service/cpe"/></td>
                                </tr>
    							
    							  <xsl:for-each select="script">
    								<tr class="script">
    								  <td></td>
    								  <td><xsl:value-of select="@id"/> <xsl:text>&#xA0;</xsl:text></td>
    								  <td colspan="7">
    									<pre><xsl:value-of select="@output"/> <xsl:text>&#xA0;</xsl:text></pre>
    								  </td>
    								</tr>
    
    							  </xsl:for-each>
    							  
                              </xsl:when>
                              <xsl:when test="state/@state = 'filtered'">
                                <tr class="warning">
                                  <td><xsl:value-of select="@portid"/></td>
                                  <td><xsl:value-of select="@protocol"/></td>
                                  <td><xsl:value-of select="state/@state"/><br/><xsl:value-of select="state/@reason"/></td>
                                  <td><xsl:value-of select="service/@name"/></td>
                                  <td><xsl:value-of select="service/@product"/></td>
                                  <td><xsl:value-of select="service/@version"/></td>
                                  <td><xsl:value-of select="service/@extrainfo"/></td>
    							  <td><xsl:value-of select="service/cpe"/></td>
                                </tr>
                              </xsl:when>
                              <xsl:when test="state/@state = 'closed'">
                                <tr class="active">
                                  <td><xsl:value-of select="@portid"/></td>
                                  <td><xsl:value-of select="@protocol"/></td>
                                  <td><xsl:value-of select="state/@state"/><br/><xsl:value-of select="state/@reason"/></td>
                                  <td><xsl:value-of select="service/@name"/></td>
                                  <td><xsl:value-of select="service/@product"/></td>
                                  <td><xsl:value-of select="service/@version"/></td>
                                  <td><xsl:value-of select="service/@extrainfo"/></td>
    							  <td><xsl:value-of select="service/cpe"/></td>
                                </tr>
                              </xsl:when>
                              <xsl:otherwise>
                                <tr class="info">
                                  <td><xsl:value-of select="@portid"/></td>
                                  <td><xsl:value-of select="@protocol"/></td>
                                  <td><xsl:value-of select="state/@state"/><br/><xsl:value-of select="state/@reason"/></td>
                                  <td><xsl:value-of select="service/@name"/></td>
                                  <td><xsl:value-of select="service/@product"/></td>
                                  <td><xsl:value-of select="service/@version"/></td>
                                  <td><xsl:value-of select="service/@extrainfo"/></td>
    							  <td><xsl:value-of select="service/cpe"/></td>
                                </tr>
                              </xsl:otherwise>
                            </xsl:choose>
                          </xsl:for-each>
                        </tbody>
                      </table>
                    </div>
    				
                    <xsl:if test="count(hostscript/script) > 0">
                      <h4>主机 脚本</h4>
                    </xsl:if>
                    <xsl:for-each select="hostscript/script">
                      <h5><xsl:value-of select="@id"/></h5>
                      <pre style="white-space:pre-wrap; word-wrap:break-word;"><xsl:value-of select="@output"/></pre>
                    </xsl:for-each>
    				
                  </div>
                </div>
              </xsl:for-each>
    		  
    		  
    		  
              <h2 id="openservices" class="target">服务信息</h2>
              <div class="table-responsive">
                <table id="table-services" class="table table-striped dataTable" role="grid">
                  <thead>
                    <tr>
                      <th>IP</th>
                      <th>端口</th>
                      <th>协议</th>
                      <th>服务</th>
                      <th>组件</th>
                      <th>版本</th>
                      <th>CPE</th>
                      <th>附加信息</th>
                    </tr>
                  </thead>
                  <tbody>
                    <xsl:for-each select="/nmaprun/host">
                      <xsl:for-each select="ports/port[state/@state='open']">
                        <tr>
                          <td><xsl:value-of select="../../address/@addr"/><xsl:if test="count(../../hostnames/hostname) > 0"> - <xsl:value-of select="../../hostnames/hostname/@name"/></xsl:if></td>
                          <td><xsl:value-of select="@portid"/></td>
                          <td><xsl:value-of select="@protocol"/></td>
                          <td><xsl:value-of select="service/@name"/></td>
                          <td><xsl:value-of select="service/@product"/></td>
                          <td><xsl:value-of select="service/@version"/></td>
                          <td><xsl:value-of select="service/cpe"/></td>
                          <td><xsl:value-of select="service/@extrainfo"/></td>
                        </tr>
                      </xsl:for-each>
                    </xsl:for-each>
                  </tbody>
                </table>
              </div>
              <script>		
                $(document).ready(function() {			  
    			 $('#table-services').DataTable({
    				 language: {
    					 "sProcessing": "处理中...",
    					 "sLengthMenu": "显示 _MENU_ 项结果",
    					 "sZeroRecords": "没有匹配结果",
    					 "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
    					 "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
    					 "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
    					 "sInfoPostFix": "",
    					 "sSearch": "搜索:",
    					 "sUrl": "",
    					 "sEmptyTable": "表中数据为空",
    					 "sLoadingRecords": "载入中...",
    					 "sInfoThousands": ",",
    					 "oPaginate": {
    						 "sFirst": "首页",
    						 "sPrevious": "上页",
    						 "sNext": "下页",
    						 "sLast": "末页"
    					 },
    					 "oAria": {
    						 "sSortAscending": ": 以升序排列此列",
    						 "sSortDescending": ": 以降序排列此列"
    					 }
    				 }
    			 });			  
                });			
              </script>
            </div>
    	 <!-- 页脚 -->
    		<footer class="footer" style="height: 50px; margin-top: 20px; padding-top: 20px;">
              <div class="container">
                <p class="text-muted">
                  This Report Was Generated By <a href='https://www.cnblogs.com/lyshark'>LyShark</a>.<br/>
                </p>
              </div>
            </footer>
          </body>
        </html>
      </xsl:template>
    </xsl:stylesheet>
    

    执行命令,使用指定模板生成。

    xsltproc -o index.html mode.xsl lyshark.xml
    

    1. 输出成.xls结尾的报告,下载模板并使用converter.py文件实现转换。

    converter.py代码如下

    # https://github.com/mrschyte/nmap-converter
    # pip install python-libnmap XlsxWriter
    # nmap-converter.py -o lyshark.xls lyshark.xml
    from libnmap.parser import NmapParser, NmapParserException
    from xlsxwriter import Workbook
    from datetime import datetime
    import os.path
    
    class HostModule():
        def __init__(self, host):
            self.host = next(iter(host.hostnames), "")
            self.ip = host.address
            self.port = ""
            self.protocol = ""
            self.status = ""
            self.service = ""
            self.tunnel = ""
            self.method = ""
            self.source = ""
            self.confidence = ""
            self.reason = ""
            self.reason = ""
            self.product = ""
            self.version = ""
            self.extra = ""
            self.flagged = "N/A"
            self.notes = ""
    
    
    class ServiceModule(HostModule):
        def __init__(self, host, service):
            super(ServiceModule, self).__init__(host)
            self.host = next(iter(host.hostnames), "")
            self.ip = host.address
            self.port = service.port
            self.protocol = service.protocol
            self.status = service.state
            self.service = service.service
            self.tunnel = service.tunnel
            self.method = service.service_dict.get("method", "")
            self.source = "scanner"
            self.confidence = float(service.service_dict.get("conf", "0")) / 10
            self.reason = service.reason
            self.product = service.service_dict.get("product", "")
            self.version = service.service_dict.get("version", "")
            self.extra = service.service_dict.get("extrainfo", "")
            self.flagged = "N/A"
            self.notes = ""
    
    
    class HostScriptModule(HostModule):
        def __init__(self, host, script):
            super(HostScriptModule, self).__init__(host)
            self.method = script["id"]
            self.source = "script"
            self.extra = script["output"].strip()
    
    
    class ServiceScriptModule(ServiceModule):
        def __init__(self, host, service, script):
            super(ServiceScriptModule, self).__init__(host, service)
            self.source = "script"
            self.method = script["id"]
            self.extra = script["output"].strip()
    
    
    def _tgetattr(object, name, default=None):
        try:
            return getattr(object, name, default)
        except Exception:
            return default
    
    
    def generate_summary(workbook, sheet, report):
        summary_header = ["Scan", "Command", "Version", "Scan Type", "Started", "Completed", "Hosts Total", "Hosts Up", "Hosts Down"]
        summary_body = {"Scan": lambda report: _tgetattr(report, 'basename', 'N/A'),
                        "Command": lambda report: _tgetattr(report, 'commandline', 'N/A'),
                        "Version": lambda report: _tgetattr(report, 'version', 'N/A'),
                        "Scan Type": lambda report: _tgetattr(report, 'scan_type', 'N/A'),
                        "Started": lambda report: datetime.utcfromtimestamp(_tgetattr(report, 'started', 0)).strftime("%Y-%m-%d %H:%M:%S (UTC)"),
                        "Completed": lambda report: datetime.utcfromtimestamp(_tgetattr(report, 'endtime', 0)).strftime("%Y-%m-%d %H:%M:%S (UTC)"),
                        "Hosts Total": lambda report: _tgetattr(report, 'hosts_total', 'N/A'),
                        "Hosts Up": lambda report: _tgetattr(report, 'hosts_up', 'N/A'),
                        "Hosts Down": lambda report: _tgetattr(report, 'hosts_down', 'N/A')}
    
        for idx, item in enumerate(summary_header):
            sheet.write(0, idx, item, workbook.myformats["fmt_bold"])
            for idx, item in enumerate(summary_header):
                sheet.write(sheet.lastrow + 1, idx, summary_body[item](report))
    
        sheet.lastrow = sheet.lastrow + 1
    
    
    def generate_hosts(workbook, sheet, report):
        sheet.autofilter("A1:E1")
        sheet.freeze_panes(1, 0)
    
        hosts_header = ["Host", "IP", "Status", "Services", "OS"]
        hosts_body = {"Host": lambda host: next(iter(host.hostnames), ""),
                      "IP": lambda host: host.address,
                      "Status": lambda host: host.status,
                      "Services": lambda host: len(host.services),
                      "OS": lambda host: os_class_string(host.os_class_probabilities())}
    
        for idx, item in enumerate(hosts_header):
            sheet.write(0, idx, item, workbook.myformats["fmt_bold"])
    
        row = sheet.lastrow
        for host in report.hosts:
            for idx, item in enumerate(hosts_header):
                sheet.write(row + 1, idx, hosts_body[item](host))
            row += 1
    
        sheet.lastrow = row
    
    
    def generate_results(workbook, sheet, report):
        sheet.autofilter("A1:N1")
        sheet.freeze_panes(1, 0)
    
        results_header = ["Host", "IP", "Port", "Protocol", "Status", "Service", "Tunnel", "Source", "Method", "Confidence", "Reason", "Product", "Version", "Extra", "Flagged", "Notes"]
        results_body = {"Host": lambda module: module.host,
                        "IP": lambda module: module.ip,
                        "Port": lambda module: module.port,
                        "Protocol": lambda module: module.protocol,
                        "Status": lambda module: module.status,
                        "Service": lambda module: module.service,
                        "Tunnel": lambda module: module.tunnel,
                        "Source": lambda module: module.source,
                        "Method": lambda module: module.method,
                        "Confidence": lambda module: module.confidence,
                        "Reason": lambda module: module.reason,
                        "Product": lambda module: module.product,
                        "Version": lambda module: module.version,
                        "Extra": lambda module: module.extra,
                        "Flagged": lambda module: module.flagged,
                        "Notes": lambda module: module.notes}
    
        results_format = {"Confidence": workbook.myformats["fmt_conf"]}
    
        print("[+] Processing {}".format(report.summary))
        for idx, item in enumerate(results_header):
            sheet.write(0, idx, item, workbook.myformats["fmt_bold"])
    
        row = sheet.lastrow
        for host in report.hosts:
            print("[+] Processing {}".format(host))
    
            for script in host.scripts_results:
                module = HostScriptModule(host, script)
                for idx, item in enumerate(results_header):
                    sheet.write(row + 1, idx, results_body[item](module), results_format.get(item, None))
                row += 1
    
            for service in host.services:
                module = ServiceModule(host, service)
                for idx, item in enumerate(results_header):
                    sheet.write(row + 1, idx, results_body[item](module), results_format.get(item, None))
                row += 1
    
                for script in service.scripts_results:
                    module = ServiceScriptModule(host, service, script)
                    for idx, item in enumerate(results_header):
                        sheet.write(row + 1, idx, results_body[item](module), results_format.get(item, None))
                    row += 1
    
        sheet.data_validation("O2:O${}".format(row + 1), {"validate": "list",
                                               "source": ["Y", "N", "N/A"]})
        sheet.lastrow = row
    
    
    def setup_workbook_formats(workbook):
        formats = {"fmt_bold": workbook.add_format({"bold": True}),
                   "fmt_conf": workbook.add_format()}
    
        formats["fmt_conf"].set_num_format("0%")
        return formats
    
    
    def os_class_string(os_class_array):
        return " | ".join(["{0} ({1}%)".format(os_string(osc), osc.accuracy) for osc in os_class_array])
    
    
    def os_string(os_class):
        rval = "{0}, {1}".format(os_class.vendor, os_class.osfamily)
        if len(os_class.osgen):
            rval += "({0})".format(os_class.osgen)
        return rval
    
    
    def main(reports, workbook):
        sheets = {"Summary": generate_summary,
                  "Hosts": generate_hosts,
                  "Results": generate_results}
    
        workbook.myformats = setup_workbook_formats(workbook)
    
        for sheet_name, sheet_func in sheets.items():
            sheet = workbook.add_worksheet(sheet_name)
            sheet.lastrow = 0
            for report in reports:
                sheet_func(workbook, sheet, report)
        workbook.close()
    
    
    if __name__ == "__main__":
        import argparse
        parser = argparse.ArgumentParser()
        parser.add_argument("-o", "--output", metavar="XLS", help="path to xlsx output")
        parser.add_argument("reports", metavar="XML", nargs="+", help="path to nmap xml report")
        args = parser.parse_args()
    
        if args.output == None:
            parser.error("Output must be specified")
    
        reports = []
        for report in args.reports:
            try:
                parsed = NmapParser.parse_fromfile(report)
            except NmapParserException as ex:
                parsed = NmapParser.parse_fromfile(report, incomplete=True)
            
            parsed.basename = os.path.basename(report)
            reports.append(parsed)
    
        workbook = Workbook(args.output)
        main(reports, workbook)
    

    安装模块,并使用命令完成转换。

    pip install python-libnmap XlsxWriter
    nmap-converter.py -o lyshark.xls lyshark.xml
    
    文章出处:https://www.cnblogs.com/LyShark/p/12346908.html
    版权声明:本博客文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

    如果您恶意转载本人文章并被本人发现,则您的整站文章,将会变为我的原创作品,请相互尊重 !
    转载规范 点击阅读 如果您转载本人文章,则视为您默认同意此规范约定。
  • 相关阅读:
    浅谈C++ STL中的优先队列(priority_queue)
    哈夫曼树与哈夫曼编码
    Binary Search 的递归与迭代实现及STL中的搜索相关内容
    Prime 算法的简述
    估算网站需要多少宽带方法
    微服务服务拆分步骤
    第一次有人把科创板讲得这么简单明了
    一个人优秀到可怕的三个迹象!一旦具备,必为人中龙凤,大富大贵
    美元加息怎么“剪羊毛”
    英国脱欧的影响
  • 原文地址:https://www.cnblogs.com/LyShark/p/12346908.html
Copyright © 2011-2022 走看看