diff options
Diffstat (limited to 'scripts/targets-ipv6-map4to6.nse')
-rw-r--r-- | scripts/targets-ipv6-map4to6.nse | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/scripts/targets-ipv6-map4to6.nse b/scripts/targets-ipv6-map4to6.nse new file mode 100644 index 0000000..f588e75 --- /dev/null +++ b/scripts/targets-ipv6-map4to6.nse @@ -0,0 +1,247 @@ +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local stringaux = require "stringaux" +local table = require "table" +local target = require "target" + +description = [[ +This script runs in the pre-scanning phase to map IPv4 addresses onto IPv6 +networks and add them to the scan queue. + +The technique is more general than what is technically termed "IPv4-mapped IPv6 +addresses." The lower 4 bytes of the IPv6 network address are replaced with the +4 bytes of IPv4 address. When the IPv6 network is ::ffff:0:0/96, then the +script generates IPv4-mapped IPv6 addresses. When the network is ::/96, then it +generates IPv4-compatible IPv6 addresses. +]] + +--- +-- @usage +-- nmap -6 --script targets-ipv6-map4to6 --script-args newtargets,targets-ipv6-map4to6.IPv4Hosts={192.168.1.0/24},targets-ipv6-subnet={2001:db8:c0ca::/64} +-- +-- @output +-- Pre-scan script results: +-- | targets-ipv6-map4to6: +-- | node count: 256 +-- | addresses: +-- |_ 2001:db8:c0ca:0:0:0:c0a8:100/120 +-- +-- @args targets-ipv6-map4to6.IPv4Hosts This must have at least one IPv4 +-- Host for the script be able to work +-- (Ex. 192.168.1.1 or +-- { 192.168.1.1, 192.168.2.2 } ) or Subnet +-- Addresses ( 192.168.1.0/24 or +-- { 192.168.1.0/24, 192.168.2.0/24 } ) +-- +-- @args targets-ipv6-subnet Table/single IPv6 address with prefix +-- (Ex. 2001:db8:c0ca::/48 or +-- { 2001:db8:c0ca::/48, 2001:db8:FEA::/48 }) +-- +-- @xmloutput +-- <elem key="node count">256</elem> +-- <table key="addresses"> +-- <elem>2001:db8:c0ca:0:0:0:c0a8:100/120</elem> +-- </table> + +-- +-- Version 1.4 +-- Update 01/12/2014 - V 1.4 Update for inclusion in Nmap by Daniel Miller +-- Update 05/05/2014 - V 1.3 Eliminate the Host phase. +-- Update 05/05/2014 - V 1.2 Minor corrections and standardization. +-- Update 18/10/2013 - V 1.1 Added SaveMemory option +-- Update 29/03/2013 - V 1.0 Functional script +-- Created 28/03/2013 - v0.1 Created by Raúl Fuentes <ra.fuentess.sam+nmap@gmail.com> +-- + +author = "Raúl Armando Fuentes Samaniego" +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +categories = { + "discovery", +} + +local function split_prefix (net) + local split = stringaux.strsplit("/", net) + return split[1], tonumber(split[2]) +end +--- +-- This function will add all the list of IPv4 host to IPv6 +-- +-- The most normal is returning X:X:X:X::Y.Y.Y.Y/128 +-- The conversion is going to be totally IPv6 syntax (we are going to +-- concatenate strings). +-- @param IPv6_Network A IPv6 Address ( X:X:X:X::/YY ) +-- @param IPv4SHosts A IPv4 String can be: X.X.X.X or X.X.X.X/YY +-- @param addr_table A table to hold the generated addresses. +-- @return Number Total successfully nodes added to the scan. +-- @return Error A warning if something happened. (Nil otherwise) +local From_4_to_6 = function (IPv6_Network, IPv4SHosts, addr_table) + + --We check if the PRefix are OK, anything less than 96 is fine + local v6_base, IPv6_Prefix = split_prefix(IPv6_Network) + if IPv6_Prefix > 96 then + return 0, string.format("The IPv6 subnet %s can't support a direct Mapping 4 to 6.", IPv6_Network) + end + + local sBin6, sError = ipOps.ip_to_bin(v6_base) + if sBin6 == nil then + return 0, sError + end + + -- two options: String or Table, the bes thing to do: make string Table + local tTabla + if type(IPv4SHosts) == "table" then + tTabla = IPv4SHosts + else + tTabla = { IPv4SHosts } + end + + stdnse.debug1("Total IPv4 objects to analyze: %d for IPv6 subnet %s", + #tTabla, IPv6_Network) + + local iTotal = 0 + for _, Host in ipairs(tTabla) do + + + stdnse.debug2("IPv4 Object: %s", Host) + + local v4base, prefix = split_prefix(Host) + + local sBin4 + sBin4, sError = ipOps.ip_to_bin(v4base) + if sBin4 == nil then + return 0, sError + end + + local IPAux + IPAux, sError = ipOps.bin_to_ip(sBin6:sub(1, 96) .. sBin4) + if prefix then + prefix = prefix + (128 - 32) -- adjust for different address lengths + IPAux = string.format("%s/%d", IPAux, prefix) + else + prefix = 128 + end + + stdnse.debug2("IPv6 address: %s", IPAux) + + addr_table[#addr_table+1] = IPAux + if target.ALLOW_NEW_TARGETS then + local bool + bool, sError = target.add(IPAux) + if bool then + iTotal = iTotal + 2^(128 - prefix) + else + stdnse.debug1("Error adding node %s: %s", IPAux, sError) + end + else + iTotal = iTotal + 2^(128 - prefix) + end + + end + + return iTotal +end + +local IPv4Sub = stdnse.get_script_args(SCRIPT_NAME .. ".IPv4Hosts") +local IPv6User = stdnse.get_script_args("targets-ipv6-subnet") +--- +-- We populated the host discovery list. +local Prescanning = function () + + local errors = {} + local tSalida = { + Nodos = 0, + addrs = {}, + } + local Grantotal = 0 + + stdnse.debug2("Beginning the work.") + + if type(IPv6User) == "string" then + IPv6User = { IPv6User } + end + + -- TODO: Gather IPv6 subnets from other sources. + -- This was implemented in the original version of the script, but stripped + -- for now until the other scripts are integrated. + -- http://seclists.org/nmap-dev/2013/q4/285 + for _, IPv6_Subnet in ipairs(IPv6User) do + stdnse.debug1("Processing %s", IPv6_Subnet) + local IPv6Host, sError = From_4_to_6(IPv6_Subnet, IPv4Sub, tSalida.addrs) + if sError ~= nil then + stdnse.debug1( "ERROR: One IPv6 subnet wasn't translated") + errors[#errors+1] = sError + end + if IPv6Host then + -- We need to concatenate the new nodes + Grantotal = Grantotal + IPv6Host + end + end + + tSalida.Nodos = Grantotal + if #errors > 0 then + tSalida.Error = table.concat(errors, "\n") + end + return true, tSalida +end + +--- +-- The script need to be working with IPv6 +-- +--(To bad can't do it with both at same time ) +function prerule () + + if not (nmap.address_family() == "inet6") then + stdnse.verbose1("This script is IPv6 only.") + return false + end + + -- Because Nmap current limitation of working ONE single IP family we must + -- be sure to have everything for work the Mapped IPv4 to IPv6 + if IPv4Sub == nil then + stdnse.verbose1( "There are no IPv4 addresses to map!\z + You must provide it using the %s.IPv4Hosts script-arg.", SCRIPT_NAME) + return false + end + + -- Now we need to have based IPv6 Prefix, the most important is the previous + -- known but we have a last-option too . + if IPv6User == nil then + stdnse.verbose1("There are no IPv6 subnets to scan!\z + You must provide it using the targets-ipv6-subnet script-arg.") + return false + end + + return true +end + +function action () + --Vars for created the final report + local tOutput = stdnse.output_table() + local bExito = false + local tSalida + + bExito, tSalida = Prescanning() + + -- Now we adapt the exit to tOutput and add the hosts to the target! + tOutput.warning = tSalida.Error + + if bExito then + --Final report of the Debug Lvl of Prescanning + stdnse.debug1("Successful Mapped IPv4 to IPv6 added to the scan: %d", + tSalida.Nodos) + + tOutput["node count"] = tSalida.Nodos + tOutput["addresses"] = tSalida.addrs + + if tSalida.Error then + stdnse.debug1("Warnings: %s", tSalida.Error) + end + else + stdnse.debug1("Was unable to add nodes to the scan list due this error: %s", + tSalida.Error) + end + + return tOutput +end |