Project

General

Profile

Bug #1116

lighttpd 1.4.13 reproducible (every time) segfault when file cannot be stat-ed (with simple test-case)

Added by scroffer52 almost 13 years ago. Updated over 11 years ago.

Status:
Missing Feedback
Priority:
Urgent
Assignee:
-
Category:
core
Target version:
Start date:
Due date:
% Done:

0%

Estimated time:
Missing in 1.5.x:

Description

'_*Short version*_

If you have files which can't be accessed by lighttpd 1.4.13's normal user (i.e. are run via suexec), then lighttpd can easily be tricked into trying to open() them, causing a segfault every time. Do this by post-fixing a slash.

'_*Long version*_

I have a lighttpd 1.4.13 + FastCGI with SuExec, running on some files which can't be read by the normal lighttpd user.

This all works fine... unless you try to access specially crafted URLs - which cause lighty to crash every time.

Here's my (slightly obscured) set-up:


server.name = "1.2.3.4" 

server.document-root = "/var/www/html/" 

server.indexfiles = ( "index.html", "index.htm", "index.php" )

fastcgi.server = ( ".php" =>
   ( "localhost" =>
      ( "socket" => "/tmp/webadmin.socket",
        "bin-path" => "/etc/lighttpd/suexec.sh",
        "idle-timeout" => 30,
        "check-local" => "disable",
        "min-procs" => 1,
        "max-procs" => 1,
     ) ) )

I have a file /var/www/html/x.php. Its contents can be anything. For a test case, I used:


<?

phpinfo();

?>

My suexec script is not relevant to the crash, but is completely simple (just execs a shell script that calls php-cgi).

The test file x.php is only accessible by the SuExec user:


[root@ ~]# ls -l /var/www/html/x.php
-rwxr-x---  1 suexecuser suexecgroup 19 Apr 12 22:06 /var/www/html/x.php

If I access it as http://1.2.3.4/x.php then all is fine - I get what I'd expect. No problems.

However, if I try http://1.2.3.4/x.php/y (i.e. appending a pseudo-directory), then - boom! segfault! This happens every single time. Not good on a live server... :-(

Here are the last few lines of the strace:


poll([{fd=4, events=POLLIN}, {fd=5, events=POLLIN}, {fd=25, events=POLLIN, revents=POLLIN}], 3, 1000) = 1
read(25, "\27\3\1\2\0\7\273)\315YK:\36j#\345\30\321\316\2623!\357"..., 18437) = 517
read(25, 0x8780820, 18437)              = -1 EAGAIN (Resource temporarily unavailable)
stat64("/var/www/html/x.php/y", 0xbffcaa70) = -1 ENOTDIR (Not a directory)
stat64("/var/www/html/x.php/y", 0xbffcab30) = -1 ENOTDIR (Not a directory)
stat64("/var/www/html/x.php", {st_mode=S_IFREG|0750, st_size=19, ...}) = 0
stat64("/var/www/html/x.php", {st_mode=S_IFREG|0750, st_size=19, ...}) = 0
open("/var/www/html/x.php", O_RDONLY|O_LARGEFILE) = -1 EACCES (Permission denied)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
#1

Updated by darix almost 13 years ago

can you try to reproduce it with http://zen.sh.nu/~darix/lighttpd-1.4.x.r1745.tar.gz.
i cant reproduce it here.

do you have follow-symlinks enabled or disabled?
in my setup i had php running via external spawning.

#2

Updated by scroffer52 almost 13 years ago

The problem exists too in r1745, compiled with identical options.

But... I've now traced this by simplifying my configuration:

The offending lines in my configuration are:


compress.cache-dir         = "/var/cache/lighttpd/compress/" 
compress.filetype          = ("text/plain", "text/html")
compress.max-filesize      = 1024000

That compression directory isn't writable by the su-execed user; but I don't think that should matter (as mod_compress doesn't touch PHP output anyway, and as mod_compress is running as the correct user). In any case, changing it to a 777-ed directory doesn't fix the segfault.

Without those lines, no segfault. With those lines, a segfault happens.

#3

Updated by scroffer52 almost 13 years ago

Sorry - forgot to mention that I'm not using follow-symlinks anywhere, so it must be the default (on?).

#4

Updated by scroffer52 almost 13 years ago

Here's what I got from valgrind:


==3501== Invalid read of size 4
==3501==    at 0x44F69DE: (within /usr/lib/lighttpd/mod_compress.so)
==3501==    by 0x805F4D4: plugins_call_handle_subrequest_start (in /usr/sbin/lighttpd)
==3501==    by 0x804FDCA: http_response_prepare (in /usr/sbin/lighttpd)
==3501==    by 0x8052CB4: connection_state_machine (in /usr/sbin/lighttpd)
==3501==    by 0x8053C9B: network_server_handle_fdevent (in /usr/sbin/lighttpd)
==3501==    by 0x804E4CE: main (in /usr/sbin/lighttpd)
==3501==  Address 0x38 is not stack'd, malloc'd or (recently) free'd
==3501==
==3501== Process terminating with default action of signal 11 (SIGSEGV)
==3501==  Access not within mapped region at address 0x38
==3501==    at 0x44F69DE: (within /usr/lib/lighttpd/mod_compress.so)
==3501==    by 0x805F4D4: plugins_call_handle_subrequest_start (in /usr/sbin/lighttpd)
==3501==    by 0x804FDCA: http_response_prepare (in /usr/sbin/lighttpd)
==3501==    by 0x8052CB4: connection_state_machine (in /usr/sbin/lighttpd)
==3501==    by 0x8053C9B: network_server_handle_fdevent (in /usr/sbin/lighttpd)
==3501==    by 0x804E4CE: main (in /usr/sbin/lighttpd)
--3501-- discard syms at 0x451C000-0x4527000 in /lib/libnss_files-2.3.4.so due to munmap()

#5

Updated by jan almost 13 years ago

  • Status changed from New to Assigned
#6

Updated by scroffer52 over 12 years ago

Do the lighttpd developers count this as a low-priority bug?

I was expecting a consistently remotely exploitable crash to be the kind of thing that was a level 1 priority!

#7

Updated by stbuehler almost 12 years ago

I couldn't reproduce it either; if open (in stat_cache_get_entry) fails with EACCES, lighty returns 403 Forbidden and does not start mod_compress.

If you still have trouble with this in the current version, please provide a backtracke of a debug build (so we have the line number in which the segfault happens).

#8

Updated by stbuehler over 11 years ago

  • Status changed from Assigned to Fixed
  • Resolution set to worksforme

Missing feedback.

#9

Updated by stbuehler over 11 years ago

  • Status changed from Fixed to Missing Feedback

Also available in: Atom