VirtualHosts mit Apache

Ein klassisches Anwendungs-Szenario für AppArmor ist ein Shared-Hosting-Webserver, der von einem Anbieter betrieben wird und auf dem mehrere Kunden ihre Webpräsenz pflegen. Sobald der Anbieter den Kunden die Unterstützung von serverbasierten Skriptsprachen wie PHP, Perl oder Python anbietet, besteht die Gefahr, dass Fehler in den Skripten eines Kunden sich auf den gesamten Webserver auswirken. Da aber kaum noch ein Kunde mit statischen Webseiten arbeitet, sondern fast alle Webpräsenzen dynamisch mit Skripten datenbankgestützt erzeugt werden, ist dies die Regel. Stellen Sie sich den folgenden Fall vor: Ein Apache-Webserver wurde so konfiguriert, dass er zwei virtuelle Hosts anbietet. Einer enthält ein Content-Management-System (CMS). Dieses besitzt einige Konfigurationsdateien, in denen auch Benutzernamen und Kennwörter gespeichert wurden. Bisher sind keine Sicherheitslücken in dem CMS bekannt. Der zweite virtuelle Host verfügt über einige selbstgeschriebene und vorgefertigte PHP-Skripte. Mindestens ein Skript weist eine Sicherheitslücke auf, mit der es möglich ist, den Inhalt von Dateien anzuzeigen und auszuführen. Ein anderes Skript erlaubt es Bilder auf den Webserver zu laden. Eine Prüfung der Dateien erfolgt nicht. Auch ein Upload von Skripten und ausführbaren Programmen ist möglich. Mit Hilfe dieser Skripte kann ein Angreifer nun auf alle Dateien lesend und ausführend zugreifen, die auch der Apache Webserver erreichen kann. Wurde der Apache Webserver nicht in einem Chroot-Verzeichnis installiert und gestartet, handelt es sich um fast sämtliche Dateien des darunterliegenden Linux Betriebssystems. Dazu gehören dann natürlich auch die Dateien des anderen virtuellen Hosts inklusive der Dateien mit Benutzernamen und Kennwörtern. Bei einem Webshop gehören potentiell auch Dateien mit Bankverbindungen und Kreditkarteninformationen hierzu. Wurden diese Informationen in einer Datenbank gespeichert, kann der Angreifer ein eigenes PHP-Skript hochladen, welches die Datenbank ausliest und das Skript über den Browser starten (siehe 13.1).
Abbildung: Bei virtuellen Hosts kann eine Sicherheitslücke alle weiteren virtuellen Hosts kompromittieren.
\includegraphics{screenshots/apacheangriff}
Der Kunde des sicheren CMS wird über einen derartigen Angriff nicht erfreut sein und der Provider wird die Nachlässigkeiten des zweiten Kunden verantworten müssen.

Der Apache Webserver bietet keine Möglichkeit virtuelle Hosts voreinander zu schützen. Sämtliche Skripte werden bei dem Einsatz von mod_php oder mod_perl von einem einzigen immer gleichen Benutzer ausgeführt. UNIX-Dateirechte können hier also keinen Schutz erreichen. Werden die Skripte als CGI-Skripte ausgeführt, kann der Apache mit dem suEXEC-Mechanismus hier unterschiedliche Benutzer verwenden. So können die Skripte der verschiedenen virtuellen Hosts mit unterschiedlichen Benutzern gestartet werden. Das erlaubt eine Einschränkung der Zugriffe mit UNIX-Dateirechten. Eine andere Alternative ist der Einsatz des experimentellen Multi-Processing-Modules perchild. Dieses Apache-2-MPM erlaubt die Bindung eines virtuellen Hosts an einen Apache-Prozess (Worker). Die verschiedenen Worker können dann mit unterschiedlichen Benutzern gestartet werden. Dies würde dann auch die Einschränkung der Zugriffe bei Einsatz von mod_php und mod_perl erlauben.

Am einfachsten und wirkungsvollsten ist jedoch der Einsatz eines MAC-System wie AppArmor oder SELinux, welches für diesen Fall eine Unterstützung bietet. Ein derartiges MAC-System schützt auch in einem weiteren Fall: Vielleicht erfolgt der Angriff gar nicht von außen, sondern ein Kunde des Shared-Hosting-Providers versucht auf die Daten der anderen Kunden zuzugreifen und diese auszulesen. Bis zu einem gewissen Grad kann mit Dateirechten sichergestellt werden, dass auf der Kommandozeile kein Zugriff auf die Dateien der anderen Kunden möglich ist. Der Webserver muss jedoch auf alle Daten sämtlicher Kunden zugreifen können. Also installiert der Angreifer in seinem Webspace lediglich ein PHP- oder auch Perl-Skript, welches die Dateien der anderen Kunden ausliest und anzeigt.

Hier soll der Einsatz von AppArmor beschrieben werden. Die Anwendung von SELinux erfolgt in dem entsprechenden Kapitel.

Um AppArmor für unterschiedliche virtuelle Hosts nutzen zu können, müssen diese zunächst konfiguriert werden. Eine typische Konfiguration für zwei virtuelle Hosts könnte folgendermaßen aussehen:

# Bei SUSE ist dies die Datei /etc/apache2/vhosts.d/vhost.conf

NameVirtualHost *:80

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /srv/www/evil
    ServerName evil-hacker.com
    ServerAlias www.evil-hacker.com
    ErrorLog /var/log/apache2/evil
    CustomLog /var/log/apache2/evil-access common
    <Directory /srv/www/evil>
       Order allow,deny
       allow from all
    </Directory>
</VirtualHost>

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /srv/www/bookshop
    ServerName bookshop.opensource-training.de
    ErrorLog /var/log/apache2/bookshop
    CustomLog /var/log/apache2/bookshop-access common
    <Directory /srv/www/bookshop>
       Order allow,deny
       allow from all
    </Directory>
</VirtualHost>

Nun sollte zunächst für jeden virtuellen Host ein Default-Hat definiert werden. Der Apache Webserver wechselt dann bei Anfragen für einen virtuellen Host in das entsprechende Subprofil. Hierzu fügen Sie zu jedem virtuellen Host in der Konfiguration nur die folgende Zeile hinzu:

   AADefaultHatName evil
beziehungsweise
   AADefaultHatName bookshop
Nun rufen Sie den Profilassistenten genprof auf. Dies kann über Yast oder auf der Kommandozeile erfolgen:
genprof /usr/sbin/httpd2-prefork
Anschließend greifen Sie mit einem Browser auf beide Websites zu und versuchen sämtliche erlaubten Funktionen wahrzunehmen. Sobald Sie zufrieden sind, werten Sie die Zugriffe mit Genprof aus, indem Sie Scan auswählen. Genprof fragt zunächst, ob der neue Hat ^evil hinzugefügt werden soll. Anschließend werden für die Zugriffe innerhalb des Hats Regeln hinzugefügt. Ein typischer Hat könnte so aussehen:
  ^evil {
    /srv/www/evil/** r,
    /usr/share/apache2/error/** r,
    /var/log/apache2/evil w,
    /var/log/apache2/evil-access w,
  }
Dieser Hat erlaubt dem Apache-Webserver bei Anfragen für diesen virtuellen Host auf alle Dateien unterhalb von /srv/www/evil und /usr/share/apahce2/error/ zuzugreifen. Zusätzlich dürfen die zwei Protokolldateien geschrieben werden. Jeder weitere Zugriff ist nicht erlaubt.

Der Hat für den zweiten virtuellen Host wird analog konfiguriert. Existiert nun noch ein besonderes /admin-Verzeichnis, in dem durch ein Kennwort geschützt besondere privilegierte Skripte liegen, die erweiterten Schreibzugriff benötigen, um zum Beispiel Dateien hochzuladen, kann auch dies berücksichtigt werden. Hierzu wird die Apache-Konfiguration zunächst angepasst:

<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot /srv/www/bookshop
    ServerName bookshop.opensource-training.de
    ErrorLog /var/log/apache2/bookshop
    CustomLog /var/log/apache2/bookshop-access common
    <Directory /srv/www/bookshop>
       Order allow,deny
       allow from all
    </Directory>
    <Directory /srv/www/bookshop/admin>
       AAHatName bookshop-admin
    </Directory>
</VirtualHost>
Nun kann ein weiterer Hat definiert werden:
  ^bookshop-admin {
    /srv/www/bookshop/** rw,
    /usr/share/apache2/error/** r,
    /var/log/apache2/bookshop w,
    /var/log/apache2/bookshop-access w,
  }
Sobald nun ein Skript aus dem Verzeichnis /srv/www/bookshop/admin aufgerufen wird, wechselt der Webserver aus dem Hat ^bookshop in den Hat ^bookshop-admin. In diesem Hat erlaubt AppArmor einen schreibenden Zugriff auf die Dateien in /srv/www/bookshop. Natürlich müssen auch die UNIX-Dateirechte dem Apache-Webserver den schreibenden Zugriff erlauben. Ein Schreibzugriff außerhalb des Verzeichnisses oder durch den anderen virtuellen Host wird aber wirksam unterbunden.

Ralf Spenneberg 2007-11-13