Previously, if proxy_set_body was used with HTTP/2, and body size exceeded
16M, then an overflow happened in the 24-bit DATA frame size, which resulted
in sending unframed bytes, potentially allowing for an injection.
Also, DATA frame size could exceed NGX_HTTP_V2_DEFAULT_FRAME_SIZE (16K) and
available send window.
Reported by Mufeed VH of Winfunc Research.
The following code resulted in incorrect escaping of $1 and possible
segfault:
location / {
rewrite ^(.*) /new?c=1;
set $myvar $1;
return 200 $myvar;
}
If there were arguments in a rewrite's replacement string, the is_args flag
was set and incorrectly never cleared. This resulted in escaping applied
to any captures evaluated afterwards in set or if. Additionally buffer was
allocated by ngx_http_script_complex_value_code() without escaping expected,
thus this also resulted in buffer overrun and possible segfault.
A similar issue was fixed in 74d939974d.
Reported by Leo Lin.
If the first response line was split across reads and it didn't appear
a status line, the portion already processed was lost. To preserve ABI,
the change reuses r->header_name_start for proper backtracking on status
line fallback.
Previously, it was possible to start parsing headers with a wrong
parsing state after status line was not recognized, as a fallback
used in the scgi and uwsgi modules.
Reported by Leo Lin.
When a multi-byte UTF-8 character was split across 3+ single-byte
buffers, the saved bytes continuation path had two related bugs:
ngx_utf8_decode() was called with the last saved-array index instead
of the byte count, causing it to report "incomplete" even when the
sequence was already complete.
The subsequent ngx_memcpy() used that same index as the copy length,
reading past the input buffer boundary.
Previously, when a client migrated to a new address, new QUIC streams
received this address before validation. This allowed an attacker to
create QUIC streams with a spoofed address.
Reported by Rodrigo Laneth.
Previously, when a client SSL connection was terminated (typically due to a
timeout) while resolving an OCSP responder, the OCSP context was freed, but
the resolve context was not. This resulted in use-after-free on resolve
completion.
Reported by Leo Lin.
Previously, when an HTTP/2 request had no body or an explicit body
was set by proxy_set_body, the request consisted of only one buffer,
which had no b->last_buf flag set. This prevented ctx->output_closed
from being set after processing this buffer. Consequently,
u->keepalive might not be set to store the connection in the
keepalive cache.
When a request was retried to a new upstream after receiving 103
Early Hints from the previous one, the accumulated early_hints_length
was not reset, causing valid early hints from the next upstream to be
incorrectly rejected as "too big".
The directive limits the number of request headers accepted from clients.
While the total amount of headers is believed to be sufficiently limited
by the existing buffer size limits (client_header_buffer_size and
large_client_header_buffers), the additional limit on the number of headers
might be beneficial to better protect backend servers.
Requested by Maksim Yevmenkin.
Signed-off-by: Elijah Zupancic <e.zupancic@f5.com>
Origin: <https://freenginx.org/hg/nginx/rev/199dc0d6b05be814b5c811876c20af58cd361fea>
The issue described below was only reproducible prior to
7924a4ec6c
When parsing the `charset` parameter in the `Content-Type` header within
`ngx_http_upstream_copy_content_type`, an input such as `charset="`
resulted in an integer underflow.
In this scenario, both `p` and `last` point to the position immediately
following the opening quote. The logic to strip a trailing quote checked
`*(last - 1)` without verifying that `last > p`. This caused `last` to
be decremented to point to the opening quote itself, making `last < p`.
The subsequent length calculation `r->headers_out.charset.len = last - p`
resulted in -1, which wrapped to `SIZE_MAX` as `len` is a `size_t`. This
invalid length was later passed to `ngx_cpymem` in `ngx_http_header_filter`,
leading to an out-of-bounds memory access (detected as
`negative-size-param` by AddressSanitizer).
The fix ensures `last > p` before attempting to strip a trailing quote,
correctly resulting in a zero-length charset for malformed input.
The oss-fuzz payload that triggers this issue holds multiple 103 status
lines, and it's a sequence of 2 of those Content-Type headers that
trigger the ASAN report.
Co-authored-by: CodeMender <codemender-patching@google.com>
Fixes: https://issues.oss-fuzz.com/issues/486561029
Signed-off-by: David Korczynski <david@adalogics.com>
CLOCK_MONOTONIC_FAST, like CLOCK_MONOTONIC_COARSE, has low accuracy. It
shows noticeable timing variation for short intervals, which is visible
in metrics like $upstream_response_time for fast upstream responses.
This change complements the work started in commit f29d7ade5.
In addition to the reasons described in f29d7ade5, the performance of
CLOCK_MONOTONIC is good enough on modern hardware when using a TSC
timecounter. This is especially true when it is accessed through a
shared page, as implemented in FreeBSD 10.0 (see git commits
869fd80fd449 and aea810386d8e for details).
Co-authored-by: Sergey Kandaurov <pluknet@nginx.com>
X509_get_issuer_name() and X509_get_subject_name() were changed to return
a const value. Since it is passed to functions with a non const argument
in older versions, the const modifier is conditionally compiled as needed.
ASN1_INTEGER was made opaque. ASN1_STRING accessors are used to preserve
the behaviour. ASN1_STRING_get0_data() compat shim is provided for OpenSSL
< 1.1.0 where it does not exist.
Previously, it was not properly cleared retaining length as part of
authenticating with CRAM-MD5 and APOP methods that expect to receive
password in auth response. This resulted in null pointer dereference
and worker process crash in subsequent auth attempts with CRAM-MD5.
Reported by Arkadi Vainbrand.
Now host name resolved from client address is validated to only contain
the characters specified in RFC 1034, Section 3.5. The validation allows
to avoid injections when using the resolved host name in auth_http and
smtp proxy.
Reported by Asim Viladi Oglu Manizada, Colin Warren,
Xiao Liu (Yunnan University), Yuan Tan (UC Riverside), and
Bird Liu (Lanzhou University).
Previously, when alias was used in a location with Dav COPY or MOVE
enabled, and the destination URI was shorter than the alias, integer
underflow could happen in ngx_http_map_uri_to_path(), which could
result in heap buffer overwrite, followed by a possible segfault.
With some implementations of memcpy(), the segfault could be avoided
and the overwrite could result in a change of the source or destination
file names to be outside of the location root.
Reported by Calif.io in collaboration with Claude and Anthropic Research.
Previously, a 32-bit overflow could happen while validating atom entries
count. This allowed processing of an invalid atom with entrires beyond
its boundaries with reads and writes outside of the allocated mp4 buffer.
Reported by Prabhav Srinath (sprabhav7).
Previously, data validation checks did not cover the cases when the output
contained empty buffers. Such buffers are considered illegal and produce
"zero size buf in output" alerts. The change rejects the mp4 files which
produce such alerts.
Also, the change fixes possible buffer overread and overwrite that could
happen while processing empty stco and co64 atoms, as reported by
Pavel Kohout (Aisle Research) and Tim Becker.
Updates the proxy module to use HTTP/1.1 as the default protocol when
communicating with upstream servers. This change unlocks features
such as persistent connections and chunked transfer encoding. Configurations
that require HTTP/1.0 can still override the protocol explicitly.
Keepalive is now automatically enabled in the "local" mode for upstreams
defined in configuration files. Cached keepalive connections are no longer
shared between different locations referencing the same explicit upstream
unless keepalive is explicitly configured without the "local" parameter.
To disable keepalive entirely, use keepalive 0; inside the upstream block.
To allow sharing cached connections between locations, configure
keepalive <max_cached>; without the "local" parameter.
The new "local" parameter prevents sharing cached keepalive connections
between location blocks. Connections are now reused only within the same
location.
When configured, it enables Multipath TCP support on a listen socket.
As of now it works on Linux starting with Linux 5.6 and glibc 2.32,
where it is enabled with an IPPROTO_MPTCP socket(2) protocol.
To avoid EADDRINUSE errors in bind() and listen() when transitioning
between sockets with different protocols, SO_REUSEPORT is set on both
sockets. See f7f1607bf for potential implications.
Based on previous work by Maxime Dourov and Anthony Doeraene.
Previously, ctx->out was not cleared in ngx_http_grpc_reinit_request(),
which could cause queued HTTP/2 control frames (SETTINGS ACK, PING ACK,
WINDOW_UPDATE) to be sent on next upstream.
Additionally, ctx->in and ctx->busy needs to be cleared to avoid similar
problems with buffered request body fixed in cd12dc4f1.
Previously, ctx->out was not cleared in ngx_http_proxy_v2_reinit_request(),
which could cause stale HTTP/2 control frames (SETTINGS ACK, PING ACK,
WINDOW_UPDATE) queued for the old upstream connection to be sent to a new
upstream connection during a retry.
Previously, the expiration timer for learned session was not started
until a new session is created. This could lead to the sessions being
active past the expiration time.
RFC 6265 defines "Max-Age" cookie attribute in section 5.2.2.
If the "expires" option is passed to the "sticky" directive, "max-age"
attribute will appear in cookies set by the module with corresponding
value in seconds.
For the special "max" value of the "expires" option, corresponding "max-age"
attribute value will be set to 315360000 seconds (10 years, similar to
how its done in headers_filter module for the "Cache-Control" header).