In den bisherigen Themen ging es vor allem um sicheren Code: Eingaben prüfen, Ausgaben sicher kodieren, Fehler sauber behandeln und Komponenten voneinander isolieren. Das ist sehr sinnvoll und notwendig, reicht aber noch nicht.

Eine Anwendung besteht nicht nur aus Code. Sie besteht auch aus Einstellungen und Konfigurationen. Diese Einstellungen entscheiden zum Beispiel, ob Debug-Ausgaben aktiv sind, wie lange Sitzungen gültig bleiben, welche Domains auf eine API zugreifen dürfen, ob Testkonten erlaubt sind und welche externen Dienste angebunden werden.
Die Anwendung muss nicht nur korrekt programmiert sein. Sie muss auch sicher betrieben werden können.
Bei NovaHealth wird das neue Modul für Laborergebnisse in die Staging-Umgebung ausgerollt. Staging ist eine Testumgebung, die möglichst nah an der Produktion liegt. Dort fällt Melina eine Konfigurationsdatei auf:
APP_ENV=production
DEBUG=true
ALLOW_TEST_LOGIN=true
TOKEN_TTL_MINUTES=1440
RATE_LIMITING_ENABLED=false

„Das sieht nach einer typischen Testkonfiguration aus. Kritisch wird es, wenn genau so etwas versehentlich in Produktion landet, oder?“
„Genau. Der Code kann sauber sein, aber diese Werte ändern das Sicherheitsverhalten der Anwendung. DEBUG=true kann interne Details preisgeben, ALLOW_TEST_LOGIN=true öffnet Testzugänge und ohne Rate Limiting können Anfragen automatisiert wiederholt werden.“

Anwendungskonfiguration umfasst Einstellungen, die das Verhalten einer Anwendung ändern, ohne den Quellcode selbst zu verändern. Dazu gehören zum Beispiel Umgebungsvariablen, Konfigurationsdateien, Feature Flags oder Deployment-Vorlagen.

Feature Flags sind Schalter, mit denen Funktionen aktiviert oder deaktiviert werden können, ohne neuen Code auszurollen. Das ist praktisch für Tests und schrittweise Releases. Es wird gefährlich, wenn Testfunktionen versehentlich in Produktion aktiv bleiben.
Vereinfacht gesagt: Der Code beschreibt, was die Anwendung kann. Die Konfiguration bestimmt, wie sie sich in einer konkreten Umgebung verhält.
Härtung (Hardening) bedeutet, unnötige Angriffsfläche zu reduzieren. In früheren Kapiteln haben wir Härtung bereits für DNS, E-Mail, Webanwendungen und Active Directory betrachtet. Hier geht es nicht darum, diese Themen zu wiederholen.
Im Kontext der sicheren Anwendungsentwicklung bedeutet Härtung: Die Anwendung wird so gebaut, dass unsichere Betriebszustände schwerer entstehen.
Das betrifft vor allem diese Fragen:
Schauen wir das nochmal etwas genauer an.
Eine Anwendung sollte nicht erst sicher werden, wenn jemand diverse Optionen durchgeht. Die sichere Variante sollte der Standard sein. In der vorigen NovaHealth Konfiguration wären das zum Beispiel Einstellungen wie:
DEBUG=false
ADMIN_MFA_REQUIRED=true
CORS_ALLOWED_ORIGINS=https://portal.novahealth-solutions.de
Damit sind Debug-Ausgaben ausgeschaltet, Admin-Konten benötigen MFA (Multi-Factor Authentication) und die API akzeptiert Browser-Anfragen nur vom NovaHealth-Portal.
Secure by Default bedeutet: Die sichere Variante ist voreingestellt. Unsichere Ausnahmen müssen bewusst aktiviert und begründet werden.
Eine sichere Anwendung sollte bei kritischen Produktionswerten nicht raten. Wenn ein Wert fehlt, der für Sicherheit relevant ist, muss das auffallen. Sonst läuft die Anwendung möglicherweise mit einem bequemen Ersatzwert weiter, der nie für Produktion gedacht war.
if (config.environment === 'production' && config.debug === true) {
throw new Error('DEBUG darf in Produktion nicht aktiv sein');
}
Dieses Prinzip nennt man Fail Safe oder Fail Closed. Es bedeutet: Wenn eine sicherheitskritische Prüfung fehlschlägt, wird der Zugriff oder der Start verweigert, statt unsicher weiterzulaufen.
Entwickler benötigen detaillierte Logs, Testdaten, lokale URLs und manchmal vereinfachte Abläufe. In Produktion darf das nicht aktiv bleiben.
In Produktion sollten Debug-Ausgaben deaktiviert, Testfunktionen ausgeschaltet und administrative Funktionen streng geschützt sein. Tokens sollten nur so lange gültig sein wie fachlich nötig. Logs dürfen keine Passwörter, Tokens oder Patientendaten enthalten. Beispiel: Ein Stacktrace zeigt, an welcher Stelle im Programm ein Fehler entstanden ist. Für Entwickler ist das hilfreich. Für Angreifer kann es interne Klassen, Dateipfade, Datenbanknamen oder verwendete Frameworks offenlegen.
Bei NovaHealth könnte ein Testlogin während der Entwicklung praktisch sein. In Produktion darf er aber nicht nur per Konfiguration „ausgeschaltet“ sein, wenn ein einfacher Schalter ihn wieder aktivieren kann. Besser ist, solche Funktionen gar nicht in produktive Builds aufzunehmen oder sie an klare technische Bedingungen zu knüpfen, die in Produktion nicht erfüllt sind.
Eine Änderung an sicherheitsrelevanter Konfiguration kann genauso kritisch sein wie eine Änderung am Code.

Deshalb gehören Konfigurationsdateien, Deployment-Vorlagen und Feature-Flag-Änderungen in denselben Review-Prozess wie Code. Mindestens eine zweite Person sollte prüfen, ob die Änderung fachlich notwendig und sicher vertretbar ist.
Konfiguration sollte nicht nur dokumentiert, sondern automatisch geprüft werden. Sonst bleibt Sicherheit von manueller Aufmerksamkeit abhängig.
Bei NovaHealth könnte die CI/CD-Pipeline vor dem Deployment prüfen, ob die Produktionskonfiguration Mindestanforderungen erfüllt.
Eine solche Prüfung muss nicht kompliziert sein. Für Produktion kann zum Beispiel festgelegt werden: DEBUG muss false sein, ADMIN_MFA_REQUIRED muss true sein. Eine unsichere Einstellung fällt somit vor dem Deployment auf, nicht erst im Betrieb.
Secrets gehören nicht in den Quellcode und nicht in normale Konfigurationsdateien im Repository. Eine Konfiguration darf beschreiben, welches Secret gebraucht wird. Sie sollte das Secret selbst aber nicht enthalten. Statt DATABASE_PASSWORD=SuperSecret123 wäre ein Verweis wie DATABASE_PASSWORD_SECRET_NAME=novahealth/prod/lab-results/db-password sinnvoller. Der Wert enthält nicht das Passwort selbst, sondern zeigt auf den Eintrag im Secret-Management-System.
Die OWASP Cheat Sheet Series beschreibt wichtige Grundlagen für Secret Management: https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html
Secrets werden nicht in Git eingecheckt, nicht in Logs ausgegeben und nicht in Container-Images eingebaut. Anwendungen bekommen nur die Secrets, die sie wirklich brauchen. Außerdem müssen Secrets rotiert werden können, ohne den Anwendungscode anzupassen.
Für Webanwendungen bietet der OWASP ASVS (Application Security Verification Standard) einen verbreiteten, herstellerneutralen Anforderungskatalog. Er beschreibt überprüfbare Sicherheitsanforderungen für Entwicklung und Tests von Webanwendungen. In der aktuellen Version behandelt Kapitel V13 „Configuration“ u. a. sichere Standardkonfiguration, Secret Management, Debug-Modi in Produktion, deaktivierte Directory Listings, keine veröffentlichten .git-Ordner und Schutz von Monitoring- oder API-Dokumentationsendpunkten.
Die Twelve-Factor App ist ein weiterer Leitfaden für moderne, cloudfähige Anwendungen. Ein zentrales Prinzip lautet, Konfiguration vom Code zu trennen: Datenbank-Adressen, externe Dienste, Zugangsdaten und umgebungsspezifische Einstellungen werden beim Deployment bereitgestellt statt fest im Quellcode hinterlegt. Das reduziert insbesondere das Risiko, dass Secrets versehentlich in Repositories oder Build-Artefakte gelangen. Sensible Zugangsdaten sollten in Produktion zusätzlich über ein Secret-Management-System verwaltet werden.
Sichere Anwendungsentwicklung endet nicht beim Quellcode. Sie umfasst auch die Konfiguration, mit der dieser Code später betrieben wird.