Java-Logging: Was sollten Sie protokollieren – und was nicht?
11. November 2020
0 Min. LesezeitLogs sind ein praktisches Hilfsmittel, um Fehler zu erkennen und Code zu debuggen. Für Engineers und insbesondere in einer DevOps-Umgebung sind Logs ein äußerst wertvolles Werkzeug.
Neben ihrem funktionalen Nutzen sind Logs auch aus Java-Sicherheitsperspektive entscheidend. Kommt es zu einem Sicherheitsvorfall, sind Ihre Logdateien die erste Anlaufstelle, um Hinweise auf den Hergang zu finden. Doch wie wählen Sie bei der Vielzahl verschiedener Frameworks für das Logging in Java-Anwendungen das richtige aus? Und noch wichtiger: Wie gelingt Java-Logging richtig?
Die Qualität der Logs ist entscheidend. Zu viele oder zu wenige Informationen zu protokollieren, kann aus Java-Sicherheitsperspektive katastrophale Folgen haben. Tatsächlich steht „Insufficient Logging & Monitoring“ (A10:2017) auf der OWASP Top 10-Liste.
In diesem Artikel zeige ich Ihnen einen pragmatischen Ansatz für Java-Logging: Was sollten wir protokollieren, was nicht und wie lässt sich Java-Logging richtig implementieren?
Was sollten wir protokollieren?
Beim Militär mussten wir früher immer die 5W-H-Methode anwenden, wenn wir etwas melden sollten – Who, What, Where, When, Why und How (Wer, Was, Wo, Wann, Warum und Wie). Diese Methode ist auch eine hervorragende Regel für Log-Einträge.
Wer hat das getan?
Identifizieren Sie den Benutzer oder das System, von dem die Anfrage stammt. Wenn möglich, mit einer userID und einer IP-Adresse.
Was passiert?
Um welche Art von Log-Eintrag handelt es sich? Viele Entwickler kennen bereits die verschiedenen Log-Level, mit denen sich die Wichtigkeit einer Meldung kennzeichnen lässt (ERROR, WARN, INFO, DEBUG, TRACE). Es ist sinnvoll, zwischen funktionalem Logging, Security-Logging und gegebenenfalls auch Audit-Logging zu unterscheiden.
Wo ist es passiert?
Identifizieren Sie den Ort. In der Regel definieren Sie für jede Klasse einen Logger – das ist bereits ein guter Anfang. Sie müssen jedoch auch die jeweilige Methode kennen. Außerdem ist es wichtig, den konkreten Knoten zu kennen, zum Beispiel bei einer Microservice-Architektur.
Wann ist es passiert?
Der Zeitpunkt ist entscheidend. Achten Sie daher darauf, einen Zeitstempel zu protokollieren. Berücksichtigen Sie Zeitzonenunterschiede und vor allem, dass sich die Zeitzone zweimal jährlich ändert. Mein Rat: Geben Sie die Zeit immer in UTC aus, damit sie für alle eindeutig ist.
Warum ist es passiert?
Meistens müssen Sie genau dieses „Warum“ herausfinden. Das lässt sich nicht immer in einem einzigen Log-Eintrag festhalten. In manchen Fällen ist es offensichtlich. Wenn das so ist, nehmen Sie es in die Meldung auf. Oft können wir das „Warum“ jedoch erst erklären, wenn wir die Zusammenhänge zwischen den Logs erkennen. Achten Sie deshalb darauf, dass Ihre Log-Meldungen absolut klar formuliert sind.
Wie ist es passiert?
Wie das „Warum“ lässt sich auch das „Wie“ in der Regel nicht in einem einzigen Eintrag festhalten. Daher ist es äußerst wichtig, Meldungen miteinander zu korrelieren – insbesondere in einer servicebasierten Architektur. Erstellen Sie dafür für jede eingehende Anfrage in jedem Service mit ausgehender Schnittstelle eine eindeutige Korrelations-ID. Protokollieren Sie diese ID in jedem Eintrag. Wenn Sie die ID an einen anderen Service übertragen müssen, können Sie den entsprechenden HTTP-Header X-Correlation-ID verwenden, um die Meldungen zustandslos miteinander zu korrelieren.
Security-Ereignisse protokollieren
Java wird überwiegend in Backend-Prozessen eingesetzt und interagiert direkt mit Daten. Deshalb müssen wir sicherheitsrelevante Ereignisse nachverfolgen. Wir müssen diese entsprechend priorisieren und Ereignisse, für die hohe Berechtigungen erforderlich sind (Admin-Ereignisse), als besonders kritisch einstufen.
Zu den typischen Ereignissen gehören:
erfolgreiche und fehlgeschlagene Logins
Logouts
Passwortänderungen und -zurücksetzungen
Erstellen und Entfernen von Benutzern
Autorisierungsfehler
Änderungen der Zugriffsebene
Zusätzlich sollten Sie auch Indikatoren protokollieren, die auf bestimmte Angriffe hindeuten können.
Fehler bei der Eingabevalidierung: Erkennen Sie Script-Tags, die zu XSS-Angriffen führen, oder Parameter wie UNION, die auf eine SQL-Injection hindeuten
HTTP 4xx- und 5xx-Antworten
ungewöhnlich viele Anfragen von einer bestimmten IP-Adresse
Prüfen Sie IP-Adressbereiche, etwa wenn ein interner Service von einer externen IP-Adresse angegriffen wird
Eine gute Maßnahme ist es, Schwellenwerte für bestimmte Security-Log-Ereignisse festzulegen. Werden diese überschritten, können Sie automatisch Warnmeldungen versenden. So können Sie gezielt eingreifen und größeren Schaden verhindern.
Was sollten wir nicht protokollieren?
Zu viele Informationen zu protokollieren ist genauso schädlich wie zu wenige. Ihre Logs sollten nicht mit Informationen überflutet werden, die in der Produktionsumgebung keinen Nutzen haben. Stellen Sie deshalb sicher, dass Sie das Log-Level in einem Produktionssystem stets auf einen geeigneten Wert wie WARN oder ERROR setzen.
Während der Entwicklung protokollieren Engineers sensible Entitäten, die personenbezogene Daten enthalten können, um Anwendungen zu debuggen. Zwar sollten wir das möglichst verhindern, doch interne Debug-Meldungen sollten das richtige Log-Level haben – zum Beispiel DEBUG oder TRACE – und in der Produktionsumgebung nicht sichtbar sein.
Grundsätzlich sollte eine Anwendung keine anwendungs- oder benutzerspezifischen Daten offenlegen, da Angreifer diese nutzen könnten. Wenn Sie personenbezogene Informationen preisgeben, verstoßen Sie höchstwahrscheinlich auch gegen Datenschutzvorschriften. Selbst wenn nur interne Personen auf die Logs zugreifen können, stellen sie einen einzelnen Schwachpunkt dar. Diese Informationen sollen also keinesfalls in die falschen Hände geraten.
Überlegen Sie bei der Entwicklung, was protokolliert werden muss. Müssen wir eine interne ID, ein unverschlüsseltes Passwort oder die Kreditkartendaten einer Person protokollieren? Geben Sie nicht versehentlich ein vollständiges Datenobjekt in Java aus, denn die Ausgabe hängt von der toString()-Methode des jeweiligen Objekts ab.
Wenn wir personenbezogene Informationen zu Debugging-Zwecken protokollieren, umgehen wir viele unserer eigenen Sicherheitsrichtlinien. Es wäre daher sinnvoll, solche Informationen grundsätzlich nicht zu protokollieren. Falls bestimmte Daten protokolliert werden müssen, achten Sie darauf, das passende Log-Level wie DEBUG festzulegen. Setzen Sie das Log-Level des Produktionssystems außerdem auf einen höheren Wert wie WARN.
Kurz gesagt: Personenbezogene und sensible Informationen dürfen in Ihren Produktions-Logs nicht auftauchen.
Security-Logging in Java
Verwenden Sie in Java in jedem Fall ein Logging-Framework. Das scheint selbstverständlich, doch in vielen Anwendungen verwenden Entwickler immer noch das veraltete System.out.println(), um direkt in die Konsole zu schreiben. Das muss unbedingt verhindert werden. Ein guter Linter (Spotbugs, PMD, SonarLint) kann Ihnen dabei helfen.
Für Java gibt es zahlreiche Logging-Frameworks. Dieser Artikel konzentriert sich auf Logback und Log4j2, da diese derzeit am häufigsten verwendet werden. Unabhängig vom Framework ist es jedoch sinnvoll, Security-Logging von allgemeinem Application-Logging zu trennen. Sowohl in Logback als auch in Log4j2 können Sie das ganz einfach erreichen, indem Sie dem Logger Marker hinzufügen. Mit einem bestimmten Marker wie SECURITY oder auch AUDIT können Sie diese Einträge in Ihren Logs einfach filtern. Sie können dem Logger auch einen zusätzlichen Appender hinzufügen und nach dem jeweiligen Marker filtern, um diese Logs separat zu speichern oder anzuzeigen.
Logback
Für die Implementierung von Logback benötigen Sie lediglich die Abhängigkeit logback-classic, wie unten gezeigt. Damit werden sowohl die Pakete logback-core als auch slf4j-api eingebunden.
Marker
Marker lassen sich mit beliebigen Strings festlegen und unabhängig vom Log-Level zum Logger hinzufügen, wie unten zu sehen ist.
Konfiguration
Im folgenden Beispiel für eine Logback-Konfiguration habe ich meiner Datei logback.xml zwei Appender hinzugefügt.
Der erste Appender gibt alle Log-Zeilen auf der Konsole aus, einschließlich der Marker, die ich hinzugefügt habe. Der zweite Appender filtert anhand des Markers SECURITY ausschließlich die sicherheitsrelevanten Logs heraus und schreibt sie täglich in eine separate Security-Logdatei.
Log4j2
Für die Verwendung müssen Sie die Pakete log4j-api und log4j-core einbinden, wie unten gezeigt.
Marker
Das Erstellen und Hinzufügen von Markern funktioniert ähnlich wie im Logback-Beispiel. Diesmal verwenden wir jedoch den spezifischen Log4j-Manager, um den Logger und den Marker zu erstellen.
Konfiguration
Ähnlich wie bei der Logback-Konfiguration habe ich eine Konfiguration für Log4j2 mit zwei Appendern erstellt. Darin wird das Security-Log anhand der Marker in einer separaten Datei gespeichert. Diese Konfiguration muss sich in der Datei log4j2.xml im Classpath befinden.
Logging für verteilte Systeme
Bei verteilten Systemen sollten Sie nicht für jeden Service in eine einzelne Datei schreiben. Nutzen Sie stattdessen einen zentralen Speicherort. Dort gespeicherte Logs lassen sich leichter miteinander korrelieren und potenzielle Probleme einfacher finden.
Profi-Tipp:Bei der Implementierung von zentralisiertem Logging ist es oft sinnvoll, Log-Zeilen als JSON zu formatieren. So lassen sich die Daten einfacher und schneller indexieren und durchsuchen.
Ergänzend zum zentralisierten Logging sollten Sie auch aktives Monitoring und Alerts für Ihre Log-Zeilen in Betracht ziehen. Viele verschiedene Produkte können auf Basis Ihrer Logs Echtzeitdiagramme erstellen und Sie automatisch benachrichtigen, wenn vordefinierte Schwellenwerte überschritten werden.
Fazit
Logging ist keine Aufgabe, die man einfach nebenbei erledigt. Es ist entscheidend, genau zu prüfen, was und wann Sie protokollieren und wie Sie Ihre Logs nutzen, um schnell recherchieren oder eingreifen zu können. Prävention ist zwar besser als Nachsorge, doch es kann immer jemand in Ihr System eindringen. Dann wollen Sie weiteren Schaden verhindern.
Falls dieser Ernstfall eintritt, stellen Sie sicher, dass Ihre Logs Ihnen helfen können!
Starten Sie mit Capture the Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Herausforderungen lösen.



