mirror of
https://github.com/nginx/nginx.git
synced 2026-08-04 14:58:20 +00:00
Dav: improved path validation for COPY and MOVE operations
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.
This commit is contained in:
parent
3b5da468b3
commit
f0a084645b
1 changed files with 71 additions and 0 deletions
|
|
@ -47,6 +47,9 @@ static ngx_int_t 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);
|
||||
static void ngx_http_dav_merge_slashes(ngx_str_t *path);
|
||||
static ngx_int_t ngx_http_dav_validate_paths(ngx_http_request_t *r,
|
||||
ngx_str_t *src, ngx_str_t *dst, ngx_uint_t slash, ngx_table_elt_t *dest);
|
||||
static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
|
||||
static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx,
|
||||
ngx_str_t *path);
|
||||
|
|
@ -719,6 +722,9 @@ overwrite_done:
|
|||
|
||||
r->uri = uri;
|
||||
|
||||
ngx_http_dav_merge_slashes(&path);
|
||||
ngx_http_dav_merge_slashes(©.path);
|
||||
|
||||
copy.path.len--; /* omit "\0" */
|
||||
|
||||
if (copy.path.data[copy.path.len - 1] == '/') {
|
||||
|
|
@ -733,6 +739,12 @@ overwrite_done:
|
|||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http copy to: \"%s\"", copy.path.data);
|
||||
|
||||
if (ngx_http_dav_validate_paths(r, &path, ©.path, slash, dest)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
if (ngx_link_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
|
||||
err = ngx_errno;
|
||||
|
||||
|
|
@ -870,6 +882,65 @@ overwrite_done:
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_dav_merge_slashes(ngx_str_t *path)
|
||||
{
|
||||
u_char *p, *q;
|
||||
|
||||
p = path->data;
|
||||
q = path->data;
|
||||
|
||||
while (*p) {
|
||||
*q++ = *p;
|
||||
|
||||
if (*p++ == '/') {
|
||||
while (*p == '/') {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*q++ = '\0';
|
||||
path->len = q - path->data;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_dav_validate_paths(ngx_http_request_t *r, ngx_str_t *src,
|
||||
ngx_str_t *dst, ngx_uint_t slash, ngx_table_elt_t *dest)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = src->len - 1;
|
||||
|
||||
if (len > 0 && src->data[len - 1] == '/') {
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len == dst->len && ngx_strncmp(src->data, dst->data, len) == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"both URI \"%V\" and \"Destination\" URI \"%V\" "
|
||||
"point to the same location",
|
||||
&r->uri, &dest->value);
|
||||
return NGX_HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
if (slash
|
||||
&& ngx_strncmp(src->data, dst->data, ngx_min(len, dst->len)) == 0
|
||||
&& (len < dst->len
|
||||
? dst->data[len] == '/'
|
||||
: src->data[dst->len] == '/'))
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"\"%V\" could not be %Ved to collection \"%V\"",
|
||||
&r->uri, &r->method_name, &dest->value);
|
||||
return NGX_HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue