When the rewrite replacement string had no variables, but had
overlapping captures, the length of the allocated buffer could be
smaller than the replacement string. This could happen either
when the "redirect" parameter is specified, or when arguments are
present in the replacement string.
The following configurations resulted in heap buffer overflow when
using URI "/++++++++++++++++++++++++++++++":
location / {
rewrite ^/((.*))$ http://127.0.0.1:8080/$1$2 redirect;
return 200 foo;
}
location / {
rewrite ^/((.*))$ http://127.0.0.1:8080/?$1$2;
return 200 foo;
}
Reported by Mufeed VH of Winfunc Research.
Following 2046b45aa0, this change introduces better control of memory
allocation flags for escaped values. Notably:
- The e->is_args flag is now explicitly reset on rewrite start.
If the flag was set prior to rewrite start, then buffer overflow
could happen before 2046b45aa0.
- The le->is_args flag value is now copied from e->is_args when
calculating complex value length for "if" and "set" directives.
If e->is_args was set, but le->is_args was not, then buffer overflow
could happen before 2046b45aa0.
Previously, when ngx_handle_read_event() or ngx_handle_write_event()
returned an error while handling an SMTP, POP3 or IMAP session, the
released session memory could be accessed after handling the error.
Previously, when these fields were larger than ~2M, the number of bytes
allocated for the field length was insufficient for such a large number.
The deficit is 1 byte up until ~4M, 2 bytes for sizes above, and grows
bigger with even larger fields.
Currently, nginx does not have modules which allow to exploit this
overflow with reasonably large Content-Type and Location. The reason is
other response fields make up for this deficit. For example, the Date
header value contains the characters compressed well by Huffman
encoding, which frees up spare bytes in the header buffer.
Reported by Leo Lin.
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. The change
introduces a new field 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.
Notably, "auth_delay" now delays the response for both 401 and 407.
Also, in the "satisfy any" mode, the next access/auth attempt is made
for 401, 403 and 407.
To avoid future churn give the workflow a generic name, don't operate on
pull-requests, and extend the issues stale date to 365 days and update
its message.
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.
The COPY and MOVE handler did not validate whether source and
destination paths referred to the same resource or a parent-child
collection relationship, which could corrupt or destroy files.
Now 403 is returned if paths match or one is a prefix of the other.
Reported by Mufeed VH of Winfunc Research.
Example configuration:
upstream u {
least_time connect | first_byte | last_byte [inflight];
server a;
server b;
}
Co-authored-by: Roman Arutyunyan <arut@nginx.com>
The module implements load-balancing algorithm based on least average
response header/last_byte time and least number of active connections.
The optional "inflight" mode enables accounting of incomplete
requests/sessions. This allows to mitigate cases when an upstream
server hangs and does not close connections.
Example configuration:
upstream u {
least_time header | last_byte [inflight];
server a;
server b;
}
Co-authored-by: Roman Arutyunyan <arut@nginx.com>
If the "gcc version ... " string appeared within "Configured with:", it
was picked up rather than the real gcc version string. This might then
break the configure scripts due to a malformed NGX_COMPILER macro.
The simple fix is to look for "gcc version ... " at the start of the
line, rather than anywhere within.
Suggested-by: Aleksei Bavshin <a.bavshin@nginx.com>
Closes: https://github.com/nginx/nginx/issues/1278
This restores a long-standing optimization when the entire request
body is empty and r->request_body_in_file_only is set, used to avoid
writing an empty file as initially introduced in 4c7f51136 (0.4.4).
The previous condition never worked with chunked body filter, where
rb->bufs holds at least the final chunk; in length body filter, it is
used to indicate the last received buffer since 2a7092138 (1.21.2).
The fix is to additionally check if it is the only empty buffer.
Found with UndefinedBehaviorSanitizer (pointer-overflow)
The module can now be disabled with the
--without-http_upstream_sticky_module option to match
the naming convention used by other upstream modules.
Deprecated the --without-http_upstream_sticky option.
Closes: https://github.com/nginx/nginx/issues/1273
This runs git-log(1) --check on *each* commit and will report any
issues, e.g.
--- afe5753fa ("Changes made in upstream")
src/http/ngx_http_upstream.c:415: trailing whitespace.
+
src/http/ngx_http_upstream.c:417: trailing whitespace.
+ ngx_http_upstream_backend_ssl_protocol, 0,
Specific exceptions can be handled via gitattributes(5).
In the third call to ngx_pstrdup() for setting cycle->conf_param.data in
ngx_init_cycle() we would pass in a nulled ngx_str_t in the case there
was no -g command line option passed to nginx.
This would result in a
memcpy(dst, NULL, 0)
which up to and including C23 is Undefined Behaviour.
Currently Clang and GCC (in this particular case) just treat this as a
no-op, so things just happen to work.
However some undefined behaviour sanitizers will throw an error when
this is hit, e.g. Clang and the zig compiler and it's probably best not
to rely on this behaviour.
It's worth noting that the next C standard will make this (and other
NULL related operations) defined behaviour.
Link: <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>
Closes: https://github.com/nginx/nginx/issues/1079
Added the proxy_ssl_alpn directive, which sets the list of protocols
to advertise via ALPN during upstream TLS handshakes. Each argument
is a complex value, so variables are accepted. In particular,
proxy_ssl_alpn $ssl_alpn_protocol;
inherits the protocol negotiated in the downstream TLS handshake.
When all evaluated values are empty or absent, no ALPN extension is
sent, equivalent to the directive not being set at all.
Closes#406 on GitHub.
Previously, the encoder stream allocated each new inserted field in the
connection pool. This memory was not freed until the end of the connection.
Now a special insert buffer is used for all inserts.
The SSL_R_RECORD_LAYER_FAILURE ("record layer failure") errors are
reported by OpenSSL 3.2 or newer as the last record layer error for
various low level read errors. Further, a976e6b9e (1.23.4) caused
to always log them at the "crit" level. For example, the following
errors are observed on OpenSSL 3.2.0 - 4.0:
SSL_read() failed (SSL: error:0A000119:SSL routines::decryption failed
or bad record mac error:0A000139:SSL routines::record layer failure)
SSL_read() failed (SSL: error:1C800066:Provider routines::cipher operation
failed error:0A000119:SSL routines::decryption failed or bad record mac
error:0A000139:SSL routines::record layer failure)
SSL_read() failed (SSL: error:0A00010B:SSL routines::wrong version number
error:0A000139:SSL routines::record layer failure)
These errors are now logged at the "info" level.
Closes: https://github.com/nginx/nginx/issues/961
Co-authored-by: Smeet23 <smeetagrawal2003@gmail.com>
Although uninitialized values aren't used in practice due to the
nature of the OpenSSL code flow, this violates the API contract.
Reported by lukefr09 on GitHub.
The SSL_R_INVALID_ALERT ("invalid alert") errors are reported by OpenSSL
1.1.1 or newer if the client sends a malformed alert. These errors are
now logged at the "info" level.
Signed-off-by: Aleksei Bavshin <a.bavshin@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/d89e0386b695>
Errors about alerts received from peers are generated by OpenSSL by adding
peer-provided alert description (from 0 to 255) to SSL_AD_REASON_OFFSET.
All such errors, including ones for unknown alerts, are now logged at the
"info" level, as these can be caused by a misbehaving client.
Signed-off-by: Aleksei Bavshin <a.bavshin@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/f5423ee155fe>