1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Updates TN3270.lua and scripts. It also adds an argument to disable TN3270. Closes #1455

This commit is contained in:
paulino
2019-03-21 04:07:55 +00:00
parent 2f7b505bd8
commit f9a08ccd2c
9 changed files with 113 additions and 49 deletions

View File

@@ -1,5 +1,8 @@
#Nmap Changelog ($Id$); -*-text-*-
o [NSE][GH#1504] Updates TN3270.lua and adds argument to disable TN3270E
[Soldier of Fortran]
o [GH#1504] RMI parser could crash when encountering invalid input
[Clément Notin]

View File

@@ -61,12 +61,13 @@ Telnet = {
EOR = "\239"
},
-- Thesse are the options we accept for telnet
options = {
BINARY = "\000",
EOR = "\025",
TTYPE = "\024",
--TN3270 = "\028",
TN3270 = "\040" -- Technically TN3270E
TN3270 = "\028",
TN3270E = "\040"
},
command = {
@@ -251,6 +252,7 @@ Telnet = {
telnet_state = 0, -- same as TNS_DATA to begin with
server_options = {},
client_options = {},
unsupported_opts = {},
sb_options = '',
connected_lu = '',
connected_dtype= '',
@@ -452,6 +454,7 @@ Telnet = {
local TNS_DONT = 5
local TNS_SB = 6
local TNS_SB_IAC = 7
local supported = false
local DO_reply = self.commands.IAC .. self.commands.DO
local DONT_reply = self.commands.IAC .. self.commands.DONT
local WILL_reply = self.commands.IAC .. self.commands.WILL
@@ -488,48 +491,72 @@ Telnet = {
elseif data == self.commands.SB then self.telnet_state = TNS_SB
end
elseif self.telnet_state == TNS_WILL then
-- I know if could use a for loop here with ipairs() but i find this easier to read
if data == self.options.BINARY or data == self.options.EOR or
data == self.options.TTYPE or data == self.options.TN3270 then
stdnse.debug(3, "[TELNET] IAC WILL 0x%s?", stdnse.tohex(data))
for _,v in pairs(self.options) do -- check to see if we support this sub option (SB)
if v == data then
stdnse.debug(3, "[TELNET] IAC DO 0x%s", stdnse.tohex(data))
supported = true
break
end
end -- end of checking options
for _,v in pairs(self.unsupported_opts) do
if v == data then
stdnse.debug(3, "[TELNET] IAC DONT 0x%s (disabled)", stdnse.tohex(data))
supported = false
end
end
if supported then
if not self.server_options[data] then -- if we haven't already replied to this, let's reply
self.server_options[data] = true
self:send_data(DO_reply..data)
stdnse.debug(3, "Sent Will Reply: " .. data)
stdnse.debug(3, "[TELNET] Sent Will Reply: 0x%s", stdnse.tohex(data))
self:in3270()
end
else
self:send_data(DONT_reply..data)
stdnse.debug(3, "Sent Don't Reply: " .. data)
stdnse.debug(3, "[TELNET] Sent Don't Reply: 0x%s", stdnse.tohex(data))
end
self.telnet_state = TNS_DATA
elseif self.telnet_state == TNS_WONT then
if self.server_options[data] then
self.server_options[data] = false
self:send_data(DONT_reply..data)
stdnse.debug(3, "Sent Don't Reply: " .. data)
stdnse.debug(3, "[TELNET] Sent Don't Reply: 0x%s", stdnse.tohex(data))
self:in3270()
end
self.telnet_state = TNS_DATA
elseif self.telnet_state == TNS_DO then
if data == self.options.BINARY or data == self.options.EOR or
data == self.options.TTYPE or data == self.options.TN3270 then
-- data == self.options.STARTTLS -- ssl encryption to be added later
stdnse.debug(3, "[TELNET] IAC DO 0x%s?", stdnse.tohex(data))
for _,v in pairs(self.options) do -- check to see if we support this sub option (SB)
if v == data then
stdnse.debug(3, "[TELNET] IAC WILL 0x%s", stdnse.tohex(data))
supported = true
break
end
end -- end of checking options
for _,v in pairs(self.unsupported_opts) do
if v == data then
stdnse.debug(3, "[TELNET] IAC WONT 0x%s (disabled)", stdnse.tohex(data))
supported = false
end
end
if supported then
if not self.client_options[data] then
self.client_options[data] = true
self:send_data(WILL_reply..data)
stdnse.debug(3, "Sent Do Reply: " .. data)
stdnse.debug(3, "[TELNET] Sent Do Reply: 0x%s" , stdnse.tohex(data))
self:in3270()
end
else
self:send_data(WONT_reply..data)
stdnse.debug(3, "Got unsupported Do. Sent Won't Reply: " .. data .. " " .. self.telnet_data)
stdnse.debug(3, "[TELNET] Got unsupported Do. Sent Won't Reply: " .. data .. " " .. self.telnet_data)
end
self.telnet_state = TNS_DATA
elseif self.telnet_state == TNS_DONT then
if self.client_options[data] then
self.client_options[data] = false
self:send_data(WONT_reply .. data)
stdnse.debug(3, "Sent Wont Reply: " .. data)
stdnse.debug(3, "[TELNET] Sent Wont Reply: 0x%s", stdnse.tohex(data))
self:in3270()
end
self.telnet_state = TNS_DATA
@@ -540,7 +567,7 @@ Telnet = {
self.sb_options = self.sb_options .. data
end
elseif self.telnet_state == TNS_SB_IAC then
stdnse.debug(3, "Processing SB options")
stdnse.debug(3, "[TELNET] Processing SB options")
-- self.sb_options = self.sb_options .. data -- looks like this is a bug? Why append F0 to the end?
if data == self.commands.SE then
self.telnet_state = TNS_DATA
@@ -553,12 +580,13 @@ Telnet = {
self.device_type ..
self.commands.IAC ..
self.commands.SE )
elseif self.client_options[self.options.TN3270] and
self.sb_options:sub(1,1) == self.options.TN3270 then
elseif (self.client_options[self.options.TN3270] or self.client_options[self.options.TN3270E]) and
(self.sb_options:sub(1,1) == self.options.TN3270 or
self.sb_options:sub(1,1) == self.options.TN3270E) then
if not self:negotiate_tn3270() then
return false
end
stdnse.debug(3, "Done Negotiating Options")
stdnse.debug(3, "[TELNET] Done Negotiating Options")
else
self.telnet_state = TNS_DATA
end
@@ -587,7 +615,7 @@ Telnet = {
if self.connected_lu == '' then
self:send_data(self.commands.IAC ..
self.commands.SB ..
self.options.TN3270 ..
self.options.TN3270E ..
self.tncommands.DEVICETYPE ..
self.tncommands.REQUEST ..
self.device_type ..
@@ -597,7 +625,7 @@ Telnet = {
stdnse.debug(3,"[TN3270] Sending LU: %s", self.connected_lu)
self:send_data(self.commands.IAC ..
self.commands.SB ..
self.options.TN3270 ..
self.options.TN3270E ..
self.tncommands.DEVICETYPE ..
self.tncommands.REQUEST ..
self.device_type ..
@@ -631,7 +659,7 @@ Telnet = {
-- since We've connected lets send our options
self:send_data(self.commands.IAC ..
self.commands.SB ..
self.options.TN3270 ..
self.options.TN3270E ..
self.tncommands.FUNCTIONS ..
self.tncommands.REQUEST ..
--self.tncommands.RESPONSES .. -- we'll only support basic 3270E mode
@@ -649,7 +677,7 @@ Telnet = {
-- functions really but we'll agree to whatever they want
self:send_data(self.commands.IAC ..
self.commands.SB ..
self.options.TN3270 ..
self.options.TN3270E ..
self.tncommands.FUNCTIONS ..
self.tncommands.IS ..
self.sb_options:sub(4,4) ..
@@ -664,29 +692,32 @@ Telnet = {
--- Check to see if we're in TN3270
in3270 = function ( self )
if self.client_options[self.options.TN3270] then
if self.client_options[self.options.TN3270E] then
stdnse.debug(3,"[in3270] In TN3270E mode")
if self.negotiated then
stdnse.debug(3,"[in3270] TN3270E negotiated")
self.state = self.TN3270E_DATA
end
elseif self.server_options[self.options.EOR] and
self.server_options[self.options.BINARY] and
elseif self.client_options[self.options.EOR] and
self.client_options[self.options.BINARY] and
self.client_options[self.options.EOR] and
self.client_options[self.options.BINARY] and
self.client_options[self.options.TTYPE] then
stdnse.debug(3,"[in3270] In TN3270 mode")
self.state = self.TN3270_DATA
end
if self.state == self.TN3270_DATA or self.state == self.TN3270E_DATA then
-- since we're in TN3270 mode, let's create an empty buffer
stdnse.debug(3, "Creating Empty IBM-3278-2 Buffer")
stdnse.debug(3, "[in3270] Creating Empty IBM-3278-2 Buffer")
for i=0, 1920 do
self.buffer[i] = "\0"
self.fa_buffer[i] = "\0"
self.overwrite_buf[i] = "\0"
end
stdnse.debug(3, "Empty Buffer Created. Length: " .. #self.buffer)
stdnse.debug(3, "[in3270] Empty Buffer Created. Length: " .. #self.buffer)
end
stdnse.debug(3,"Current State: "..self.word_state[self.state])
stdnse.debug(3,"[in3270] Current State: "..self.word_state[self.state])
end,
--- Also known as process_eor
@@ -1220,7 +1251,7 @@ Telnet = {
for j = i,#self.fa_buffer do
-- find end of field
if (self.fa_buffer[j]:byte(1) & 0x20) == 0x20 then
stdnse.debug(3,"Writeable Area: %d Row: %d Col: %d Length: %d", i + 1, self:BA_TO_ROW(i + 1), self:BA_TO_COL(i + 2), j-i-1)
stdnse.debug(3,"[WRITEABLE] Area: %d Row: %d Col: %d Length: %d", i + 1, self:BA_TO_ROW(i + 1), self:BA_TO_COL(i + 2), j-i-1)
table.insert(writeable_list, {i + 1, j-i-1})
break
end
@@ -1240,13 +1271,13 @@ Telnet = {
end
end
--local buff = self:get_screen()
stdnse.debug(3, "Looking for: " ..str)
stdnse.debug(3, "[FIND] Looking for: %s", tostring(str))
local i, j = string.find(buff, str)
if i == nil then
stdnse.debug(3, "Couldn't find: " ..str)
stdnse.debug(3, "[FIND] Couldn't find: %s", tostring(str))
return false
else
stdnse.debug(3, "Found String: " ..str)
stdnse.debug(3, "[FIND] Found String: %s", tostring(str))
return i , j
end
end,
@@ -1262,10 +1293,10 @@ Telnet = {
end
local i, j = string.find(buff, '%w')
if i ~= nil then
stdnse.debug(3, "Screen has text")
stdnse.debug(3, "[CLEAR] Screen has text")
return false
else
stdnse.debug(3, "Screen is Empty")
stdnse.debug(3, "[CLEAR] Screen is Empty")
return true
end
end,
@@ -1344,8 +1375,10 @@ Telnet = {
get_lu = function ( self )
return self.connected_lu
end,
disable_tn3270e = function ( self )
stdnse.debug(3,"Disabling TN3270E")
table.insert(self.unsupported_opts,self.options.TN3270E)
end,
overwrite_data = function ( self )
if not self:any_overwritten() then
return false

View File

@@ -57,6 +57,7 @@ found for CICS transaction IDs.
-- 2015-07-04 - v0.1 - created by Soldier of Fortran
-- 2015-11-14 - v0.2 - rewrote iterator
-- 2017-01-22 - v0.3 - added authenticated CICS ID enumeration
-- 2019-02-01 - v0.4 - Removed TN3270E support (breaks location)
--
-- @author Philip Young
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html
@@ -90,6 +91,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new()
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -263,6 +265,7 @@ Driver = {
local function cics_test( host, port, commands, user, pass )
stdnse.debug("Checking for CICS")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
local msg = 'Unable to get to CICS'
local cics = false -- initially we're not at CICS

View File

@@ -34,6 +34,7 @@ CICS User ID brute forcing script for the CESL login screen.
-- 2016-08-29 - v0.1 - created by Soldier of Fortran
-- 2016-10-26 - v0.2 - Added RACF support
-- 2017-01-23 - v0.3 - Rewrote script to use fields and skip enumeration to speed up testing
-- 2019-02-01 - v0.4 - Disabled new TN3270E support
author = "Philip Young aka Soldier of Fortran"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
@@ -60,6 +61,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new(brute.new_socket())
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -120,9 +122,10 @@ Driver = {
-- Ok we're good we're at CESL. Send the Userid and Password.
local fields = self.tn3270:writeable() -- Get the writeable field areas
local user_loc = {fields[1][1],user} -- This is the 'UserID:' field
local pass_loc = {fields[3][1],pass} -- This is the 'Password:' field ([2] is a group ID)
stdnse.verbose('Trying CICS: ' .. user ..' : ' .. pass)
local user_loc = {fields[2][1],user} -- This is the 'UserID:' field
local pass_loc = {fields[4][1],pass} -- This is the 'Password:' field ([2] is a group ID)
stdnse.verbose('[BRUTE] Trying CICS: ' .. user ..' : ' .. pass)
stdnse.debug(3,"[BRUTE] Location:" .. fields[2][1] .. " x " .. fields[4][1])
self.tn3270:send_locations({user_loc,pass_loc})
self.tn3270:get_all_data()
stdnse.debug(2,"Screen Received for User ID: %s/%s", user, pass)
@@ -194,6 +197,7 @@ Driver = {
local function cics_test( host, port, commands )
stdnse.verbose(2,"Checking for CICS Login Page")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
local cesl = false -- initially we're not at CICS
if not status then

View File

@@ -37,6 +37,7 @@ CICS User ID enumeration script for the CESL/CESN Login screen.
-- @changelog
-- 2016-08-29 - v0.1 - created by Soldier of Fortran
-- 2016-12-19 - v0.2 - Added RACF support
-- 2019-02-01 - v0.3 - Disabled TN3270E support
--
-- @author Philip Young
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html
@@ -56,6 +57,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new()
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -108,8 +110,8 @@ Driver = {
end
-- At this point we MUST be at CESL/CESN to try accounts.
-- If we're not then we quit with an error
if not (self.tn3270:find('SIGN ON TO CICS') or self.tn3270:find("Signon to CICS")) then
local err = brute.Error:new( "Can't get to Transaction")
if not (self.tn3270:find('Type your userid and password')) then
local err = brute.Error:new( "Can't get to Transaction CESN")
err:setRetry( true )
return false, err
end
@@ -158,6 +160,7 @@ Driver = {
local function cics_test( host, port, commands, transaction )
stdnse.verbose(2,"Checking for CICS Login Page")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
local cesl = false -- initially we're not at CICS
if not status then
@@ -176,7 +179,7 @@ local function cics_test( host, port, commands, transaction )
tn:get_all_data()
tn:get_screen_debug(2) -- for debug purposes
-- We should now be at CICS. Check if we're already at the logon screen
if tn:find('SIGN ON TO CICS') and tn:find("Signon to CICS") then
if tn:find('Type your userid and password') then
stdnse.verbose(2,"At CICS Login Transaction")
tn:disconnect()
return true

View File

@@ -44,13 +44,15 @@ Hidden fields will be listed below the screen with (row, col) coordinates.
--
-- @args tn3270-screen.commands a semi-colon separated list of commands you want to
-- issue before printing the screen
-- tn3270-screen.lu a logical unit you with to use fails if can't connect
-- tn3270-screen.lu specify a logical unit you with to use, fails if can't connect
-- tn3270-screen.disable_tn3270e disables TN3270 Enhanced mode
--
--
-- @changelog
-- 2015-05-30 - v0.1 - created by Soldier of Fortran
-- 2015-11-14 - v0.2 - added commands argument
-- 2018-09-07 - v0.3 - added support for Logical Units
-- 2019-02-01 - v0.4 - Added ability to disable TN3270E mode
--
author = "Philip Young aka Soldier of Fortran"
@@ -67,12 +69,17 @@ local hidden_field_mt = {
action = function(host, port)
local commands = stdnse.get_script_args(SCRIPT_NAME .. '.commands')
local disable_tn3270e = stdnse.get_script_args(SCRIPT_NAME .. '.disable_tn3270e') or false
local lu = stdnse.get_script_args(SCRIPT_NAME .. '.lu')
local t = tn3270.Telnet:new()
if lu then
if lu and not disable_tn3270e then
stdnse.debug("Setting LU: %s", lu)
t:set_lu(lu)
end
if disable_tn3270e then
t:disable_tn3270e()
end
local status, err = t:initiate(host,port)
if not status then
stdnse.debug("Could not initiate TN3270: %s", err )
@@ -107,7 +114,9 @@ action = function(host, port)
local out = stdnse.output_table()
out.screen = t:get_screen()
out["hidden fields"] = hidden
if not disable_tn3270e then
out["logical unit"]= t:get_lu()
end
return out
end
end

View File

@@ -75,6 +75,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new(brute.new_socket())
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -228,6 +229,7 @@ Driver = {
local function tso_test( host, port, commands )
stdnse.debug("Checking for TSO")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
local tso = false -- initially we're not at TSO logon panel
local secprod = "RACF"
@@ -259,7 +261,7 @@ local function tso_test( host, port, commands )
end
tn:send_pf(3)
tn:disconnect()
return tso, secprod, "Could not get to TSO. Try --script-args=tso-enum.commands='logon applid(tso)'. Aborting."
return tso, secprod, "Could not get to TSO. Try --script-args=tso-brute.commands='logon applid(tso)'. Aborting."
end
--- Tests the target to see if we can speed up brute forcing
@@ -274,6 +276,7 @@ end
local function tso_skip( host, port, commands )
stdnse.debug("Checking for IKJ56700A message skip")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
stdnse.debug2("Connecting TN3270 to %s:%s", host.targetname or host.ip, port.number)
local status, err = tn:initiate(host,port)
stdnse.debug2("Displaying initial TN3270 Screen:")

View File

@@ -57,6 +57,7 @@ TSO user IDs have the following rules:
-- 2015-10-30 - v0.2 - streamlined the code, relying on brute and unpwdb and
-- renamed to tso-enum.
-- 2017-1-13 - v0.3 - Fixed 'data' bug and added options checking to speedup
-- 2019-02-01 - v0.4 - Disabled TN3270 Enhanced support and fixed debug errors
author = "Philip Young aka Soldier of Fortran"
@@ -74,6 +75,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new()
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -165,6 +167,7 @@ Driver = {
local function tso_test( host, port, commands )
stdnse.debug("Checking for TSO")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
local tso = false -- initially we're not at TSO logon panel
local secprod = "RACF"
@@ -211,6 +214,7 @@ end
local function tso_skip( host, port, commands )
stdnse.debug("Checking for IKJ56700A message skip")
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
stdnse.debug2("Connecting TN3270 to %s:%s", host.targetname or host.ip, port.number)
local status, err = tn:initiate(host,port)
stdnse.debug2("Displaying initial TN3270 Screen:")

View File

@@ -57,7 +57,7 @@ found for application IDs.
-- 2015-11-14 - v0.3 - rewrote iterator
-- 2017-01-13 - v0.4 - Fixed 'macros' bug with default vtam screen and test
-- and added threshold for macros screen checking
--
-- 2019-02-01 - v0.5 - Disabling Enhanced mode
author = "Philip Young aka Soldier of Fortran"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
@@ -104,6 +104,7 @@ Driver = {
o.port = port
o.options = options
o.tn3270 = tn3270.Telnet:new()
o.tn3270:disable_tn3270e()
return o
end,
connect = function( self )
@@ -181,6 +182,7 @@ Driver = {
-- @return status true on success, false on failure
local function vtam_test( host, port, commands, macros)
local tn = tn3270.Telnet:new()
tn:disable_tn3270e()
local status, err = tn:initiate(host,port)
stdnse.debug1("Testing if VTAM and 'logon applid' command supported")
stdnse.debug2("Connecting TN3270 to %s:%s", host.targetname or host.ip, port.number)