Level 3 – Einfache Serververwaltung (Minimal)
Version vom 24. März 2026, 20:18 Uhr von Thomas.will (Diskussion | Beiträge) (→Anpassung: index.php (XSS Schutz))
Level 3 – Absicherung der Anwendung (Security Hardening)
Voraussetzung
- Level 2 muss vollständig umgesetzt und funktionsfähig sein
- Benutzerverwaltung und Login existieren
- Anwendung ist erreichbar unter:
http://SERVER-IP/server
Ziel
- Absicherung gegen SQL Injection
- Sichere Speicherung von Passwörtern
- Einführung von Rollen (admin / user)
- Schutz vor Cross-Site-Scripting (XSS)
Erweiterung der Datenbank
- Anmeldung an MariaDB
mysql -u root
- Datenbank auswählen
use serververwaltung;
- Tabelle erweitern (Rollen hinzufügen)
alter table benutzer add rolle varchar(20);
- Rollen setzen
update benutzer set rolle='admin' where benutzername='admin'; update benutzer set rolle='user' where benutzername='user';
Passwort-Hashing
- Passwörter dürfen nicht im Klartext gespeichert werden
- Stattdessen wird ein Hash verwendet
- Beispiel (PHP):
<?php
echo password_hash("admin", PASSWORD_DEFAULT);
?>
- Den erzeugten Hash in die Datenbank eintragen
update benutzer set passwort='HASH_HIER_EINFUEGEN' where benutzername='admin'; update benutzer set passwort='HASH_HIER_EINFUEGEN' where benutzername='user';
Datei: login.php (sicher)
- Verwendung von Prepared Statements
- Überprüfung des Passworts mit password_verify()
<?php
include 'db.php';
session_start();
$benutzername = $_POST['benutzername'];
$passwort = $_POST['passwort'];
$stmt = $conn->prepare("SELECT * 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['user'] = $benutzername;
$_SESSION['rolle'] = $row['rolle'];
header("Location: index.php");
exit;
}
}
echo "Login fehlgeschlagen";
?>
Datei: add.php (sicher)
- Schutz durch Session
- Verwendung von Prepared Statements
<?php
include 'db.php';
session_start();
if (!isset($_SESSION['user'])) {
die("Nicht eingeloggt");
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$rechnername = $_POST["rechnername"];
$ip_adresse = $_POST["ip_adresse"];
$betriebssystem = $_POST["betriebssystem"];
$festplattenspeicher = $_POST["festplattenspeicher"];
$ram = $_POST["ram"];
$hauptdienst = $_POST["hauptdienst"];
$stmt = $conn->prepare("INSERT INTO server (rechnername, ip_adresse, betriebssystem, festplattenspeicher, ram, hauptdienst)
VALUES (?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssiss",
$rechnername,
$ip_adresse,
$betriebssystem,
$festplattenspeicher,
$ram,
$hauptdienst
);
if ($stmt->execute()) {
header("Location: index.php");
exit;
} else {
echo "Fehler";
}
}
?>
Datei: delete.php (sicher)
- Nur Admin darf löschen
- Verwendung von Prepared Statements
<?php
include 'db.php';
session_start();
if (!isset($_SESSION['user'])) {
die("Nicht eingeloggt");
}
if ($_SESSION['rolle'] !== 'admin') {
die("Keine Berechtigung");
}
$id = $_GET['id'];
$stmt = $conn->prepare("DELETE FROM server WHERE id = ?");
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo "Server gelöscht";
} else {
echo "Fehler";
}
?>
Anpassung: index.php (XSS Schutz)
- Ausgabe der Daten absichern
<?php
session_start();
include 'db.php';
$result = $conn->query("SELECT * FROM server");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Serververwaltung</title>
</head>
<body>
<?php
if (isset($_SESSION['user'])) {
echo "Eingeloggt als: " . htmlspecialchars($_SESSION['user']) . "<br>";
} else {
echo "<a href='login.html'>Login</a><br>";
}
?>
<h2>Neuen Server eintragen</h2>
<form method="post" action="add.php">
Rechnername: <input type="text" name="rechnername" required><br>
IP-Adresse: <input type="text" name="ip_adresse" required><br>
Betriebssystem: <input type="text" name="betriebssystem" required><br>
Festplatte (GB): <input type="number" name="festplattenspeicher" required><br>
RAM (GB): <input type="number" name="ram" required><br>
Hauptdienst: <input type="text" name="hauptdienst" required><br>
<input type="submit" value="Speichern">
</form>
<h2>Serverliste</h2>
<?php
if ($result->num_rows > 0) {
echo "<table border='1'>";
echo "<tr><th>ID</th><th>Name</th><th>IP</th><th>OS</th><th>Disk</th><th>RAM</th><th>Dienst</th><th>Aktion</th></tr>";
while ($row = $result->fetch_assoc()) {
echo "<tr>";
echo "<td>".$row["id"]."</td>";
echo "<td>".htmlspecialchars($row["rechnername"])."</td>";
echo "<td>".htmlspecialchars($row["ip_adresse"])."</td>";
echo "<td>".htmlspecialchars($row["betriebssystem"])."</td>";
echo "<td>".$row["festplattenspeicher"]."</td>";
echo "<td>".$row["ram"]."</td>";
echo "<td>".htmlspecialchars($row["hauptdienst"])."</td>";
echo "<td><a href='delete.php?id=".$row["id"]."'>löschen</a></td>";
echo "</tr>";
}
echo "</table>";
} else {
echo "Keine Server vorhanden.";
}
?>
</body>
</html>
Test
- Login mit admin/admin
- Login mit user/user
- SQL Injection testen
' OR 1=1 --
- Ergebnis:
- Login funktioniert NICHT mehr
- Löschen testen
- admin → funktioniert
- user → wird verweigert
Ergebnis
- Teilnehmer verstehen:
- Warum SQL Injection gefährlich ist
- Wie Prepared Statements schützen
- Warum Passwort-Hashing notwendig ist
- Wie Rollen Zugriff steuern
- Warum Ausgaben gefiltert werden müssen