Sicherheitshinweise für PHP/MySQL-Anwendungen

Allgemeine Empfehlungen zur Absicherung von Apache-Servern, die PHP/MySQL-Anwendungen wie ConfTool betreiben – und nützlich für die meisten produktiven PHP-Umgebungen.

Immer HTTPS / TLS verwenden

Jede Anwendung, die Logins, personenbezogene Daten oder Zahlungsinformationen verarbeitet, muss ausschließlich über eine verschlüsselte Verbindung ausgeliefert werden. Besorgen Sie sich ein TLS-Zertifikat (z. B. ein kostenloses Zertifikat von Let’s Encrypt über certbot) und leiten Sie sämtlichen unverschlüsselten HTTP-Verkehr auf HTTPS um.

# In your virtual host: force HTTPS
<VirtualHost *:80>
    ServerName conference.example.org
    Redirect permanent / https://conference.example.org/
</VirtualHost>

Sobald HTTPS erzwungen wird, aktivieren Sie HTTP Strict Transport Security, damit Browser nicht mehr auf unverschlüsselte Verbindungen zurückfallen (siehe Security-Header unten).

Sicherheit des Apache-Servers

Zugriff auf Backup-Dateien sperren

Es empfiehlt sich, den Zugriff auf alle Backup-Dateien zu sperren. Handelt es sich dabei beispielsweise um PHP-Dateien, werden diese vom Server üblicherweise nicht ausgeführt und können Parameter wie das Passwort Ihrer MySQL-Datenbank offenlegen.

Um den Zugriff auf Backup-Dateien mit den Endungen .bak, .BAK und ~ zu sperren, fügen Sie Folgendes in Ihre httpd.conf (oder den entsprechenden Virtual Host) ein:

<FilesMatch "(\.bak|\.BAK|~)$">
 Require all denied
</FilesMatch>

Beispiel innerhalb eines Directory-Blocks:

<Directory "/home/conftool/">
  # Verzeichnisoptionen einschränken
  # -Indexes deaktiviert automatische Verzeichnisauflistungen
   Options -Indexes
   # -Includes deaktiviert Server-Side Includes (SSI
   Options -Includes
   # -ExecCGI verhindert die Ausführung von CGI-Skripten in diesem Verzeichnis.
   Options -ExecCGI

  # Legt fest, wer auf Inhalte dieses Verzeichnisses zugreifen darf.
  Require all granted

  # Zugriff auf Backup-Dateien verhindern!
  <FilesMatch "(\.bak|\.BAK|~)$">
      Require all denied
  </FilesMatch>
</Directory>

 

Die HTTP-Methode TRACE deaktivieren

Die HTTP-Methode TRACE gibt die empfangene Anfrage zurück. Für eine normale Anwendung hat sie keinen Nutzen und wurde in der Vergangenheit für Cross-Site-Tracing-Angriffe (XST) missbraucht, um ansonsten geschützte Header wie Cookies auszulesen. Deaktivieren Sie sie global in Ihrer Server- oder Virtual-Host-Konfiguration:

TraceEnable Off

Bitte beachten Sie: 
TraceEnable ist eine Direktive auf Server-Ebene – platzieren Sie sie in der httpd.conf oder innerhalb eines <VirtualHost>-Blocks. In einem <Directory>-Block oder einer .htaccess-Datei kann sie nicht gesetzt werden.

Security-Header

Mit aktiviertem mod_headers fügen Sie Antwort-Header hinzu, die gängige Angriffsflächen verringern. Setzen Sie HSTS erst, wenn HTTPS zuverlässig funktioniert.

Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set Referrer-Policy “no-referrer”

Sicherheit der MySQL-Datenbank

Netzwerkzugriff einschränken

Sofern nicht benötigt, sperren Sie den Netzwerkzugriff auf den MySQL-/MariaDB-Server von anderen Hosts. Eine Möglichkeit besteht darin, Folgendes in Ihre Konfigurationsdatei (my.cnf, üblicherweise in /etc/ oder unterhalb des Datenverzeichnisses) einzutragen:

skip-networking

Anwendungen müssen den MySQL-Daemon dann über eine Socket-Datei erreichen. Falls das vollständige Deaktivieren des Netzwerks Probleme verursacht, binden Sie den Server stattdessen an localhost:

bind-address = 127.0.0.1

Root-Passwort setzen

Verbinden Sie sich als root und setzen Sie das Passwort:

mysql -u root

-- im Client:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'myNewStrongPassword';
FLUSH PRIVILEGES;

Alternativ führen Sie bei einer Neuinstallation das geführte Härtungsskript mysql_secure_installation aus, das das Root-Passwort setzt sowie anonyme Benutzer und die Test-Datenbank entfernt.

Einen dedizierten Anwendungsbenutzer verwenden

Lassen Sie die Anwendung niemals als root verbinden. Legen Sie einen eigenen Benutzer an, der nur die Rechte besitzt, die er tatsächlich auf seiner eigenen Datenbank benötigt (Prinzip der geringsten Rechte):

CREATE USER 'conftool'@'localhost' IDENTIFIED BY 'aStrongPassword';
GRANT SELECT, INSERT, UPDATE, DELETE ON conftool_db.* TO 'conftool'@'localhost';
FLUSH PRIVILEGES;

Wenn Sie nur Datenrechte vergeben (und, wo nötig, Schemarechte während Installation/Upgrades), bleibt ein Angreifer, der die Anwendungs-Zugangsdaten erbeutet, von administrativen und dateibezogenen Möglichkeiten ausgeschlossen.

LOAD_FILE() und serverseitigen Dateizugriff deaktivieren

Die MySQL-Funktion LOAD_FILE() kann Dateien aus dem Dateisystem des Datenbankservers lesen und ihren Inhalt an eine Abfrage zurückgeben. In Kombination mit einer SQL-Injection-Schwachstelle können so Konfigurationsdateien, Passwort-Hashes oder andere sensible Daten offengelegt werden. Es gibt zwei einander ergänzende Maßnahmen.

1. Das FILE-Recht vorenthalten. LOAD_FILE() (ebenso wie LOAD DATA INFILE und SELECT … INTO OUTFILE) erfordert das globale FILE-Recht. Anwendungsbenutzer sollten es niemals besitzen. Wurde es einem Benutzer gewährt, entziehen Sie es:

REVOKE FILE ON *.* FROM 'conftool'@'localhost';
FLUSH PRIVILEGES;

Welche Konten es besitzen, können Sie prüfen:

SELECT grantee FROM information_schema.user_privileges
WHERE privilege_type = 'FILE';

2. Dateioperationen serverweit einschränken oder deaktivieren über die Systemvariable secure_file_priv im Abschnitt [mysqld] der my.cnf. Wird sie auf NULL gesetzt, ist jeglicher serverseitiger Datei-Import/-Export deaktiviert, sodass LOAD_FILE() für alle NULL zurückgibt – unabhängig von den Rechten:

[mysqld]
# Disable LOAD_FILE / LOAD DATA INFILE / SELECT ... INTO OUTFILE vollständig deaktivieren
secure_file_priv = NULL

Falls Sie den Datei-Import/-Export für bestimmte Wartungsaufgaben tatsächlich benötigen, richten Sie ihn auf ein einzelnes, abgeschottetes Verzeichnis aus, statt ihn vollständig zu deaktivieren:

secure_file_priv = "/var/lib/mysql-files/"

Bitte beachten Sie: 
secure_file_priv ist zur Laufzeit schreibgeschützt; der Server muss daher neu gestartet werden, damit Änderungen wirksam werden. Den aktuellen Wert prüfen Sie mit:

SHOW VARIABLES LIKE 'secure_file_priv';

PHP-Sicherheitseinstellungen

PHP ist keine „unsichere" Sprache, aber einige wenige Einstellungen verringern die Angriffsfläche der meisten Installationen. Sie werden in der php.ini gesetzt; manche lassen sich auch in der Apache-Konfiguration oder einer lokalen .htaccess-Datei setzen.

Achtung: 
Andere PHP-Skripte auf demselben Server können von diesen Einstellungen betroffen sein.

disable_functions

Einige PHP-Funktionen legen Systemressourcen, Parameter oder Dateien offen. Die heikelsten sind:

show_source, system, shell_exec, passthru, exec, phpinfo, popen, proc_open, proc_nice

ConfTool verwendet zwei davon:

exec wird auf Windows-Systemen genutzt, um zu prüfen, ob die Domain einer E-Mail-Adresse existiert (alle Parameter werden vor dem Aufruf bereinigt; in einigen angepassten Bibliotheken wird es zudem für den Zugriff auf Kreditkarten-Gateways verwendet). popen wird von der Bibliothek PHPMailer zum E-Mail-Versand genutzt (Sie können stattdessen die eingebaute mail-Funktion von PHP verwenden, sie ist jedoch weniger leistungsfähig).

Wenn Sie diese Funktionen nutzen, deaktivieren Sie nur die übrigen:

disable_functions = show_source, system, shell_exec, passthru, phpinfo, proc_open, proc_nice

allow_url_fopen / allow_url_include

allow_url_fopen = Off

Dies sollte auf den meisten Servern gesetzt sein. Es verhindert, dass Skripte Code oder Daten von entfernten Servern laden – ein potenzielles Sicherheitsrisiko. Falls einige Ihrer Skripte allow_url_fopen wirklich benötigen, können Sie zumindest entferntes include/require separat unterbinden:

allow_url_include = Off

display_errors / log_errors

display_errors = Off

Dies unterdrückt die Ausgabe von PHP-Fehlern an Benutzer (und potenzielle Angreifer) und sollte im Produktivbetrieb immer ausgeschaltet sein. Protokollieren Sie Fehlerdetails stattdessen weiterhin im Server-Log zur Analyse:

log_errors = On

open_basedir

Beschränkt die Verzeichnisse, aus denen PHP-Dateien ausgeführt werden dürfen; Dateien außerhalb der angegebenen Pfade werden nicht ausgeführt. Es ist grundsätzlich empfehlenswert, PHP auf die Verzeichnisse der bekannten Anwendungen zu beschränken.

# Beispiel Unix/Linux
open_basedir = "/home/conftool/:/srv/www/"

# Beispiel Windows
open_basedir = "D:/www/conftool/;C:/Apache24/htdocs/"

expose_php / Session-Cookies

Verbergen Sie die PHP-Version in den Antwort-Headern und erschweren Sie das Stehlen oder den Missbrauch von Session-Cookies. Das secure-Flag setzt die oben beschriebene HTTPS-Einrichtung voraus.

expose_php = Off
session.cookie_secure   = On
session.cookie_httponly = On
session.cookie_samesite = “Lax”

Software aktuell halten

Betreiben Sie nur PHP- und MySQL-/MariaDB-Versionen, die noch Sicherheitsunterstützung erhalten, und spielen Sie Betriebssystem- und Anwendungs-Updates zeitnah ein. Erwägen Sie einen grundlegenden Brute-Force-Schutz für den Login (z.B. fail2ban) und überprüfen Sie die Dateisystem-Rechte, damit Konfigurationsdateien mit Zugangsdaten nicht für alle lesbar sind.

Fazit

Sicherheit ist kein Zustand, sondern ein Prozess. 
Da PHP und MySQL sehr verbreitet sind, sollten Sie aktuelle Entwicklungen verfolgen und Ihre Servereinstellungen entsprechend anpassen. Falls Sie mögliche Probleme in ConfTool entdecken, kontaktieren Sie uns bitte umgehend.