Lucene search

K
nmapRiccardo CecolinNMAP:EAP-INFO.NSE
HistoryMar 08, 2012 - 6:00 p.m.

eap-info NSE Script

2012-03-0818:00:35
Riccardo Cecolin
nmap.org
83

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Enumerates the authentication methods offered by an EAP (Extensible Authentication Protocol) authenticator for a given identity or for the anonymous identity if no argument is passed.

Script Arguments

eap-info.identity

Identity to use for the first step of the authentication methods (if omitted “anonymous” will be used).

eap-info.scan

Table of authentication methods to test, e.g. { 4, 13, 25 } for MD5, TLS and PEAP. Default: TLS, TTLS, PEAP, MSCHAP.

eap-info.timeout

Maximum time allowed for the scan (default 10s). Methods not tested because of timeout will be listed as “unknown”.

eap-info.interface

Network interface to use for the scan, overrides “-e”.

Example Usage

nmap -e interface --script eap-info [--script-args="eap-info.identity=0-user,eap-info.scan={13,50}"] <target>

Script Output

Pre-scan script results:
| eap-info:
| Available authentication methods with identity="anonymous" on interface eth2
|   true     PEAP
|   true     EAP-TTLS
|   false    EAP-TLS
|_  false    EAP-MSCHAP-V2

Requires


local eap = require "eap"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"

description = [[
Enumerates the authentication methods offered by an EAP (Extensible
Authentication Protocol) authenticator for a given identity or for the
anonymous identity if no argument is passed.
]]

---
-- @usage
-- nmap -e interface --script eap-info [--script-args="eap-info.identity=0-user,eap-info.scan={13,50}"] <target>
--
-- @output
-- Pre-scan script results:
-- | eap-info:
-- | Available authentication methods with identity="anonymous" on interface eth2
-- |   true     PEAP
-- |   true     EAP-TTLS
-- |   false    EAP-TLS
-- |_  false    EAP-MSCHAP-V2
--
-- @args eap-info.identity Identity to use for the first step of the authentication methods (if omitted "anonymous" will be used).
-- @args eap-info.scan Table of authentication methods to test, e.g. { 4, 13, 25 } for MD5, TLS and PEAP. Default: TLS, TTLS, PEAP, MSCHAP.
-- @args eap-info.interface Network interface to use for the scan, overrides "-e".
-- @args eap-info.timeout Maximum time allowed for the scan (default 10s). Methods not tested because of timeout will be listed as "unknown".

author = "Riccardo Cecolin"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"

categories = { "broadcast", "safe" }


prerule = function()
  return nmap.is_privileged()
end

local default_scan = {
  eap.eap_t.TLS,
  eap.eap_t.TTLS,
  eap.eap_t.PEAP,
  eap.eap_t.MSCHAP,
}

local UNKNOWN = "unknown"

action = function()

  local arg_interface = stdnse.get_script_args(SCRIPT_NAME .. ".interface")
  local arg_identity = stdnse.get_script_args(SCRIPT_NAME .. ".identity")
  local arg_scan = stdnse.get_script_args(SCRIPT_NAME .. ".scan")
  local arg_timeout = stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout"))
  local iface

  -- trying with provided interface name
  if arg_interface then
    iface = nmap.get_interface_info(arg_interface)
  end

  -- trying with default nmap interface
  if not iface then
    local iname = nmap.get_interface()
    if iname then
      iface = nmap.get_interface_info(iname)
    end
  end

  -- failed
  if not iface then
    return "please specify an interface with -e"
  end
  stdnse.debug1("iface: %s", iface.device)

  local timeout = (arg_timeout or 10) * 1000

  stdnse.debug2("timeout: %s", timeout)

  local pcap = nmap.new_socket()
  pcap:pcap_open(iface.device, 512, true, "ether proto 0x888e")


  local identity = { name="anonymous", auth = {}, probe = -1 }

  if arg_identity then
    identity.name = tostring(arg_identity)
  end

  local scan
  if arg_scan == nil or type(arg_scan) ~= "table" or #arg_scan == 0 then
    scan = default_scan
  else
    scan = arg_scan
  end

  local valid = false
  for i,v in ipairs(scan) do
    v = tonumber(v)
    if v ~= nil and v < 256 and v > 3 then
      stdnse.debug1("selected: %s", eap.eap_str[v] or "unassigned" )
      identity.auth[v] = UNKNOWN
      valid = true
    end
  end

  if not valid then
    return "no valid scan methods provided"
  end

  local tried_all = false

  local start_time = nmap.clock_ms()
  eap.send_start(iface)

  while(nmap.clock_ms() - start_time < timeout) and not tried_all do
    local status, plen, l2_data, l3_data, time = pcap:pcap_receive()
    if (status) then
      stdnse.debug2("packet size: 0x%x", plen )
      local packet = eap.parse(l2_data .. l3_data)

      if packet then
        stdnse.debug2("packet valid")

        -- respond to identity requests, using the same session id
        if packet.eap.type == eap.eap_t.IDENTITY and  packet.eap.code == eap.code_t.REQUEST then
          stdnse.debug1("server identity: %s",packet.eap.body.identity)
          eap.send_identity_response(iface, packet.eap.id, identity.name)
        end

        -- respond with NAK to every auth request to enumerate them until we get a failure
        if packet.eap.type ~= eap.eap_t.IDENTITY and  packet.eap.code == eap.code_t.REQUEST then
          stdnse.debug1("auth request: %s",eap.eap_str[packet.eap.type])
          identity.auth[packet.eap.type] = true

          identity.probe = -1
          for i,v in pairs(identity.auth) do
            stdnse.debug1("identity.auth: %d %s",i,tostring(v))
            if v == UNKNOWN then
              identity.probe = i
              eap.send_nak_response(iface, packet.eap.id, i)
              break
            end
          end
          if identity.probe == -1 then tried_all = true end
        end

        -- retry on failure
        if packet.eap.code == eap.code_t.FAILURE then
          stdnse.debug1("auth failure")
          identity.auth[identity.probe] = false

          -- don't give up at the first failure!
          -- mac spoofing to avoid to wait too much
          local d = string.byte(iface.mac,6)
          d = (d + 1) % 256
          iface.mac = iface.mac:sub(1,5) .. string.pack("B",d)

          tried_all = true
          for i,v in pairs(identity.auth) do
            if v == UNKNOWN then
              tried_all = false
              break
            end
          end
          if not tried_all then
            eap.send_start(iface)
          end
        end

      else
        stdnse.debug1("packet invalid! wrong filter?")
      end
    end
  end

  local results = { ["name"] = ("Available authentication methods with identity=\"%s\" on interface %s"):format(identity.name, iface.device) }
  for i,v in pairs(identity.auth) do
    if v== true then
      table.insert(results, 1, ("%-8s %s"):format(tostring(v), eap.eap_str[i] or "unassigned" ))
    else
      table.insert(results, ("%-8s %s"):format(tostring(v), eap.eap_str[i] or "unassigned" ))
    end
  end

  for i,v in ipairs(results) do
    stdnse.debug1("%s", tostring(v))
  end

  return stdnse.format_output(true, results)
end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:EAP-INFO.NSE