From 9739e755b8dddba82e65ca2a08d079f4c9826b75 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Mon, 16 Mar 2026 20:13:03 +0400 Subject: Dav: destination length validation for COPY and MOVE. 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. --- src/http/modules/ngx_http_dav_module.c | 39 ++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'src/http/modules') diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c index cfb98929e..4619b139a 100644 --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -535,19 +535,20 @@ ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf) static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r) { - u_char *p, *host, *last, ch; - size_t len, root; - ngx_err_t err; - ngx_int_t rc, depth; - ngx_uint_t overwrite, slash, dir, flags; - ngx_str_t path, uri, duri, args; - ngx_tree_ctx_t tree; - ngx_copy_file_t cf; - ngx_file_info_t fi; - ngx_table_elt_t *dest, *over; - ngx_ext_rename_file_t ext; - ngx_http_dav_copy_ctx_t copy; - ngx_http_dav_loc_conf_t *dlcf; + u_char *p, *host, *last, ch; + size_t len, root; + ngx_err_t err; + ngx_int_t rc, depth; + ngx_uint_t overwrite, slash, dir, flags; + ngx_str_t path, uri, duri, args; + ngx_tree_ctx_t tree; + ngx_copy_file_t cf; + ngx_file_info_t fi; + ngx_table_elt_t *dest, *over; + ngx_ext_rename_file_t ext; + ngx_http_dav_copy_ctx_t copy; + ngx_http_dav_loc_conf_t *dlcf; + ngx_http_core_loc_conf_t *clcf; if (r->headers_in.content_length_n > 0 || r->headers_in.chunked) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -644,6 +645,18 @@ destination_done: return NGX_HTTP_CONFLICT; } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->alias + && clcf->alias != NGX_MAX_SIZE_T_VALUE + && duri.len < clcf->alias) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client sent invalid \"Destination\" header: \"%V\"", + &dest->value); + return NGX_HTTP_BAD_REQUEST; + } + depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { -- cgit