do not try to read request body in HTTP2/3 if there's no content-length header (#64)

This commit is contained in:
blotus 2024-02-22 10:18:05 +01:00 committed by GitHub
parent 26e9c0c19c
commit cce2ea3946
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -90,7 +90,7 @@ function csmod.init(configFile, userAgent)
runtime.conf["APPSEC_ENABLED"] = false
if runtime.conf["APPSEC_URL"] ~= "" then
u = url.parse(runtime.conf["APPSEC_URL"])
local u = url.parse(runtime.conf["APPSEC_URL"])
runtime.conf["APPSEC_ENABLED"] = true
runtime.conf["APPSEC_HOST"] = u.host
if u.port ~= nil then
@ -193,7 +193,7 @@ local function item_to_string(item, scope)
local ip_network_address, is_ipv4 = iputils.parseIPAddress(ip)
if ip_network_address == nil then
return nil
end
end
if is_ipv4 then
ip_version = "ipv4"
if cidr == nil then
@ -221,11 +221,11 @@ local function set_refreshing(value)
end
if forcible then
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
end
end
end
local function stream_query(premature)
-- As this function is running inside coroutine (with ngx.timer.at),
-- As this function is running inside coroutine (with ngx.timer.at),
-- we need to raise error instead of returning them
@ -283,7 +283,7 @@ local function stream_query(premature)
end
if forcible then
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
end
end
local status = res.status
local body = res.body
@ -345,7 +345,7 @@ local function stream_query(premature)
end
if forcible then
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
end
end
local ok, err = ngx.timer.at(runtime.conf["UPDATE_FREQUENCY"], stream_query)
@ -369,7 +369,7 @@ local function live_query(ip)
local status = res.status
local body = res.body
if status~=200 then
return true, nil, "Http error " .. status .. " while talking to LAPI (" .. link .. ")"
return true, nil, "Http error " .. status .. " while talking to LAPI (" .. link .. ")"
end
if body == "null" then -- no result from API, no decision for this IP
-- set ip in cache and DON'T block it
@ -407,6 +407,13 @@ end
local function get_body()
-- the LUA module requires a content-length header to read a body for HTTP 2/3 requests, although it's not mandatory.
-- This means that we will likely miss body, but AFAIK, there's no workaround for this.
-- do not even try to read the body if there's no content-length as the LUA API will throw an error
if ngx.req.http_version() >= 2 and ngx.var.http_content_length == nil then
ngx.log(ngx.DEBUG, "No content-length header in request")
return nil
end
ngx.req.read_body()
local body = ngx.req.get_body_data()
if body == nil then
@ -468,7 +475,7 @@ function csmod.allowIp(ip)
return in_cache, runtime.remediations[tostring(remediation_id)], nil
end
end
local ip_network_address = key_parts[3]
local netmasks = iputils.netmasks_by_key_type[key_type]
for i, netmask in pairs(netmasks) do
@ -528,6 +535,8 @@ function csmod.AppSecCheck(ip)
headers["content-length"] = tostring(#body)
end
end
else
headers["content-length"] = nil
end
local res, err = httpc:request_uri(runtime.conf["APPSEC_URL"], {
@ -641,8 +650,11 @@ function csmod.Allow(ip)
-- we check if the IP need to validate its captcha before checking it against crowdsec local API
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ip)
local source, state_id, err = flag.GetFlags(flags)
if previous_uri ~= nil and state_id == flag.VERIFY_STATE then
ngx.req.read_body()
local body = get_body()
-- nil body means it was likely not a post, abort here because the user hasn't provided a captcha solution
if previous_uri ~= nil and state_id == flag.VERIFY_STATE and body ~= nil then
local captcha_res = ngx.req.get_post_args()[csmod.GetCaptchaBackendKey()] or 0
if captcha_res ~= 0 then
local valid, err = csmod.validateCaptcha(captcha_res, ip)
@ -719,4 +731,4 @@ end
function csmod.close()
end
return csmod
return csmod