Einfache Serververwaltung mit PHP und MySQL Sicherheit

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Sicherheitserweiterung für das Projekt "Serververwaltung"

Ziel

Dieses Dokument verbessert die Sicherheit des bestehenden Projekts „Serververwaltung“, indem es unsichere Praktiken durch sichere Alternativen ersetzt – konkret am bestehenden Quellcode und Setup.

Übersicht der Verbesserungen

  • Kein Datenbankzugriff mit Root-Rechten
  • Kein Klartextpasswort im Webverzeichnis
  • Nutzung von Prepared Statements gegen SQL-Injection
  • Keine Fehlermeldungen an Benutzer
  • Sessions korrekt abgesichert

Sicherer Datenbankbenutzer

Statt root wird ein eingeschränkter Benutzer webapp verwendet:

CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'sicheres-passwort';
GRANT SELECT, INSERT, UPDATE, DELETE ON serververwaltung.* TO 'webapp'@'localhost';
FLUSH PRIVILEGES;

Zugangsdaten auslagern

Die Datei mit Zugangsdaten wird außerhalb des Webroots gespeichert: /etc/serververwaltung/db.conf.php

<?php
return [
  'host' => '127.0.0.1',
  'user' => 'webapp',
  'pass' => 'sicheres-passwort',
  'name' => 'serververwaltung'
];

Dateiberechtigungen setzen:

chmod 640 /etc/serververwaltung/db.conf.php
chown root:www-data /etc/serververwaltung/db.conf.php

Überarbeitung der Datei db.php

<?php
$config = require('/etc/serververwaltung/db.conf.php');

$conn = new mysqli($config['host'], $config['user'], $config['pass'], $config['name']);

if ($conn->connect_error) {
    error_log("DB-Verbindung fehlgeschlagen: " . $conn->connect_error);
    die("Interner Fehler. Bitte später erneut versuchen.");
}

Absicherung der Datei login.php

Verwendung von Prepared Statements statt direktem SQL und sichere Passwort-Hashes.

<?php
session_start();
include 'db.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $benutzername = $_POST["benutzername"];
    $passwort = $_POST["passwort"];

    $stmt = $conn->prepare("SELECT passwort, rolle FROM benutzer WHERE benutzername = ?");
    $stmt->bind_param("s", $benutzername);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($row = $result->fetch_assoc()) {
        if (password_verify($passwort, $row['passwort'])) {
            $_SESSION["benutzername"] = $benutzername;
            $_SESSION["rolle"] = $row["rolle"];
            header("Location: auswahl.html");
            exit;
        }
    }

    echo "Falsche Anmeldedaten.";
}

Passwort-Hash bei Benutzeranlage

Beim Erstellen neuer Benutzer:

insert into benutzer (benutzername, passwort, rolle)
values ('admin', 'REPLACE_DURCH_HASH', 'admin');

Beispiel für Passwort-Hash in PHP generieren:

php -r "echo password_hash('radler', PASSWORD_DEFAULT);"

Eintrag mit Prepared Statement (eintragen.php)

<?php
include 'db.php';
session_start();

if (!isset($_SESSION["benutzername"])) {
    header("Location: login.html");
    exit;
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $stmt = $conn->prepare("INSERT INTO server (rechnername, ip_adresse, betriebssystem, festplattenspeicher, ram, hauptdienst)
                            VALUES (?, ?, ?, ?, ?, ?)");
    $stmt->bind_param("sssdds",
        $_POST["rechnername"],
        $_POST["ip_adresse"],
        $_POST["betriebssystem"],
        $_POST["festplattenspeicher"],
        $_POST["ram"],
        $_POST["hauptdienst"]
    );

    if ($stmt->execute()) {
        header("Location: liste.php");
        exit;
    } else {
        error_log("Fehler beim Eintrag: " . $stmt->error);
        echo "Interner Fehler beim Eintrag.";
    }
}

Session-Absicherung

Session-Cookie absichern:

In PHP-Ini oder am Anfang des Scripts:

session_set_cookie_params([
  'lifetime' => 0,
  'path' => '/',
  'domain' => '', // ggf. setzen
  'secure' => true,
  'httponly' => true,
  'samesite' => 'Strict'
]);
session_start();

HTTPS

Das Projekt läuft nur über HTTPS. HTTP wird per Apache umgeleitet:

Datei: /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
    ServerName server.it113.int
    Redirect permanent / https://server.it113.int/
</VirtualHost>

Aktivieren:

a2ensite default-ssl
a2enmod rewrite
a2enmod ssl
systemctl reload apache2

Zusammenfassung

  • Root-Nutzer ersetzt
  • Passwörter aus Webverzeichnis entfernt
  • Alle SQL-Zugriffe auf Prepared Statements umgestellt
  • Passwörter gehasht
  • Fehlerprotokollierung statt Benutzeranzeige
  • Sessions und HTTPS korrekt konfiguriert