16. Sicherheits-Review
Sicherheits-Review
Abschnitt betitelt „Sicherheits-Review“In Kapitel 9 haben Sie Angriffsvektoren einzeln kennengelernt, jeden an einem präparierten Beispiel. Diese Woche wenden Sie alles zusammen auf ein echtes System an: auf Ihres.
Ein Review ist kein Blick über den Code. Es ist ein Verfahren mit festgelegtem Umfang, einer abzuarbeitenden Liste und einem Dokument am Ende. Der Unterschied ist praktisch bedeutsam: „Wir haben uns das angeschaut” lässt sich weder überprüfen noch wiederholen, und in vier Wochen weiß niemand mehr, was geprüft wurde und was nicht.
Vorgehen
Abschnitt betitelt „Vorgehen“Umfang festlegen
Abschnitt betitelt „Umfang festlegen“Zuerst schreiben Sie auf, was geprüft wird, und ebenso, was nicht. Das zweite ist wichtiger, als es klingt: Ohne diese Grenze fehlt am Ende die Aussage, ob eine Lücke übersehen oder bewusst ausgeklammert wurde.
| Im Umfang | Außerhalb |
|---|---|
| VPS samt SSH, Firewall, Updatestand | Netz der Schule, Hetzner-Infrastruktur |
| Docker-Aufbau, Dokploy, Geheimnisse, Sicherungen | Basis-Images der Hersteller |
| Eigene Anwendung samt Schnittstelle | Fremde Dienste, die Sie nur aufrufen |
| CMS mit Erweiterungen | Quellcode des CMS selbst |
Abhängigkeiten aus package.json | |
| Gespeicherte Daten und Zugriffsrechte darauf |
Reihenfolge und Zeit
Abschnitt betitelt „Reihenfolge und Zeit“Erst die Breite, dann die Tiefe. Ein vollständiger Durchgang über alle Bereiche findet die groben Sachen und zeigt, wo es sich lohnt, genauer hinzusehen. Wer stattdessen sofort in ein Thema eintaucht, verbringt drei Stunden mit der Content-Security-Policy und übersieht, dass die Datenbank am offenen Port hängt.
Für die Woche hat sich diese Aufteilung bewährt: ein Durchgang über die Checkliste, danach Tiefenprüfung der zwei riskantesten Bereiche, danach beheben und nachweisen. Behebung braucht mehr Zeit als das Finden, planen Sie entsprechend.
Prüfbereiche
Abschnitt betitelt „Prüfbereiche“Die folgenden Tabellen sind Ihre Checkliste. Jede Zeile hat eine Prüfung und ein erwartetes Ergebnis, damit die Antwort nicht „passt schon” lautet, sondern eine Ausgabe ist, die Sie in den Bericht kopieren können.
| Prüfung | Kommando | Erwartet |
|---|---|---|
| SSH-Anmeldung | sudo sshd -T | grep -Ei "permitrootlogin|passwordauth" | no, und zwar in der wirksamen Konfiguration |
| Offene Ports | ss -tulpn | nur 22, 80, 443 nach außen |
| Firewall | sudo ufw status verbose | Regeln aktiv, Standard eingehend deny |
| Updatestand | apt list --upgradable | leer oder nur Unkritisches |
| Automatische Updates | systemctl status unattended-upgrades | aktiv, letzte Ausführung sichtbar |
Benutzer mit sudo | getent group sudo | genau die Personen, die es brauchen |
| Fehlanmeldungen | sudo fail2ban-client status sshd | Sperren greifen |
| Protokollgröße | journalctl --disk-usage | begrenzt, Platte nicht voll |
Prüfen Sie die Ports von außen nach, nicht nur auf dem Server selbst. Ein docker ps mit einer Zeile 0.0.0.0:5432->5432/tcp ist der Befund aus Kapitel 2, der am häufigsten unbemerkt zurückkommt, weil Docker die ufw-Regeln umgeht.
Auslieferung und Betrieb
Abschnitt betitelt „Auslieferung und Betrieb“| Prüfung | Wie | Erwartet |
|---|---|---|
| Geheimnisse im Repository | git log -p | grep -Ei "passwort|secret|api[_-]key" | keine Treffer, auch nicht in alten Ständen |
| Dokploy-Zugang | Anmeldung prüfen | eigenes Passwort, zweiter Faktor wenn möglich |
| Image-Stand | docker images | Basis-Images nicht ein Jahr alt |
| Rollback | einmal auf die Vorversion und zurück | funktioniert, Dauer bekannt |
| Sicherung vorhanden | Ablage prüfen | Datenbank und Uploads, aktuell |
| Sicherung brauchbar | in eine leere Datenbank einspielen | Daten vollständig, Zeitbedarf bekannt |
Die letzte Zeile ist die einzige, die zählt. Eine Sicherung, die nie zurückgespielt wurde, ist eine Vermutung über eine Datei. Machen Sie das einmal, mit Uhr, und schreiben Sie die Dauer auf.
Anwendung
Abschnitt betitelt „Anwendung“| Prüfung | Wie | Erwartet |
|---|---|---|
| Objektrechte | fremde ID mit eigenem Token abrufen | 404, kein fremder Datensatz |
| Rollenprüfung | Verwaltungsendpunkt als normaler Benutzer | 403 |
| Serverseitige Prüfung | Eingaben direkt per curl, ohne Formular | Zod-Validierung greift |
| Fehlerausgaben | Fehler provozieren | problem+json, kein Stacktrace, keine SQL-Meldung |
| Sicherheitskopfzeilen | curl -sI https://… | CSP, HSTS, X-Content-Type-Options gesetzt |
| CSP wirksam | Browserkonsole | keine Verstöße, kein unsafe-inline |
| Sitzungen | Abmelden, altes Cookie erneut senden | abgelehnt |
| Ratenbegrenzung | Anmeldung mehrfach falsch | 429 mit Retry-After |
| Uploads | Datei mit falschem Typ und großer Datei | abgelehnt, Typ serverseitig geprüft |
| Ausgabe von Benutzertext | <img src=x onerror=alert(1)> als Name | erscheint als Text, führt nichts aus |
Abhängigkeiten
Abschnitt betitelt „Abhängigkeiten“npm audit --omit=dev # known vulnerabilities in the shipped statenpm outdated # how far behind we arenpx depcheck # what is not used at all any moreDer dritte Befehl ist der unterschätzte. Jedes Paket, das im Projekt liegt und nicht benutzt wird, ist Angriffsfläche ohne Gegenwert. Entfernen ist die billigste Sicherheitsmaßnahme, die es gibt.
Der letzte Bereich läuft ohne Kommando. Schreiben Sie auf, welche personenbezogenen Daten Ihr System speichert, wer sie sehen kann, wo sie überall liegen (Datenbank, Sicherungen, Protokolle, CMS) und wie lange sie bleiben.
Zwei Befunde kommen dabei fast immer heraus: Protokolle, in denen vollständige Anfragedaten samt Namen stehen, und eine Löschfunktion, die es nicht gibt. Beides ist hier nur zu benennen, die rechtliche Seite kommt in der 5. Klasse.
Befunde bewerten
Abschnitt betitelt „Befunde bewerten“Die Matrix
Abschnitt betitelt „Die Matrix“Der Schweregrad ergibt sich aus zwei Fragen: Wie schlimm wäre es, und wie wahrscheinlich ist es?
| Auswirkung gering | Auswirkung mittel | Auswirkung hoch | |
|---|---|---|---|
| Wahrscheinlich | mittel | hoch | kritisch |
| Möglich | gering | mittel | hoch |
| Unwahrscheinlich | gering | gering | mittel |
„Wahrscheinlich” heißt: Ein automatisierter Scanner findet das, ohne Ihr System zu kennen. Genau deshalb ist eine offene Datenbank mit Standardpasswort kritisch und nicht mittel, obwohl niemand es bisher versucht hat.
Drei Entscheidungen
Abschnitt betitelt „Drei Entscheidungen“Jeder Befund bekommt genau eine Einordnung, und jede braucht eine Begründung.
- Sofort beheben. Kritisch und hoch, innerhalb dieser Woche.
- Geplant beheben. Mit Termin und verantwortlicher Person. Ohne beides ist es keine Planung, sondern eine Hoffnung.
- Bewusst tragen. Legitim, wenn der Aufwand außer Verhältnis steht. Dann gehört aufgeschrieben, wer das entschieden hat, ab wann, und was passieren müsste, damit die Entscheidung neu getroffen wird.
Die Befundvorlage
Abschnitt betitelt „Die Befundvorlage“Dasselbe Format wie in Kapitel 9, um zwei Felder erweitert. Jeder Befund kommt als eigene Datei nach docs/befunde/.
# B-04: Buchungen fremder Personen abrufbar
Bereich: Anwendung / AutorisierungSchweregrad: hoch (Auswirkung hoch, Wahrscheinlichkeit möglich)Gefunden: 2026-05-12, Prüfung Objektrechte
## Nachweis
curl -H "Cookie: sitzung=<eigenes Token>" \ https://projekt.example.at/api/buchungen/812 → 200, Datensatz einer fremden Person mit Name und Telefonnummer
## Ursache
Der Handler lädt die Buchung über die ID und prüft nur, ob eine gültigeSitzung besteht. Der Vergleich mit der Besitzerin fehlt.
## Auswirkung
Jede angemeldete Person kann durch Hochzählen der ID sämtliche Buchungensamt Kontaktdaten auslesen.
## Empfehlung
Prüfung im Service statt im Handler, Antwort 404 bei fremden Objekten(Kapitel 8).
## Status
Behoben am 2026-05-13, Nachweis unten, Regressionstest angelegt.Beheben und nachweisen
Abschnitt betitelt „Beheben und nachweisen“Behebung ohne erneuten Test ist keine Behebung, sondern eine Absicht. Der Nachweis ist derselbe Weg, der zum Befund geführt hat, nur mit dem erwarteten Ergebnis:
curl -i -H "Cookie: sitzung=<eigenes Token>" \ https://projekt.example.at/api/buchungen/812HTTP/2 404content-type: application/problem+jsonUnd dann der Schritt, der einen Befund dauerhaft erledigt: Aus dem Befund wird ein Test. Sonst kommt er beim nächsten Umbau zurück, und zwar unbemerkt.
it("does not hand out other people's bookings", async () => { const other = await createBooking({ userId: userB.id });
const response = await app.request(`/api/bookings/${other.id}`, { headers: { Cookie: await sessionFor(userA) }, });
expect(response.status).toBe(404);});Ein solcher Test ist mehr wert als der Bericht, in dem der Befund steht. Der Bericht dokumentiert einen Zustand, der Test hält ihn.
Gegenseitiges Review
Abschnitt betitelt „Gegenseitiges Review“Zwei Teams prüfen einander. Das findet mehr als jede Selbstprüfung, weil fremde Augen keine Betriebsblindheit mitbringen und weil niemand die Stelle auslässt, an der er selbst geschlampt hat.
Davor steht eine schriftliche Vereinbarung, unterschrieben von beiden Seiten. Das ist keine Formalie, sondern die Übung für genau das Dokument, das in der Berufspraxis vor jedem Penetrationstest steht.
## Prüfvereinbarung
Prüfendes Team: Team BGeprüftes System: https://projekt-a.example.at, VPS 203.0.113.7Zeitraum: 13.05.2026, 08:00 bis 12:00
Erlaubt: Zugriff über die Weboberfläche und die Schnittstelle, Anmeldung mit den bereitgestellten Testkonten, Portscan des genannten ServersNicht erlaubt: Lasttests, Löschen von Daten, Zugriff auf andere Systeme, Weitergabe gefundener DatenBei Befund: sofort an <Kontakt>, keine VeröffentlichungAbbruch: bei Ausfall des Systems sofort melden und stoppen
Datum, Unterschriften beider TeamsUnd für die Besprechung danach eine einzige Regel: Der Befund gilt dem System. „Diese Route prüft die Berechtigung nicht” ist ein Befund. „Ihr habt schlampig gearbeitet” ist keiner. Wer prüft, bringt Nachweise mit; wer geprüft wird, hört zu und diskutiert die Einstufung, nicht die Person.
Häufige Stolperfallen
Abschnitt betitelt „Häufige Stolperfallen“- Prüfen, was ohnehin gut ist, und die unangenehmen Bereiche überspringen. Deshalb arbeiten Sie die Liste ab, statt zu wählen.
- Befunde ohne Nachweis. Nach zwei Wochen weiß niemand mehr, welche ID mit welchem Token gemeint war.
- Alles als kritisch einstufen und die Priorisierung damit entwerten.
- Behebung ohne erneuten Test.
- Behebung ohne Regressionstest. Der Befund kommt beim nächsten Umbau zurück.
- Sicherung als vorhanden erklärt, ohne sie je zurückgespielt zu haben.
- Nur die Anwendung geprüft und Server, CMS und Abhängigkeiten ausgelassen. Angreifer suchen sich die einfachste Stelle aus.
- Nur auf dem Server geprüft, welche Ports offen sind, statt von außen.
- Fremde Systeme geprüft, auch nur ein Portscan, ohne Vereinbarung.
- Bericht ohne Restrisiken. Ein Bericht ohne offene Punkte ist selten vollständig und wirkt entsprechend.
Lernergebnisse
Abschnitt betitelt „Lernergebnisse“- Anwenden: einen Prüfumfang festlegen und begründen, was außerhalb bleibt.
- Analysieren: ein Gesamtsystem strukturiert gegen eine Checkliste prüfen, über alle Ebenen von SSH bis Ausgabe.
- Beurteilen: Befunde nach Auswirkung und Wahrscheinlichkeit einstufen und die Einstufung vertreten.
- Beurteilen: zwischen sofortiger Behebung, geplanter Behebung und bewusst getragenem Risiko entscheiden.
- Anwenden: Befunde beheben und die Behebung mit einem wiederholbaren Nachweis belegen.
- Erschaffen: aus einem Befund einen Regressionstest ableiten.
- Anwenden: ein gegenseitiges Review nach schriftlicher Vereinbarung durchführen.
- Erklären: verbleibende Restrisiken benennen und die eigene Sicherheitslage begründen.
Arbeit am Jahresprojekt
Abschnitt betitelt „Arbeit am Jahresprojekt“Ein Sicherheitsbericht in docs/sicherheitsbericht.md, der auf die Einzelbefunde in docs/befunde/ verweist:
- Geprüfter Umfang und was ausdrücklich außerhalb lag.
- Abgearbeitete Checkliste über alle fünf Bereiche, mit Ergebnis je Zeile.
- Befundliste mit Schweregrad nach der Matrix.
- Behebungsnachweise für alle Befunde ab „hoch”.
- Mindestens ein Regressionstest, der aus einem Befund entstanden ist.
- Nachweis einer eingespielten Sicherung samt Zeitbedarf.
- Restrisiken mit Begründung und der Angabe, wer sie wann entschieden hat.
Passende Übungen
Abschnitt betitelt „Passende Übungen“- Aufgabe - Checkliste abarbeiten und Befundbericht schreiben
- Aufgabe - Gegenseitiges Review mit Vereinbarung
- Aufgabe - Aus einem Befund einen Regressionstest machen