|
* ====================================================================
*
* FrontPage SUID-Stub-Programm
*
* Copyright (c) 1995-1998 Microsoft Corporation -- Alle Rechte vorbehalten.
*
* KEINE GEWÄHRLEISTUNG. Microsoft schließt jede Gewährleistung für diesen Code und
* diese Informationen aus. Dieser Code und diese Informationen sowie jede dazugehörige
* Dokumentation wird in der vorliegenden Form zur Verfügung ohne jegliche Gewährleistung,
* weder direkt oder indirekt, einschließlich, aber nicht beschränkt auf, implizierte
* Gerwährleistung oder Handelsüblichkeit, Eignung für einen bestimmten Zweck oder
* Nichtverletzung. Das gesamte Risiko hinsichtlich Einsatz und Leistung dieses Codes und
* dieser Informationen liegt beim Benutzer.
*
* KEINE HAFTUNG FÜR SCHÄDEN. Weder Microsoft noch seine Lieferanten sind
* für irgendwelche Schäden (einschließlich, aber nicht beschränkt auf, Schäden aus
* entgangenem Gewinn, Betriebsunterbrechung, Verlust von geschäftlichen Informationen
* oder andere finanzielle Einbußen) ersatzpflichtig, die sich aus der Verwendung oder
* der Nichteinsetzbarkeit dieses Microsoft-Produkts ergeben, selbst wenn Microsoft von der
* Möglichkeit eines solchen Schadens unterrichtet worden ist. Da einige Staaten/
* Rechtsordnungen den Ausschluss oder die Beschränkung der Gewährleistung für
* Folgeschäden oder jeden anderen Schaden nicht zulassen, kann die obige Einschränkung für
* Sie nicht gelten.
*
* Version 4.0.4.3
*/
/*
* Benutzerkonfigurierbare Elemente. Die Servererweiterungen werden bei einer
* UID/GID kleiner als LOWEST_VALID_UID/LOWEST_VALID_GID nicht ausgeführt.
*/
#if defined(RS6000)
#define _ALL_SOURCE
#endif
#if defined(RS6000) | defined(UWARE7)
int initgroups (char *, int);
#endif
#if defined(LINUX)
#define LOWEST_VALID_UID 15
#else
#define LOWEST_VALID_UID 11
#endif
#if defined(HPUX) || defined(IRIX) || defined(SUNOS4)
#define LOWEST_VALID_GID 20
#else
#if defined(SCO)
#define LOWEST_VALID_GID 24
#else
#define LOWEST_VALID_GID 21 /* Solaris, AIX, Alpha, Bsdi, usw. */
#endif
#endif
#if defined(UWARE7)
#define Vstat stat32
#define Vlstat lstat32
int lstat32 (const char *, struct stat *);
int stat32 (const char *, struct stat *);
#else
#define Vstat stat
#define Vlstat lstat
#endif
#define CLEAN_PATH "PATH=/usr/bin:/bin"
static struct SaveEnvVars
{
const char* szVar;
int iLen;
} gSafeEnvVars[] =
{
{ "AUTH_TYPE=", 0 },
{ "CONTENT_LENGTH=", 0 },
{ "CONTENT_TYPE=", 0 },
{ "DATE_GMT=", 0 },
{ "DATE_LOCAL=", 0 },
{ "DOCUMENT_NAME=", 0 },
{ "DOCUMENT_PATH_INFO=", 0 },
{ "DOCUMENT_ROOT=", 0 },
{ "DOCUMENT_URI=", 0 },
{ "FILEPATH_INFO=", 0 },
{ "GATEWAY_INTERFACE=", 0 },
{ "HTTP_", 0 },
{ "LAST_MODIFIED=", 0 },
{ "PATH_INFO=", 0 },
{ "PATH_TRANSLATED=", 0 },
{ "QUERY_STRING=", 0 },
{ "QUERY_STRING_UNESCAPED=", 0 },
{ "REDIRECT_QUERY_STRING=", 0 },
{ "REDIRECT_STATUS=", 0 },
{ "REDIRECT_URL=", 0 },
{ "REMOTE_ADDR=", 0 },
{ "REMOTE_HOST=", 0 },
{ "REMOTE_IDENT=", 0 },
{ "REMOTE_PORT=", 0 },
{ "REMOTE_USER=", 0 },
{ "REQUEST_METHOD=", 0 },
{ "SCRIPT_FILENAME=", 0 },
{ "SCRIPT_NAME=", 0 },
{ "SCRIPT_URI=", 0 },
{ "SCRIPT_URL=", 0 },
{ "SERVER_ADMIN=", 0 },
{ "SERVER_NAME=", 0 },
{ "SERVER_PORT=", 0 },
{ "SERVER_PROTOCOL=", 0 },
{ "SERVER_SOFTWARE=", 0 },
{ "TZ=", 0 },
{ "USER_NAME=", 0 },
{ 0, 0 }
};
/*
* Ende benutzerkonfigurierbare Elemente
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
#if !defined(bsdi) && !defined(hpux) && !defined(sun) && !defined(linux) && !defined(SCO5) && !defined(UWARE7)
#include <sys/mode.h>
#endif
#if defined(sun) || defined(bsdi) || defined(sgi) || defined(SCO5) || defined(UWARE7)
extern const char ** environ;
#endif
extern int errno;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#if (MAXPATHLEN < 1024)
#undef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#define KEYLEN 128 /* Muss Mehrfaches von sizeof(int) sein */
#define FPKEYDIR "/usr/local/frontpage/version4.0/apache-fp"
#define KEYFILE "/usr/local/frontpage/version4.0/apache-fp/suidkey.%d"
#define FPDIR "/usr/local/frontpage/version4.0/exes"
/* Zulässige Module */
#define SHTML "/_vti_bin/shtml.exe"
#define FPCOUNT "/_vti_bin/fpcount.exe"
#define AUTHOR "/_vti_bin/_vti_aut/author.exe"
#define ADMIN "/_vti_bin/_vti_adm/admin.exe"
/*
* Irgendwas ist nicht in Ordnung - Beenden
*/
void die(const char *msg)
{
char timebuf[26];
time_t t = time(0);
strcpy(timebuf, ctime(&t));
timebuf[24] = '\0';
fprintf(stderr, "[%s] %s\n", timebuf, msg);
printf("Inhaltstyp: text/html\n\n<HTML>*-*-* :-| :^| :-/ :-( 8-( *-*-*\n<ul>\n<li>Status=1\n<li>BS-Status=0\n<li>msg=FrontPage-Sicherheitsverletzung.\n<li>osmsg=\n</ul>\n");
exit(0);
}
/*
* Entfernen aller Variablen, bei denen es sich bekannterweise nicht um ein Standard-CGI-
* Betriebssystem-Umgebungsvariable handelt. Ferner: Reparieren von PATH.
*/
static void CleanEnvironment()
{
const char** pp;
const char** ppi;
struct SaveEnvVars* pOkEnv;
for (ppi = pp = environ; *pp; pp++)
{
/*
* Ineffiziente lineare Suche; kann mit Binärsuche verbessert werden.
*/
for (pOkEnv = gSafeEnvVars; pOkEnv->szVar; pOkEnv++)
{
int iLen = pOkEnv->iLen;
if (!iLen)
pOkEnv->iLen = iLen = strlen(pOkEnv->szVar);
if (strncmp(pOkEnv->szVar, *pp, iLen) == 0)
break;
}
if (!strncmp(*pp, "PATH=", 5))
*ppi++ = CLEAN_PATH;
else if (pOkEnv->szVar)
*ppi++ = *pp;
}
*ppi = 0;
}
int main(int argc, char **argv)
{
struct passwd* pw = 0;
const char* szFpUserName;
const char* szFpExe = getenv("FPEXE");
const char* szFpUid = getenv("FPUID");
const char* szFpGid = getenv("FPGID");
const char* szFpFd = getenv("FPFD");
char* pEnd;
char* pDir;
uid_t iFpUid;
uid_t iFpGid;
uid_t iBinUid;
int iFpFd;
int iKeyFd;
int iCount;
char szKeyFile[MAXPATHLEN];
char szWork[MAXPATHLEN];
char inpKey[KEYLEN];
char refKey[KEYLEN];
struct stat fs;
/*
* Gewährleisten, dass die SUID dieses Programms tatsächlich auf root festgelegt wurde
*/
if (geteuid())
/*
* Benutzerwiederherstellung: Sicherstellen, dass SUID von fpexe auf root festgelegt ist
*/
die("FrontPage SUID-Fehler: keine Ausführung als root");
/*
* Gewährleisten, dass es sich bei dem Benutzer, unter dem der Webserver ausgeführt wird,
* um einen zulässigen Benutzer handelt
*/
if (!getpwuid(getuid()))
/*
* Benutzerwiederherstellung: Sicherstellen, dass sich der Webserverbenutzer in
* /etc/passwd befindet
*/
die("FrontPage SUID-Fehler: unzulässige UID");
/*
* Gewährleisten, dass die richtigen Argumente verwendet werden (Übergabe in Umgebung)
*/
if (!szFpExe || !szFpUid || !szFpGid || !szFpFd)
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten
* Apache-Server ausgeführt wird
*/
die("FrontPage SUID-Fehler: unzulässige Umgebungsargumente");
/*
* Überprüfen der Argumente
*/
if (strcmp(szFpExe, SHTML) != 0 &&
strcmp(szFpExe, FPCOUNT) != 0 &&
strcmp(szFpExe, AUTHOR) != 0 &&
strcmp(szFpExe, ADMIN) != 0)
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe nur aufgerufen wurde, um
* Programme der FrontPage-Servererweiterungen auszuführen.
*/
die("FrontPage SUID-Fehler: Zielprogrammverletzung");
if (strlen(szFpExe) + strlen(FPDIR) + 1 > MAXPATHLEN)
die("FrontPage SUID-Fehler: Pfad zu lang");
strcpy(szWork, FPDIR);
strcat(szWork, szFpExe);
iFpUid = strtol(szFpUid, &pEnd, 10);
if (!pEnd || *pEnd)
iFpUid = 0;
if (iFpUid < LOWEST_VALID_UID || !(pw = getpwuid(iFpUid)))
/*
* Benutzerwiederherstellung: Sicherstellen, dass die FrontPage-Benutzer-IDs den
* obigen Mindestanforderungen genügen
*/
die("FrontPage SUID-Fehler: unzulässige Ziel-UID");
szFpUserName = strdup(pw->pw_name);
iFpGid = strtol(szFpGid, &pEnd, 10);
if (!pEnd || *pEnd)
iFpGid = 0;
if (iFpGid < LOWEST_VALID_GID || !getgrgid(iFpGid))
/*
* Benutzerwiederherstellung: Sicherstellen, dass die FrontPage-Gruppen-IDs den
* obigen Mindestanforderungen genügen
*/
die("FrontPage SUID-Fehler: unzulässige Ziel-GID");
iFpFd = strtol(szFpFd, &pEnd, 10);
if (!pEnd || *pEnd)
iFpFd = -1;
if (iFpFd < 0)
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten Apache-
* Server ausgeführt wird
*/
die("FrontPage SUID-Fehler: unzulässiger Schlüsseldateideskriptor");
/*
* Schlüssel vom Server lesen. Solange noch als root angemeldet und Zugriff
* möglich, Lesen des Schlüssels aus der Masterschlüsseldatei.
* Übereinstimmung des Schlüssels prüfen.
*/
if (Vlstat(FPKEYDIR, &fs) == -1 ||
(fs.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) || fs.st_uid ||
!(S_ISDIR(fs.st_mode)))
/*
* Benutzerwiederherstellung: Besitzer des Verzeichnisses als root mit
* den Berechtigungen rwx--x--x festlegen.
*/
die("FrontPage SUID-Fehler: Schlüsseldateiverzeichnis unsicher");
#if defined(sun) && !defined(__SVR4)
sprintf(szKeyFile, KEYFILE, (int)getpgrp(0));
#else
sprintf(szKeyFile, KEYFILE, (int)getpgrp());
#endif
if (Vstat(szKeyFile, &fs) == -1 ||
(fs.st_mode & (S_IRWXG | S_IRWXO)) || fs.st_uid)
/*
* Benutzerwiederherstellung: Sicherstellen, dass die Schlüsseldatei ordnungsgemäß
* geschützt ist (Besitzer = root, Berechtigungen = r**------). Neustarten des gepatchten
* Apache-Servers.
*/
die("FrontPage SUID-Fehler: Sicherheitsverletzung der Schlüsseldatei");
iKeyFd = open(szKeyFile, O_RDONLY);
if (iKeyFd < 0)
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten
* Apache-Server ausgeführt wird. Neustarten des gepatchten Apache-Servers.
*/
die("FrontPage SUID-Fehler: Schlüsseldatei konnte nicht geöffnet werden" );
iCount = read(iKeyFd, refKey, sizeof(refKey));
close(iKeyFd);
if (iCount != sizeof(refKey))
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten
* Apache-Server ausgeführt wird. Neustarten des gepatchten Apache-Servers.
*/
die("FrontPage SUID-Fehler: aus Schlüsseldatei konnte kein gültiger Schlüssel gelesen werden");
iCount = read(iFpFd, inpKey, sizeof(inpKey));
close(iFpFd);
if (iCount != sizeof(inpKey))
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten
* Apache-Server ausgeführt wird
*/
die("FrontPage SUID-Fehler: Lesen eines zulässigen Eingabeschlüssels nicht möglich");
if (memcmp(inpKey, refKey, sizeof(refKey)) != 0)
/*
* Benutzerwiederherstellung: Sicherstellen, dass fpexe auf einem gepatchten
* Apache-Server ausgeführt wird
*/
die("FrontPage SUID-Fehler: Schlüsselsicherheitsverletzung");
/*
* Ändern von Benutzer- und Gruppen-IDs in angegebenen Benutzer
*/
if (setgid(iFpGid) == -1 || initgroups(szFpUserName, iFpGid) == -1)
/*
* Benutzerwiederherstellung: Sicherstellen, dass der Benutzer in
* /etc/passwd und /etc/group ordnungsgemäß registriert ist.
*/
die("FrontPage SUID-Fehler: setgid() fehlgeschlagen");
if (setuid(iFpUid) == -1)
/*
* Benutzerwiederherstellung: Sicherstellen, dass der Benutzer in
* /etc/passwd ordnungsgemäß registriert ist.
*/
die("FrontPage SUID-Fehler: setuid() fehlgeschlagen");
/*
* Überprüfen des Zielverzeichnisses.
*/
iBinUid = 0;
if (pw = getpwnam("bin"))
iBinUid = pw->pw_uid;
pDir = strrchr(szWork, '/');
*pDir = 0;
if (Vlstat(szWork, &fs) == -1 || (fs.st_mode & (S_IWGRP | S_IWOTH)) ||
(fs.st_uid != iBinUid && fs.st_uid != 0) ||
!(S_ISDIR(fs.st_mode)))
/*
* Benutzerwiederherstellung: Sicherstellen, dass die ausführbaren FrontPage
* Programme verfügbar sind, der Besitzer des Verzeichnisses auf bin oder root und
* die Berechtigungen auf rwx*-x*-x festgelegt sind.
*/
die("FrontPage SUID-Fehler: Zielverzeichnis nicht gefunden oder unsicher");
*pDir = '/';
/*
* Überprüfen des Zielprogramms
*/
if (Vstat(szWork, &fs) == -1 || ((fs.st_mode & (S_IWGRP | S_IWOTH)) ||
(fs.st_mode & (S_ISUID | S_ISGID)) ||
(fs.st_uid != iBinUid && fs.st_uid != 0)))
/*
* Benutzerwiederherstellung: Sicherstellen, dass die ausführbaren FrontPage
* Programme verfügbar sind, der Besitzer des Verzeichnisses auf bin oder root und
* die Berechtigungen auf rwx*-x*-x festgelegt sind.
*/
die("FrontPage SUID-Fehler: Zielprogramm nicht gefunden oder unsicher");
*pDir = '/';
/*
* Sicherstellen, dass die Umgebung keine unsicheren Werte enthält.
*/
CleanEnvironment();
/*
* Das angegebene Programm ausführen.
*/
argv[0] = szWork;
umask(022);
execv(argv[0], argv);
/*
* Sollte niemals vorkommen. Beenden mit Fehler.
*/
return (1);
}
|