Lucene search

K
nmapStephen Hilt (Digital Bond)NMAP:PCWORX-INFO.NSE
HistorySep 06, 2016 - 4:27 a.m.

pcworx-info NSE Script

2016-09-0604:27:47
Stephen Hilt (Digital Bond)
nmap.org
115

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%

This NSE script will query and parse pcworx protocol to a remote PLC. The script will send a initial request packets and once a response is received, it validates that it was a proper response to the command that was sent, and then will parse out the data. PCWorx is a protocol and Program by Phoenix Contact.

<http://digitalbond.com>

Example Usage

nmap --script pcworx-info -p 1962 &lt;host&gt;

Script Output

| pcworx-info:
|   PLC Type: ILC 330 ETH
|   Model Number: 2737193
|   Firmware Version: 3.95T
|   Firmware Date: Mar  2 2012
|_  Firmware Time: 09:39:02

Requires


local string = require "string"
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"

description = [[
This NSE script will query and parse pcworx protocol to a remote PLC.
The script will send a initial request packets and once a response is received,
it validates that it was a proper response to the command that was sent, and then
will parse out the data. PCWorx is a protocol and Program by Phoenix Contact.


http://digitalbond.com
]]
---
-- @usage
-- nmap --script pcworx-info -p 1962 <host>
--
--
-- @output
--| pcworx-info:
--|   PLC Type: ILC 330 ETH
--|   Model Number: 2737193
--|   Firmware Version: 3.95T
--|   Firmware Date: Mar  2 2012
--|_  Firmware Time: 09:39:02

--
--
-- @xmloutput
--<elem key="PLC Type">ILC 330 ETH</elem>
--<elem key="Model Number">2737193</elem>
--<elem key="Firmware Version">3.95T</elem>
--<elem key="Firmware Date">Mar  2 2012</elem>
--<elem key="Firmware Time">09:39:02</elem>

author = "Stephen Hilt (Digital Bond)"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery"}

portrule = shortport.port_or_service(1962, "pcworx", "tcp")

-- Safely extract a zero-terminated string if the blob is long enough
-- Returns nil if it is not.
local function get_string(blob, offset)
  if #blob >= offset then
    return string.unpack("z", blob, offset)
  end
end
---
--  Action Function that is used to run the NSE. This function will send the initial query to the
--  host and port that were passed in via nmap. The initial response is parsed to determine if host
--  is a pcworx Protocol device. If it is then more actions are taken to gather extra information.
--
-- @param host Host that was scanned via nmap
-- @param port port that was scanned via nmap
action = function(host,port)
  local init_comms = "\x01\x01\0\x1a\0\0\0\0x\x80\0\x03\0\x0cIBETH01N0_M\0"

  -- create table for output
  local output = stdnse.output_table()

  -- create new socket
  local socket = nmap.new_socket()
  -- define the catch of the try statement
  local catch = function()
    socket:close()
  end
  local try = nmap.new_try(catch)

  try(socket:connect(host, port))
  try(socket:send(init_comms))
  local response = try(socket:receive())

  if not response:match("^\x81") then
    stdnse.debug1("Unexpected or unknown PCWorx message.")
    return nil
  end
  -- pcworx has a session ID that is generated by the PLC
  -- This will pull the SID so we can communicate further to the PLC
  local sid = string.sub(response, 18, 18)
  local init_comms2 = "\x01\x05\0\x16\0\x01\0\0\x78\x80\0" .. sid .. "\0\0\0\x06\0\x04\x02\x95\0\0"
  try(socket:send(init_comms2))
  -- receive response
  response = try(socket:receive())
  -- TODO: verify this

  -- this is the request that will pull all the information from the PLC
  local req_info = "\x01\x06\0\x0e\0\x02\0\0\0\0\0" .. sid .. "\x04\0"
  try(socket:send(req_info))
  -- receive response
  response = try(socket:receive())

  -- if the response starts with 0x81 then we will continue
  if not response:match("^\x81") then
    stdnse.debug1("Unexpected or unknown PCWorx message.")
    socket:close()
    return nil
  end

  -- create output table with proper data
  output["PLC Type"] = get_string(response, 31)
  output["Model Number"] = get_string(response, 153)
  output["Firmware Version"] = get_string(response, 67)
  output["Firmware Date"] = get_string(response, 80)
  output["Firmware Time"] = get_string(response, 92)

  -- close socket and return output table
  socket:close()
  return output
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:PCWORX-INFO.NSE