ХакерДом : team/advisories/ApacheFDLeakage

Краткое описание проблемы
Как развивались события:
21 сентября мы сообщили об этом разработчикам: http://bugs.php.net/38915
(сообщение я писал поздно ночью, поэтому за ошибки в тексте просьба сильно не пинать ;)
Никакой реакции от PHP Team в течении почти месяца не было.
Потом мы решили отослать информацию на securityfocus.com, что и было сделано 19 октября
(http://www.securityfocus.com/archive/1/449234/30/0/threaded)

Ответ разработчиков PHP:
Sorry, but your problem does not imply a bug in PHP itself.
...
Thank you for your interest in PHP.

The opened file descriptors are opened by Apache.
It is the job of Apache to protect them, not something that should be
reinvented in all apache modules.

Not a bug in PHP.


Bernhard Mueller из SEC Consult написал:
Hello,

This is not a new problem (see http://www.securityfocus.com/bid/9302).
However, we also “discovered” this a few weeks ago and contacted Apache
and PHP about it. According to Stefan Esser (PHP) its due to Apache's
failure to open file descriptors with the close on exec flag. However,
according to Joe Orton (Apache) won't change this flag because it would
make no difference to Apache's security model («anything you can do in a
sh script spawned by a PHP script you can do directly in the PHP script
anyway»). The bottom line is that this will also work in future, because
neither the Apache team nor the PHP team will “fix” the issue.
Personally, I'd think that a combination of both measures (close on exec
flag and explicitly closing specific file descriptors by PHP) would make
the most sense.
BTW, with this flaw an attacker can also conveniently change / overwrite
Apache's log files and therefore hide his attack after owning a
PHP-based web application. Here's a quick POC as I haven't seen one
anywhere yet :)

...

Bernhard


Что радует, есть люди, которые не согласны с PHP Group по поводу бага.
20 октября мне пришло письмо от Jeff Lawson из United Devices:
I disagree with PHP's response to your bug
http://bugs.php.net/bug.php?id=38915. Unfortunately, I cannot reopen
your bug since their bug system only allows the bug submitter to reopen
it. If you can do that, then I will be able to add my response to the
bug in support of you. Thanks


(after forking but before the exec).

Keep in mind that PHP is running as a module within the same process
space as Apache, and those private FDs are required for it to operate.
Apache cannot reasonably close and re-open all of those whenever it is
invoking a module's handlers, nor can it reasonably run modules in a
separate process. Modules are intended to be trusted code and so Apache
does not attempt to protect itself from misdesigned modules.

(In the case where PHP is installed as a CGI and not a module, then
Apache does indeed close the private FDs prior to running PHP.)

For example, when a CGI process via Apache's “mod_cgi”, that module is
responsible for ensuring that it explicitly closes all open files prior
to the exec(). PHP is in a similar situation and should also do the
same when executing sub-processes.


22 октября я изменил статус бага на “Open”.
Посмотрим, что будет.

30 октября. Jeff Lawson написал свой мнение на bugs.php.net.

14 ноября. Никакой неакции от PHP Group.

Дополнительные материалы

Все статьи Steve Grubb в одном месте

Похожая проблема в My SQL


http://bugs.mysql.com/bug.php?id=3779

Утечка дескрипторов в mod_cgi

Первое упоминание о проблеме (Steve Grubb), 16 jul 2001

Apache HTTPD Bugs Mailing List – “Filehandles of logs not closed before exec of cgi scripts” (fixed) 19 feb 2003
Apache 2.x leaked descriptors (Steve Grubb) 21 feb 2003
Подробный bug report с рассмотрением исходного кода, 21–23 feb 2003
Discussion on fd leak problematic, 14 mar 2003
Вот здесь довольно хорошо написано

[PATCH] Have logfiles closed on exec
Re: [PATCH] Have logfiles closed on exec
http://sources.zabbadoz.net/patches/apache/

PHP related


Сообщение на bugs.php.net про утечку дескрипторов (Steve Grubb) 7 nov 2002
suPHP (a tool for executing PHP scripts with the permissions of their owners)

Other


ILLC – Inverse Lookup Log Corruption

Some important things

* Apache by itself does not leak fd's, because its ap_cleanup_for_exec() API
has made sure (for ages already) that nothing is passed to exec'ed processes.

* “certain 3rd party modules” do not use the API correctly (either because
they don't know better, or because they wanted top use existing unsafe
functions like system() and popen()) and do not invoke ap_cleanup_for_exec(),
thus leaking fd's.
The leaked fd's include the server's listener sockets, the accept()ed
request sockets, the access_log file, several lock files.

* By using FD_CLOEXEC with the new ap_note_cleanups_for_*_ex() functions,
we can proactively plug these leakages, even though it would be better if
the 3rd party module authors would “do it right” in _their_ code.

The apache source code already has hooks for closing these resources. The reason it is not happening is because there is a bug. A trivial patch has been posted and is being discussed with the apache group.
Christian Kratzer (CK Software), 25 feb 2003

Has anyone played with various modules looking to see if anything beyond access or
error logs are available? For example, if you look at mod_php, they leak the file
descriptor from accept() and the descriptor to the php page being executed in addition
to all the other descriptors.
Steve Grubb, 25 feb 2003


I think you can be more inventive on what a malicious script author can if they can run
arbitrary code from a CGI script, under the Apache model: here are some things I can up with:
– using ptrace() on an httpd child: now you can get the httpd child to run arbitrary code,
so “fd leaks” from child to CGI script are really irrelevant. (This is an old trick: nCipher used
this as a demo of how to extract in-server SSL private keys using a CGI script)
– send signals to the server children: SIGSTOP will make a quick'n'easy Do S.
I'm sure there are more. The bottom line is that you must trust CGI script authors with the
priviledges of the user which httpd runs as.
Joe Orton (redhat.com), 13 mar 2003


My point is that merely fixing these fd leaks does not improve security if you don't trusted
your CGI script authors, since a malicious CGI script can use ptrace() to run arbitrary code in
an httpd process, thereby gaining access to all the log file fds and more.
If you allow PHP scripts to exec/system/etc arbitrary binaries on your system, then the same
applies. PHP safe mode mitigates this somewhat, as I've said above.
Joe Orton (redhat.com), 13 mar 2003

Steve Grubb про утечку FD в модулях:
I would think apache should have a safe and defined interface between itself and modules. I cannot
possibly think of any file descriptor besides 0, 1, &2 that a module would need.

Другие модули


Я протестировал:
– mod_perl (2.0.1) + Perl (5.8.7) – утечка дескрипторов
– mod_python (3.2.10) + Python (2.3.4) – утечка дескрипторов
– mod_tcl (1.0.1) + TCL (8.4.14) – утечка дескрипторов
– mod_ruby (1.2.6) + Ruby (1.8.5) – утечки дескрипторов НЕТ! Перед выполнением внешней программы Ruby закрывает все дескрипторы с номерами, большими 2:

io.c: static VALUE pipe_open(pstr, pname, mode): 3126:
for (fd = 3; fd < NOFILE; fd++) close(fd);
...
rb_proc_exec(pname);

Позиция The Apache Software Foundation


Решил уточнить позицию Apache по данному вопросу:

From: dimmoborgir
To: secutity [at] apache.org

Hello!

There is an old problem with FD leak through mod_php:
bugs.php.net/20302
bugs.php.net/38915

PHP Team don't want to fix the problem («It is the job of Apache to protect them»).

I tested some other modules, they also have this problem:
Perl (5.8.7) + mod_perl (2.0.1)
Python (2.3.4) + mod_python (3.2.10)
TCL (8.4.14) + mod_tcl (1.0.1)

These leaked FD's can be used to write fake messages into Apache's logfiles, to clear logs,
to accept connections on privileged(!) HTTP(S) port. They can be used only in a prorgam,
spawned by PHP script (via exec() or system() functions), they can't be used in a PHP script,
because PHP itself don't have functions to access FD's by number.

So, why not just set FD_CLOEXEC flag on file descriptors to prevent their leakage to
external program? It will increase the security of Apache Web Server (when it works
with mod_php, for example).

Best regards, Dmitry.



From: Joe Orton
To: dimmoborgir

Hi Dmitry,

When scripts are interpreted using dynamically loaded loaded script
interpreters (mod_php, mod_python, PHP via Apache SAPI, etc), the
interpreter executes with the privileges of the httpd child process.

If the intepreter does not “sandbox” scripts from the environment in
which they run (as you might expect from a system like Java, for
example), the privileges of the httpd children are in effect inherited
directly by the scripts themselves.

Your report makes the implicit assumption that some other security model
exists; that PHP/Perl/... scripts can be run using the in-process
interpreter with some lesser set of privileges than those with which the
httpd child executes. That assumption is false; the “vulnerability”
described is a necessary consequence of the configuration used.

The specific case of “leaking” file descriptors to process spawned by
interpreted scripts is particularly moot. On any modern Unix system, a
process can access all its parents fds via e.g. the /proc/ filesystem,
and indeed obtain complete control over its parent via ptrace(). This
is true regardless of what fds are left open when the child process is
exec()ed, and whether or not FD_CLOEXEC is used. So no, using
FD_CLOEXEC does not improve security.

If a different configuration is used, a different security model can
be obtained: for example, by using the PHP interpreter as a CGI
program along with the “suexec” interfaces in Apache, PHP scripts can
be executed out-of-process under a different uid, and hence a
different set of privileges. Fast CGI is another popular alternative.

Regards, Joe Orton