1

我目前正在研究 NMAP XML,虽然我的 XSLT 1.0 有所改进,但我仍然非常缺乏经验。以防万一有人在考虑其他解决方案,这必须使用 XSLT 1.0 来完成。我的 XSLT 处理器仅支持 XSLT 1.0,我无法使用任何 perl/python/ruby NMAP XML 特定库。LibXML/xsltproc 必须支持任何 EXSLT 函数。

这是一个有效但显着减少/编辑的 NMAP XML 示例。

<?xml version="1.0"?>
<nmaprun scanner="nmap" args="nmap -sU -sS -sV -O -p T:20-23,25-26,53,79-81,88,106,110-111,113,119,135-139,143-144,161-162,179,199,389,427,443-445,465,513-515,543-544,548,554,587,631,646,705,873,990,993,995,1025-1029,1110,1433,1720,1723,1755,1900,1993,2000-2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5354,5357,5432,5631,5666,5800,5900,6000-6001,6646,7070,8000,8008-8009,8080-8081,8443,8888,9100,9999-10000,32768,49152-49157,U:53,67,69,111,123,137-138,161-162,199,705,1993,5353 -oX - 192.168.100.1 192.168.100.3 192.168.100.5 192.168.100.6 192.168.100.7 192.168.100.8 192.168.100.9 192.168.100.10 192.168.100.13 192.168.100.15 192.168.100.16 192.168.100.17 192.168.100.18 192.168.100.20 192.168.100.21 192.168.100.24 192.168.100.25" start="1341847779" startstr="Mon Jul  9 11:29:39 2012" version="5.51.6" xmloutputversion="1.03">
  <scaninfo type="syn" protocol="tcp" numservices="105" services="20-23,25-26,53,79-81,88,106,110-111,113,119,135-139,143-144,161-162,179,199,389,427,443-445,465,513-515,543-544,548,554,587,631,646,705,873,990,993,995,1025-1029,1110,1433,1720,1723,1755,1900,1993,2000-2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5354,5357,5432,5631,5666,5800,5900,6000-6001,6646,7070,8000,8008-8009,8080-8081,8443,8888,9100,9999-10000,32768,49152-49157"/>
  <scaninfo type="udp" protocol="udp" numservices="13" services="53,67,69,111,123,137-138,161-162,199,705,1993,5353"/>
  <verbose level="0"/>
  <debugging level="0"/>
  <host starttime="1341847779" endtime="1341854063">
    <status state="up" reason="reset"/>
    <address addr="192.168.100.1" addrtype="ipv4"/>
    <hostnames>
      <hostname name="sub1.example.com" type="PTR"/>
    </hostnames>
    <ports>
      <extraports state="filtered" count="103">
        <extrareasons reason="no-responses" count="103"/>
      </extraports>
      <port protocol="tcp" portid="22">
        <state state="closed" reason="reset" reason_ttl="43"/>
        <service name="ssh" method="table" conf="3"/>
      </port>
      <port protocol="tcp" portid="443">
        <state state="closed" reason="reset" reason_ttl="53"/>
        <service name="https" method="table" conf="3"/>
      </port>
      <port protocol="udp" portid="5353">
        <state state="open|filtered" reason="no-response" reason_ttl="0"/>
        <service name="zeroconf" method="table" conf="3"/>
      </port>
    </ports>
    <os>
      <portused state="closed" proto="tcp" portid="22"/>
      <osclass type="VoIP phone" vendor="Cisco" osfamily="embedded" accuracy="92"/>
      <osclass type="terminal" vendor="CMI" osfamily="embedded" accuracy="92"/>
      <osclass type="switch" vendor="Enterasys" osfamily="embedded" accuracy="92"/>
      <osclass type="general purpose" vendor="FreeBSD" osfamily="FreeBSD" osgen="4.X" accuracy="92"/>
      <osclass type="general purpose" vendor="FreeBSD" osfamily="FreeBSD" osgen="6.X" accuracy="92"/>
      <osclass type="printer" vendor="Intermec" osfamily="embedded" accuracy="92"/>
      <osclass type="general purpose" vendor="Microsoft" osfamily="Windows" osgen="XP" accuracy="92"/>
      <osclass type="load balancer" vendor="Radware" osfamily="APsolute OS" osgen="10.X" accuracy="92"/>
      <osclass type="load balancer" vendor="Cisco" osfamily="embedded" accuracy="91"/>
      <osclass type="general purpose" vendor="Microsoft" osfamily="Windows" osgen="2003" accuracy="91"/>
      <osclass type="router" vendor="Linksys" osfamily="embedded" accuracy="90"/>
      <osclass type="firewall" vendor="Nokia" osfamily="IPSO" osgen="4.X" accuracy="90"/>
      <osclass type="broadband router" vendor="Neuf" osfamily="embedded" accuracy="89"/>
      <osclass type="VoIP adapter" vendor="Avaya" osfamily="embedded" accuracy="89"/>
      <osclass type="specialized" vendor="Fuji" osfamily="Windows" osgen="XP" accuracy="89"/>
      <osclass type="printer" vendor="HP" osfamily="embedded" accuracy="89"/>
      <osclass type="general purpose" vendor="HP" osfamily="OpenVMS" osgen="7.X" accuracy="89"/>
      <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="89"/>
      <osclass type="WAP" vendor="Motorola" osfamily="embedded" accuracy="89"/>
      <osclass type="firewall" vendor="Netasq" osfamily="embedded" accuracy="89"/>
      <osclass type="WAP" vendor="Orange" osfamily="embedded" accuracy="89"/>
      <osclass type="WAP" vendor="Sagem Communication" osfamily="embedded" accuracy="89"/>
      <osclass type="broadband router" vendor="Sagem Communication" osfamily="embedded" accuracy="89"/>
      <osclass type="broadband router" vendor="Thomson" osfamily="embedded" accuracy="89"/>
      <osclass type="switch" vendor="Cisco" osfamily="embedded" accuracy="89"/>
      <osclass type="switch" vendor="Cisco" osfamily="IOS" osgen="12.X" accuracy="89"/>
      <osclass type="general purpose" vendor="Microsoft" osfamily="Windows" osgen="2000" accuracy="89"/>
      <osclass type="general purpose" vendor="Microsoft" osfamily="Windows" osgen="NT" accuracy="89"/>
      <osclass type="phone" vendor="Nokia" osfamily="Symbian OS" accuracy="89"/>
      <osclass type="firewall" vendor="3Com" osfamily="embedded" accuracy="88"/>
      <osclass type="WAP" vendor="AirSpan" osfamily="embedded" accuracy="88"/>
      <osmatch name="Cisco IP Phone 7941" accuracy="92" line="9973"/>
      <osmatch name="CMI Genus NEMA terminal" accuracy="92" line="12553"/>
      <osmatch name="Enterasys Matrix E1 switch" accuracy="92" line="16101"/>
      <osmatch name="FreeBSD 4.10-RELEASE (x86)" accuracy="92" line="17037"/>
      <osmatch name="FreeBSD 6.1-RELEASE" accuracy="92" line="17563"/>
      <osmatch name="Intermec PM4i label printer" accuracy="92" line="25391"/>
      <osmatch name="Microsoft Windows XP SP3" accuracy="92" line="50241"/>
      <osmatch name="Radware OnDemand Switch 2 XL (APsolute OS 10.31)" accuracy="92" line="56138"/>
      <osmatch name="Cisco ACE load balancer" accuracy="91" line="9310"/>
      <osmatch name="Microsoft Windows Server 2003" accuracy="91" line="41896"/>
    </os>
    <distance value="2"/>
    <times srtt="1260" rttvar="454" to="100000"/>
  </host>
  <host starttime="1341847779" endtime="1341854043">
    <status state="up" reason="echo-reply"/>
    <address addr="192.168.100.3" addrtype="ipv4"/>
    <hostnames>
      <hostname name="sub2.example.com" type="PTR"/>
    </hostnames>
    <ports>
      <extraports state="filtered" count="102">
        <extrareasons reason="no-responses" count="102"/>
      </extraports>
      <port protocol="tcp" portid="22">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ssh" product="OpenSSH" version="4.3" extrainfo="protocol 2.0" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="80">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="http" product="Apache httpd" version="2.2.3" extrainfo="(CentOS)" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="631">
        <state state="closed" reason="reset" reason_ttl="64"/>
        <service name="ipp" method="table" conf="3"/>
      </port>
      <port protocol="udp" portid="5353">
        <state state="open|filtered" reason="no-response" reason_ttl="0"/>
        <service name="zeroconf" method="table" conf="3"/>
      </port>
    </ports>
    <os>
      <portused state="open" proto="tcp" portid="22"/>
      <portused state="closed" proto="tcp" portid="631"/>
      <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="100"/>
      <osmatch name="Linux 2.6.11 - 2.6.18" accuracy="100" line="30082"/>
    </os>
    <uptime seconds="3662901" lastboot="Mon May 28 03:46:31 2012"/>
    <distance value="2"/>
    <tcpsequence index="258" difficulty="Good luck!" values="E1B9999,E6F5E488,274272DD,94D932E2,B9CF9CA8,F7C309B"/>
    <ipidsequence class="All zeros" values="0,0,0,0,0,0"/>
    <tcptssequence class="1000HZ" values="DA505426,DA50548C,DA5054F2,DA505558,DA5055BD,DA505621"/>
    <times srtt="1424" rttvar="772" to="100000"/>
  </host>
  <host starttime="1341847779" endtime="1341854075">
    <status state="up" reason="echo-reply"/>
    <address addr="192.168.100.5" addrtype="ipv4"/>
    <hostnames>
      <hostname name="sub3.example.com" type="PTR"/>
    </hostnames>
    <ports>
      <extraports state="filtered" count="100">
        <extrareasons reason="no-responses" count="100"/>
      </extraports>
      <port protocol="tcp" portid="21">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ftp" product="ProFTPD" version="1.3.3c" ostype="Unix" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="22">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ssh" product="OpenSSH" version="4.3" extrainfo="protocol 2.0" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="80">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="http" product="Apache httpd" version="2.2.3" extrainfo="(CentOS)" method="probed" conf="10"/>
      </port>
      <port protocol="udp" portid="5353">
        <state state="open|filtered" reason="no-response" reason_ttl="0"/>
        <service name="zeroconf" method="table" conf="3"/>
      </port>
    </ports>
    <os>
      <portused state="open" proto="tcp" portid="21"/>
      <portused state="closed" proto="tcp" portid="631"/>
      <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="100"/>
      <osmatch name="Linux 2.6.11 - 2.6.18" accuracy="100" line="30082"/>
    </os>
    <uptime seconds="2854295" lastboot="Wed Jun  6 12:23:17 2012"/>
    <distance value="2"/>
    <tcpsequence index="261" difficulty="Good luck!" values="D0B97175,E38B93CA,E038B6D0,E754B4D7,4F3B8565,2E948D89"/>
    <ipidsequence class="All zeros" values="0,0,0,0,0,0"/>
    <tcptssequence class="1000HZ" values="AA1DFC6D,AA1DFCD3,AA1DFD39,AA1DFD9F,AA1DFE04,AA1DFE69"/>
    <times srtt="1561" rttvar="679" to="100000"/>
  </host>
  <host starttime="1341847779" endtime="1341854050">
    <status state="up" reason="echo-reply"/>
    <address addr="192.168.100.6" addrtype="ipv4"/>
    <hostnames>
      <hostname name="sub4.example.com" type="PTR"/>
    </hostnames>
    <ports>
      <extraports state="filtered" count="100">
        <extrareasons reason="no-responses" count="100"/>
      </extraports>
      <port protocol="tcp" portid="21">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ftp" product="ProFTPD" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="22">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ssh" product="OpenSSH" version="4.3" extrainfo="protocol 2.0" method="probed" conf="10"/>
      </port>
      <port protocol="tcp" portid="80">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="http" product="Apache httpd" version="2.2.3" extrainfo="(CentOS)" method="probed" conf="10"/>
      </port>
      <port protocol="udp" portid="5353">
        <state state="open|filtered" reason="no-response" reason_ttl="0"/>
        <service name="zeroconf" method="table" conf="3"/>
      </port>
    </ports>
    <os>
      <portused state="open" proto="tcp" portid="21"/>
      <portused state="closed" proto="tcp" portid="631"/>
      <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="100"/>
      <osmatch name="Linux 2.6.11 - 2.6.18" accuracy="100" line="30082"/>
    </os>
    <uptime seconds="2854295" lastboot="Wed Jun  6 12:23:17 2012"/>
    <distance value="2"/>
    <tcpsequence index="264" difficulty="Good luck!" values="D5B1C96,FE5DF509,C56A40B8,DF3C5676,63A52AF7,D9A58AAE"/>
    <ipidsequence class="All zeros" values="0,0,0,0,0,0"/>
    <tcptssequence class="1000HZ" values="AA1DFC6D,AA1DFCD3,AA1DFD39,AA1DFD9F,AA1DFE04,AA1DFE69"/>
    <times srtt="1608" rttvar="697" to="100000"/>
  </host>
  <host starttime="1341847779" endtime="1341854049">
    <status state="up" reason="echo-reply"/>
    <address addr="192.168.100.10" addrtype="ipv4"/>
    <hostnames>
      <hostname name="sub5.example.com" type="PTR"/>
    </hostnames>
    <ports>
      <extraports state="closed" count="109">
        <extrareasons reason="resets" count="100"/>
        <extrareasons reason="port-unreaches" count="9"/>
      </extraports>
      <port protocol="tcp" portid="22">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="ssh" method="table" conf="3"/>
      </port>
      <port protocol="tcp" portid="111">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="rpcbind" method="table" conf="3"/>
      </port>
      <port protocol="tcp" portid="199">
        <state state="open" reason="syn-ack" reason_ttl="64"/>
        <service name="smux" method="table" conf="3"/>
      </port>
      <port protocol="udp" portid="111">
        <state state="open" reason="udp-response" reason_ttl="64"/>
        <service name="rpcbind" method="probed" conf="10"/>
      </port>
      <port protocol="udp" portid="123">
        <state state="open" reason="udp-response" reason_ttl="64"/>
        <service name="ntp" product="NTP" version="v4" method="probed" conf="10"/>
      </port>
      <port protocol="udp" portid="161">
        <state state="open|filtered" reason="no-response" reason_ttl="0"/>
        <service name="snmp" method="table" conf="3"/>
      </port>
    </ports>
    <os>
      <portused state="open" proto="tcp" portid="22"/>
      <portused state="closed" proto="tcp" portid="20"/>
      <portused state="closed" proto="udp" portid="53"/>
      <osclass type="firewall" vendor="Cisco" osfamily="embedded" accuracy="95"/>
      <osclass type="switch" vendor="Cisco" osfamily="NX-OS" osgen="4.X" accuracy="93"/>
      <osclass type="general purpose" vendor="Linux" osfamily="Linux" osgen="2.6.X" accuracy="91"/>
    </os>
    <distance value="2"/>
    <times srtt="529" rttvar="321" to="100000"/>
  </host>
  <runstats>
    <finished time="1341854092" timestr="Mon Jul  9 13:14:52 2012" elapsed="6314.31" summary="Nmap done at Mon Jul  9 13:14:52 2012; 25 IP addresses (5 hosts up) scanned in 156.31 seconds" exit="success"/>
    <hosts up="119" down="29" total="148"/>
  </runstats>
</nmaprun>

我正在尝试将其转换为一个简单的 CSV,只有这三个值,

Hostname,IP Address,OS Class

我已经创建了一个样式表,它按预期工作。我还想指定,如果os/osclass/@osfamily值为 Linux,则仅输出主机。这是我目前所拥有的

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" encoding="utf-8"/>
  <xsl:strip-space elements="*"/>
  <xsl:variable name="delimiter" select="','"/>

  <xsl:template match="/nmaprun/host">

    <xsl:if test="os/osclass[@osfamily='Linux']">
        <xsl:value-of select="hostnames/hostname/@name"/>
        <xsl:value-of select="$delimiter"/>
        <xsl:value-of select="address[@addrtype='ipv4']/@addr"/>
        <xsl:value-of select="$delimiter"/>
        <xsl:value-of select="os/osclass/@osfamily"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:if>

  </xsl:template>
</xsl:stylesheet>

这是示例输出,使用此样式表进行转换,

sub1.example.com,192.168.100.1,embedded
sub2.example.com,192.168.100.3,Linux
sub3.example.com,192.168.100.5,Linux
sub4.example.com,192.168.100.6,Linux
sub5.example.com,192.168.100.10,embedded

不幸的是,我得到了那些embedded主机,但我已经找到了原因。这是因为主机可以有多个os/osclass/@osfamily属性,为每个os/osclass元素指定一个。我想os/osclass/@osfamily每个主机只考虑一个值,它的os/osclass@accuracy值是所有os/osclasss 中最高的。尽管我一直在阅读有关排序值的内容,但我真的不知道该怎么做。如果有人有经验,可以帮助我,我将不胜感激。

4

1 回答 1

2

我想os/osclass/@osfamily每个主机只考虑一个值,它的os/osclass@accuracy值是最高的os/osclasss

你非常接近,使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text" encoding="utf-8"/>
      <xsl:strip-space elements="*"/>
      <xsl:variable name="delimiter" select="','"/>

      <xsl:template match="/nmaprun/host">

        <xsl:if test=
         "os/osclass
            [@osfamily='Linux'
           and
             not(../osclass/@accuracy > @accuracy)
            ]">
            <xsl:value-of select="hostnames/hostname/@name"/>
            <xsl:value-of select="$delimiter"/>
            <xsl:value-of select="address[@addrtype='ipv4']/@addr"/>
            <xsl:value-of select="$delimiter"/>
            <xsl:value-of select="os/osclass/@osfamily"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
      </xsl:template>
</xsl:stylesheet>

当将此转换应用于提供的 XML 文档时,现在的结果是

sub2.example.com,192.168.100.3,Linux
sub3.example.com,192.168.100.5,Linux
sub4.example.com,192.168.100.6,Linux

备注

上述解决方案相当低效(O(N ^ 2))。

这是一个更有效的解决方案 (O(N*log(N))),使用排序

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text" encoding="utf-8"/>
      <xsl:strip-space elements="*"/>
      <xsl:variable name="delimiter" select="','"/>

      <xsl:template match="/nmaprun/host">
       <xsl:variable name="vMaxAccuracy">
         <xsl:for-each select="os/osclass/@accuracy">
          <xsl:sort data-type="number" order="descending"/>
          <xsl:if test="position()=1">
            <xsl:value-of select="."/>
          </xsl:if>
         </xsl:for-each>
       </xsl:variable>

        <xsl:if test=
         "os/osclass[@osfamily='Linux' and @accuracy = $vMaxAccuracy]">
            <xsl:value-of select="hostnames/hostname/@name"/>
            <xsl:value-of select="$delimiter"/>
            <xsl:value-of select="address[@addrtype='ipv4']/@addr"/>
            <xsl:value-of select="$delimiter"/>
            <xsl:value-of select="os/osclass/@osfamily"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
      </xsl:template>
</xsl:stylesheet>
于 2012-08-26T18:38:53.487 回答