1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 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
|