[PATCH] Variables: avoid possible buffer overrun with some "$sent_http_*"

Maxim Dounin mdounin at mdounin.ru
Sat Apr 29 14:50:05 UTC 2023


Hello!

On Thu, Apr 27, 2023 at 09:53:30PM +0400, Sergey Kandaurov wrote:

> # HG changeset patch
> # User Sergey Kandaurov <pluknet at nginx.com>
> # Date 1682617947 -14400
> #      Thu Apr 27 21:52:27 2023 +0400
> # Node ID c1ec385d885fba38f15d54263944eed2c74b5733
> # Parent  77d5c662f3d9d9b90425128109d3369c30ef5f07
> Variables: avoid possible buffer overrun with some "$sent_http_*".
> 
> The existing logic to evaluate multi header "$sent_http_*" variables,
> such as $sent_http_cache_control, as previously introduced in 1.23.0,
> doesn't take into account that one or more elements can be cleared,
> yet still present in a linked list, pointed to by the next field.
> Such elements don't contribute to the resulting variable length, an
> attempt to append a separator for them ends up in out of bounds write.
> 
> This is not possible with standard modules, though at least one third
> party module is known to override multi header values this way, so it
> makes sense to harden the logic.
> 
> The fix restores a generic boundary check.
> 
> diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
> --- a/src/http/ngx_http_variables.c
> +++ b/src/http/ngx_http_variables.c
> @@ -828,7 +828,7 @@ ngx_http_variable_headers_internal(ngx_h
>      ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
>  {
>      size_t            len;
> -    u_char           *p;
> +    u_char           *p, *end;
>      ngx_table_elt_t  *h, *th;
>  
>      h = *(ngx_table_elt_t **) ((char *) r + data);
> @@ -870,6 +870,8 @@ ngx_http_variable_headers_internal(ngx_h
>      v->len = len;
>      v->data = p;
>  
> +    end = p + len;
> +
>      for (th = h; th; th = th->next) {
>  
>          if (th->hash == 0) {
> @@ -878,7 +880,7 @@ ngx_http_variable_headers_internal(ngx_h
>  
>          p = ngx_copy(p, th->value.data, th->value.len);
>  
> -        if (th->next == NULL) {
> +        if (p == end) {
>              break;
>          }
>  

Looks good.

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx-devel mailing list