Project

General

Profile

Actions

Bug #2717

closed

heap-use-after-free in lighttpd on broken config

Added by alaamub almost 9 years ago. Updated almost 9 years ago.

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

Description

Hi,

I'd like to report a security vulnerability in lighttpd and assign a CVE number for it.

The vulnerability is a heap-use-after-free in lighttpd when lighttpd is provided with a malicious config file (attached). An attacker could exploit this issue to execute arbitrary code in the context of the application using the library. Failed exploit attempts may result in denial-of-service conditions. I believe the issue caused by buffer.c at line (461). The unsigned char ca is used after free. details are below:

-bash-4.2$ /opt/lighttpd/sbin/lighttpd -f config
=================================================================
==15343== ERROR: AddressSanitizer: heap-use-after-free on address 0x600e0000ded8 at pc 0x4545cb bp 0x7fff7460edc0 sp 0x7fff7460edb0
READ of size 8 at 0x600e0000ded8 thread T0
    #0 0x4545ca (/opt/lighttpd-asan/sbin/lighttpd+0x4545ca)
    #1 0x454dff (/opt/lighttpd-asan/sbin/lighttpd+0x454dff)
    #2 0x42e6dc (/opt/lighttpd-asan/sbin/lighttpd+0x42e6dc)
    #3 0x432a73 (/opt/lighttpd-asan/sbin/lighttpd+0x432a73)
    #4 0x428f7a (/opt/lighttpd-asan/sbin/lighttpd+0x428f7a)
    #5 0x429890 (/opt/lighttpd-asan/sbin/lighttpd+0x429890)
    #6 0x42a73b (/opt/lighttpd-asan/sbin/lighttpd+0x42a73b)
    #7 0x40873c (/opt/lighttpd-asan/sbin/lighttpd+0x40873c)
    #8 0x7f58078eeaf4 (/usr/lib64/libc-2.17.so+0x21af4)
    #9 0x406658 (/opt/lighttpd-asan/sbin/lighttpd+0x406658)
0x600e0000ded8 is located 8 bytes inside of 72-byte region [0x600e0000ded0,0x600e0000df18)
freed by thread T0 here:
    #0 0x7f5808109009 (/usr/lib64/libasan.so.0.0.0+0x16009)
    #1 0x4580ca (/opt/lighttpd-asan/sbin/lighttpd+0x4580ca)
    #2 0x42c892 (/opt/lighttpd-asan/sbin/lighttpd+0x42c892)
    #3 0x42e5f3 (/opt/lighttpd-asan/sbin/lighttpd+0x42e5f3)
    #4 0x432a73 (/opt/lighttpd-asan/sbin/lighttpd+0x432a73)
    #5 0x428f7a (/opt/lighttpd-asan/sbin/lighttpd+0x428f7a)
    #6 0x429890 (/opt/lighttpd-asan/sbin/lighttpd+0x429890)
    #7 0x42a73b (/opt/lighttpd-asan/sbin/lighttpd+0x42a73b)
    #8 0x40873c (/opt/lighttpd-asan/sbin/lighttpd+0x40873c)
    #9 0x7f58078eeaf4 (/usr/lib64/libc-2.17.so+0x21af4)
previously allocated by thread T0 here:
    #0 0x7f5808109225 (/usr/lib64/libasan.so.0.0.0+0x16225)
    #1 0x458235 (/opt/lighttpd-asan/sbin/lighttpd+0x458235)
    #2 0x42f514 (/opt/lighttpd-asan/sbin/lighttpd+0x42f514)
    #3 0x432a73 (/opt/lighttpd-asan/sbin/lighttpd+0x432a73)
    #4 0x428f7a (/opt/lighttpd-asan/sbin/lighttpd+0x428f7a)
    #5 0x429890 (/opt/lighttpd-asan/sbin/lighttpd+0x429890)
    #6 0x42a73b (/opt/lighttpd-asan/sbin/lighttpd+0x42a73b)
    #7 0x40873c (/opt/lighttpd-asan/sbin/lighttpd+0x40873c)
    #8 0x7f58078eeaf4 (/usr/lib64/libc-2.17.so+0x21af4)
Shadow bytes around the buggy address:
  0x0c023fff9b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c023fff9b90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c023fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c023fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 00 00
  0x0c023fff9bc0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
=>0x0c023fff9bd0: 00 00 00 00 00 fa fa fa fa fa fd[fd]fd fd fd fd
  0x0c023fff9be0: fd fd fd fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c023fff9bf0: 00 fa fa fa fa fa 00 00 00 00 00 00 00 00 00 fa
  0x0c023fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c023fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c023fff9c20: 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
  Heap righ redzone:     fb
  Freed Heap region:     fd
  Stack left redzone:    f1
  Stack mid redzone:     f2
  Stack right redzone:   f3
  Stack partial redzone: f4
  Stack after return:    f5
  Stack use after scope: f8
  Global redzone:        f9
  Global init order:     f6
  Poisoned by user:      f7
  ASan internal:         fe
==15343== ABORTING

Program received signal SIGSEGV, Segmentation fault.
0x000000000043a88b in buffer_caseless_compare (a=a@entry=0x6bdf60 ".", a_len=a_len@entry=1, b=0x0, b_len=1) at buffer.c:461
461            unsigned char ca = a[i], cb = b[i];
(gdb) bt 
#0  0x000000000043a88b in buffer_caseless_compare (a=a@entry=0x6bdf60 ".", a_len=a_len@entry=1, b=0x0, b_len=1) at buffer.c:461
#1  0x0000000000481aa3 in array_get_index (rndx=0x0, keylen=1, key=0x6bdf60 ".", a=0x6bcd20) at array.c:101
#2  array_replace (a=a@entry=0x6bcd20, du=du@entry=0x6be040) at array.c:174
#3  0x0000000000427c74 in yy_reduce (yypParser=yypParser@entry=0x6bd6d0, yyruleno=10) at ./configparser.y:187
#4  0x000000000042a2cb in configparser (yyp=yyp@entry=0x6bd6d0, yymajor=yymajor@entry=2, yyminor=yyminor@entry=0x6bde80, ctx=ctx@entry=0x7fffffffe130)
    at configparser.c:1528
#5  0x000000000041e2ae in config_parse (srv=srv@entry=0x6bc010, context=context@entry=0x7fffffffe130, t=t@entry=0x7fffffffe0a0) at configfile.c:955
#6  0x0000000000422b22 in config_parse_file (srv=srv@entry=0x6bc010, context=context@entry=0x7fffffffe130, 
    fn=fn@entry=0x7fffffffe831 "id:000000,sig:11,src:001000,op:arith8,pos:7,val:+27") at configfile.c:1021
#7  0x0000000000423cc8 in config_read (srv=srv@entry=0x6bc010, fn=0x7fffffffe831 "id:000000,sig:11,src:001000,op:arith8,pos:7,val:+27") at configfile.c:1162
#8  0x0000000000407413 in main (argc=3, argv=0x7fffffffe5d8) at server.c:600

Thanks
Aladdin Mubaied


Files

config (1) (12 Bytes) config (1) alaamub, 2016-02-16 17:58
Actions #1

Updated by gstrauss almost 9 years ago

Something which causes a program crash should, of course, be fixed.

However, why do you think this warrants a CVE?

By design, the lighttpd.conf allows execution of arbitrary commands, e.g. with piped-loggers, as well as by other means. If you control the configuration file, you control the execution. lighttpd will abort if it detects that it is setuid, since lighttpd is not intended to be started setuid by arbitrary users (who could then specify arbitrary configuration files).

Actions #2

Updated by gstrauss almost 9 years ago

buffer_caseless_compare() should probably check if (len == 1) (indicating that one of the strings is empty, e.g. ""), and then not bother to check if '\0' matches.
In the trace provided, the crash looks to occur when b=0x0, b_len=1 is dereferenced. (NULL pointer dereference)

Additionally, I also see something suspect inside the comparison loop. Subtracting two (unsigned char) items should always result in a value >= 0, when the intended result is an integer which might be less than zero, equal to zero, or greater than zero.

Actions #3

Updated by gstrauss almost 9 years ago

Created pull request https://github.com/lighttpd/lighttpd1.4/pull/23

Perhaps a new ticket, with lower priority, should be created to look into why buffer_caseless_compare() might be called with NULL argument (and size == 1), or might be called with buffers containing data which does not end in '\0'.

[Edit: aboves statement is incorrect. stbuehler noted in https://github.com/lighttpd/lighttpd1.4/pull/23 comments that buffer_caseless_compare() is called with string length, not including terminating '\0']

Actions #4

Updated by gstrauss almost 9 years ago

Testing with the config attached to this ticket still causes a crash at shutdown when freeing srv->config_context array. I might not have a chance to dig into configparser.y until the weekend.

Actions #5

Updated by stbuehler almost 9 years ago

  • Subject changed from heap-use-after-free in lighttpd to heap-use-after-free in lighttpd on broken config
  • Priority changed from High to Normal
  • Target version set to 1.4.x

This is certainly not a security issue.

Actions #6

Updated by stbuehler almost 9 years ago

  • Description updated (diff)
Actions #7

Updated by stbuehler almost 9 years ago

  • Target version changed from 1.4.x to 1.4.40
Actions #8

Updated by stbuehler almost 9 years ago

  • Status changed from New to Fixed
  • % Done changed from 0 to 100

Applied in changeset r3080.

Actions

Also available in: Atom