Impact
CWE-404: Improper Resource Shutdown or Release
Improper use of :set_keepalive()
instead of :close()
on an upstream socket containing incomplete request data (e.g. after a client abort) does not clear that data from the socket buffer.
A subsequent request allocated to the same socket will be appended onto the first request, receiving the response to the first request. This may contain sensitive data, including cookies and request body, or a corrupted response.
As this issue can leak sensitive data between unrelated HTTP clients that may lead to further exploits, this is of High severity (8.7 CVSS 3.1).
Patches
Fixed in release v2.1.4
and above. Aborted client requests always run :close()
against the upstream socket.
Workarounds
Systems with ledge
running behind a proxy that already buffers request bodies, e.g. another nginx instance using proxy_pass
, may not expose this issue.
Ideally, update to a patched version of ledge
.
If this is not possible, use the event system to bind to before_upstream_connect
, manually creating a lua-resty-http
client instance and setting httpc.keepalive = false
:
require("ledge").bind("before_upstream_connect", function(handler)
local http = require("resty.http")
local config = handler.config
local httpc = http.new()
httpc:set_timeouts(
config.upstream_connect_timeout,
config.upstream_send_timeout,
config.upstream_read_timeout
)
local port = tonumber(config.upstream_port)
local ok, err
if port then
ok, err = httpc:connect(config.upstream_host, port)
else
ok, err = httpc:connect(config.upstream_host)
end
if not ok then
ngx_log(ngx_ERR, "upstream connection failed: ", err)
if err == "timeout" then
res.status = 524 -- upstream server timeout
else
res.status = 503
end
return res
end
if config.upstream_use_ssl == true then
-- treat an empty ("") ssl_server_name as nil
local ssl_server_name = config.upstream_ssl_server_name
if type(ssl_server_name) ~= "string" or
str_len(ssl_server_name) == 0 then
ssl_server_name = nil
end
local ok, err = httpc:ssl_handshake(
false,
ssl_server_name,
config.upstream_ssl_verify
)
if not ok then
ngx_log(ngx_ERR, "ssl handshake failed: ", err)
res.status = 525 -- SSL Handshake Failed
return res
end
end
-- Disable http keepalives to avoid aborted request leaks
httpc.keepalive = false
handler.upstream_client = httpc
end)
References
https://en.wikipedia.org/wiki/HTTP_persistent_connection
For more information
If you have any questions or comments about this advisory:
- Open an issue in the ledge repository
Impact
CWE-404: Improper Resource Shutdown or Release
Improper use of
:set_keepalive()
instead of:close()
on an upstream socket containing incomplete request data (e.g. after a client abort) does not clear that data from the socket buffer.A subsequent request allocated to the same socket will be appended onto the first request, receiving the response to the first request. This may contain sensitive data, including cookies and request body, or a corrupted response.
As this issue can leak sensitive data between unrelated HTTP clients that may lead to further exploits, this is of High severity (8.7 CVSS 3.1).
Patches
Fixed in release
v2.1.4
and above. Aborted client requests always run:close()
against the upstream socket.Workarounds
Systems with
ledge
running behind a proxy that already buffers request bodies, e.g. another nginx instance usingproxy_pass
, may not expose this issue.Ideally, update to a patched version of
ledge
.If this is not possible, use the event system to bind to
before_upstream_connect
, manually creating alua-resty-http
client instance and settinghttpc.keepalive = false
:References
https://en.wikipedia.org/wiki/HTTP_persistent_connection
For more information
If you have any questions or comments about this advisory: