Академический Документы
Профессиональный Документы
Культура Документы
local
local
local
local
description = [[
Detects a vulnerability in netfilter and other firewalls that use helpers to
dynamically open ports for protocols such as ftp and sip.
The script works by spoofing a packet from the target server asking for opening
a related connection to a target port which will be fulfilled by the firewall
through the adequate protocol helper port. The attacking machine should be on
the same network segment as the firewall for this to work. The script supports
ftp helper on both IPv4 and IPv6. Real path filter is used to prevent such
attacks.
Based on work done by Eric Leblond.
For more information, see:
* http://home.regit.org/2012/03/playing-with-network-layers-to-bypass-firewallsfiltering-policy/
]]
---- @args firewall-bypass.helper The helper to use. Defaults to <code>ftp</code>.
-- Supported helpers: ftp (Both IPv4 and IPv6).
--- @args firewall-bypass.helperport If not using the helper's default port.
--- @args firewall-bypass.targetport Port to test vulnerability on. Target port s
hould be a
-- non-open port. If not given, the script will try to find a filtered or closed
port from
-- the port scan results.
--- @usage
-- nmap --script firewall-bypass <target>
-- nmap --script firewall-bypass --script-args firewall-bypass.helper="ftp", fir
ewall-bypass.targetport=22 <target>
--- @output
-- Host script results:
-- | firewall-bypass:
-- |_ Firewall vulnerable to bypass through ftp helper. (IPv4)
author = "Hani Benhabiles"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"vuln", "intrusive"}
ftp_helper = {
should_run = function(host, helperport)
local helperport = helperport or 21
-- IPv4 and IPv6 are supported
if nmap.address_family() ~= 'inet' and nmap.address_family() ~= 'inet6' then
return false
end
-- Test if helper port is open
local testsock = nmap.new_socket()
testsock:set_timeout(1000)
return
end
-- wait packet spoofing thread to finish
stdnse.sleep(1.5)
socket:close()
return
end,
}
-- List of helpers
local helpers = {
ftp = ftp_helper, -- FTP (IPv4 and IPv6)
}
local helper
hostrule = function(host)
helper = stdnse.get_script_args(SCRIPT_NAME .. ".helper")
if not nmap.is_privileged() then
nmap.registry[SCRIPT_NAME] = nmap.registry[SCRIPT_NAME] or {}
if not nmap.registry[SCRIPT_NAME].rootfail then
stdnse.verbose1("lacks privileges." )
nmap.registry[SCRIPT_NAME].rootfail = true
end
return false
end
if not host.interface then
return false
end
if helper and not helpers[helper] then
stdnse.debug1("%s helper not supported at the moment.", helper)
return false
end
return true
end
action = function(host, port)
local helperport = tonumber(stdnse.get_script_args(SCRIPT_NAME .. ".helperport
"))
local targetport = tonumber(stdnse.get_script_args(SCRIPT_NAME .. ".targetport
"))
local helpername
if targetport then
-- We should check if target port is not already open
local testsock = nmap.new_socket()
testsock:set_timeout(1000)
local status, _ = testsock:connect(host.ip, targetport)
if status then
stdnse.debug1("%s target port already open.", targetport)
return nil
end
testsock:close()
else
-- If not target port specified, we try to get a filtered port,
-- which would be more likely blocked by a firewall before looking for a clo
sed one.
local port = nmap.get_ports(host, nil, "tcp", "filtered") or nmap.get_ports(
host, nil, "tcp", "closed")
if port then
targetport = port.number
stdnse.debug1("%s chosen as target port.", targetport)
else
-- No closed or filtered ports to check on.
stdnse.debug1("Target port not specified and no closed or filtered port fo
und.")
return
end
end
-- If helper chosen by user
if helper then
if helpers[helper].should_run(host, helperport) then
helpers[helper].attack(host, helperport, targetport)
else
return
end
-- If no helper chosen manually, we iterate over table to find a suitable on
e.
else
for i, helper in pairs(helpers) do
if helper.should_run(host, helperport) then
helpername = i
stdnse.debug1("%s chosen as helper.", helpername)
helper.attack(host, helperport, targetport)
break
end
end
if not helpername then
stdnse.debug1("no suitable helper found.")
return nil
end
end
-- Then we check if target port is now open.
local testsock = nmap.new_socket()
testsock:set_timeout(1000)
local status, _ = testsock:connect(host.ip, targetport)
testsock:close()
if status then
-- If we could connect, then port is open and firewall is vulnerable.
local vulnstring = "Firewall vulnerable to bypass through " .. (helper or he
lpername) .. " helper. "
.. (nmap.address_family() == 'inet' and "(IPv4)" or "(IPv6)")
return stdnse.format_output(true, vulnstring)
end
end