Jackson-Databind und das Problem mit CVE-2017-7525

Wird Jackson-Databind als 3rd-Party-Lib in einem Projekt eingebunden, oder es ist über eine transitive Abhängigkeit mit im Projekt, dann melden Analysetools umgehend ein Finding. Aber in welchem Fall ist Jackson-Databind tatsächlich gefährlich?

Hintergrund

Jackson-Databind wird verwendet, wenn Json Strings deserialisiert werden. Die Deserialisierung ist etwas komplizierter als die Serialisierung, was daran liegt, dass beim Serialisieren die Klassen noch bekannt sind. Werden abstrakte Klassen oder Interfaces verwendet, ist das beim Serialisieren egal – der Json String ist immer der gleiche. Anders herum muss beim Deserialisieren, wenn der Json String wieder in reale Objekte gemappt wird, eine Entscheidung für konktete Klassen gefällt werden, die auch instantiiert werden können.

Damit Jackson bei der Deserialisierung konkrete Klassen ermitteln kann, wird mit Annotations gearbeitet, über die die Klassen angegeben werden können:

{ "phone" : {
"@class" : "package.InternationalNumber",
"areaCode" : 555,
...
}
}

Auf Seite der Java-Klasse wird als Gegenstück z.B. mit @JsonTypeInfo gearbeitet, damit Jackson die richtige Klasse findet. Es gibt hier eine Vielzahl an Annotations, die bei komplexeren Strukturen helfen sollen.

Die Gefahr

Die Sicherheitslücke besteht dann, wenn der Json String so manipuliert werden kann, dass bei der Deserialisierung eine Klasse instanziiert wird, die Schaden anrichten kann (Denial of Service, Sensitive Data Exposure, Data Manipulation, …). Solche Klassen werden in diesem Kontext als “Gadgets” bezeichnet.

Eine Gadget-Klasse muss allerdings im Klassenpfad der Anwendung liegen, weshalb zunächst unlogisch erscheint, dass damit Schaden angerichtet werden kann. Es gibt aber verschiedene polymorphe Klassen, über die generischer Code eingeschleust werden kann, der dann zur Ausführung kommt. Jackson hat deshalb bereits eine Blacklist an bekannten Gadget-Klassen, die bei der Deserialisierung nicht ausgeführt werden. Allerdings kommen immer neue kreative Varianten dazu, so dass naturgemäß eine Blacklist kein vollkommener Schutz sein kann.

Voraussetzungen für erfolgreichen Angriff

  1. Die Anwendung akzeptiert Json von Clients, das manipuliert werden kann. 
    • Bei der Kommunikation zwischen 2 Anwendungen, die sich in einer Trustzone befinden, sollte diese Gefahr nicht gross sein, da darauf vertraut wird, dass keine bösartigen und manipulierten Json Strings verwendet werden.
    • Wurde die Trustzone allerdings kompomittiert, dann fällt dieses Argument, so dass man auch bei interner Kommunikation weitere Maßnahmen vorsehen sollte.
  2. Die Anwendung beinhaltet im Classpath mindestens 1 Gadget-Klasse, mit der ein Angriff ausgeführt werden kann.
    • Da in einer Anwendung meist sehr viele Klassen über transitive Abhängigkeiten enthalten sind, sind auch viele bekannte Gadget-Klassen verfügbar. Selbst im JDK existieren Klassen, die als Gadgets missbraucht werden können.
    • Aus diesem Grund trifft auch diese Voraussetzung streng genommen immer zu.
  3. Die Anwendung hat aktives polymorphes Typehandling für Felder mit dem Type Object aktiviert (oder andere allgemeine Typen wir Serializable, Comparable, …)
    • Dies wird im Code über die Methode org.codehaus.jackson.map.ObjectMapper.enableDefaultTyping() aktiviert
  4. Die Anwendung verwendet Jackson-Databind in einer Version, die (noch) keine fragwürdige Gadget-Klassen blockiert via Blacklisting.
    • Ist die Jackson-Version aktuell, dann ist es sehr schwer, aber nicht ausgeschlossen, Gadget-Klassen zu finden, die einen Angriff zulassen.

Da (1) und (2) nie komplett ausgeschlossen werden können, sollten wir uns auf (3) und (4) fokussieren.

Folgendes ist noch festzustellen für die beiden Ausprägungen:

  1. Polymorphie: Anhand des Parameters valueType wird über die Annotation JsonTypeInfo definiert, welche “Zielklasse” bei der Deserialisierung verwendet werden soll. Das ist entweder diese übergebene Klasse valueType selbst oder wird wiederum durch Annotationen dieser Klasse bestimmt. Durch die Annotation JsonTypeInfo kann definiert werden, dass die tätsächlich instanzierte Klasse, durch einen Parameter innerhalb des JSON-Textes vorgegeben wird, was bedeutet, dass der Sender des JSON-Textes die Entscheidung trifft. Die Entscheidung ist nicht völlig frei: die instanzierte Klasse, muss eine Erweiterung der Klasse valueType sein. Jackson bietet dazu mehrere Möglichkeiten. Die Kritische ist die, bei der Klassenname, bzw. ein Teil des Klassennamens, als JSON-Inhalt definiert/ausgewertet wird.
  2. DefaultTyping: unbestimmte/generische Attribute – beispielsweise von Type Tattr Object – können bei eingeschaltetem DefaultTyping mit Objekten befüllt werden, deren konkreter Typ Tconc durch den JSON-Inhalt bestimmt wird. Im Falle des Attributstyps Tattr Object unterliegt Tconc lediglich der Einschränkung, dass Tconc im Klassenpfad zu finden sein muss.


Ein Beispiel für eine gefährliche Codestelle ist folgende:

public class Person {
@JsonTypeInfo(use = Id.CLASS)
public Object phone;
}

Hier wird über @JsonTypeInfo der Klassenname angegeben, so dass dieser in der Json Struktur über die @class Annotation angegeben werden kann. Ist DefaultTyping aktiviert, dann kann an Stelle des Typs Object eine Gadget-Klasse treten, die der Angreifer angibt.

Prävention

  1. Immer die neueste Jackson-Databind Version verwenden
    • denn diese enthält die vollständigste Liste der gefährlichen Gadget-Klassen in der Blacklist
    • das ist kein perfekter Schutz, aber das mindeste was man tun sollte
  2. Default Typing vermeiden
    • statt dessen explizit die Klassen angeben, die bei der Deserialisierung verwendet werden sollen
  3. Allgemeine Klassen wie Object, Serializable, … vermeiden in den Objekten, die übertragen werden
    • dadurch wird vermieden, dass beliebige Klassen für den Angriff verwendet werden können
  4. Möglichst “type name” verwenden und nicht classname als Type-Id
    • @JsonTypeInfo(use = Id.NAME)  anstatt  @JsonTypeInfo(use = Id.CLASS)

Referenzen

Statische Codeanalyse mit Xanitizer

Wenn man eine Webanwendung nach Sicherheits-Schwachstellen untersuchen will, dann bietet sich neben der dynamischen Analyse – Pentesten – vor allem die statische Codeanalyse an. Doch was steckt hinter den beiden Ansätzen und worin unterscheiden sie sich?

Pentesten ist eine Black-Box Analyse, bei der man die Interna der Anwendung nicht kennt. Man greift die Anwendung so an, wie es ein Angreifer auch tun würde tut. Auch wenn diese Methodik seine Berechtigung hat und wichtiger Bestandteil der Sicherheitsanalyse ist, gegenüber der statischen Codeanalyse hat sie einige Nachteile, denn viele Schwachstellen sind nicht so einfach zu erkennen. Oft ist es sogar Glücksache bzw. eine Frage des Geschicks des Pentesters, ob gut versteckte Schwachstellen in all ihren speziellen Bedingungen auch gefunden werden.

Bei der statischen Codeanalyse benötigt man den Quellcode der Anwendung. Es kann auch reichen, die Binaries der Anwendung zu haben und diese zu dekompilieren. Der Quellcode der Anwendung wird dann gezielt nach Schwachstellen untersucht, und zwar zunächst an den Stellen, wo sie üblicherweise auftreten: bei der Authentizitierung, dem Berechtigugsmanagement, und den nach außen exponierten Schnittstellen.

Die statische Codeanalyse ist also eine White-Box Analyse, bei der man sich die Logik des Programms anschauen kann. Dort gefundene Schwachstellen könnten dann in Kombination mit den Pentests viel effektiver gefunden werden. Ich empfehle sogar, beide Techniken zu kombinieren, aus mehreren Gründen:

  • Beweisführung
    • Beweisen der Gültigkeit des Findings
    • False Positives werden dadurch aussortiert (fälschlich gefundene Schwachstellen)
  • Nachvollziehbarkeit
    • Das Dev-Team kann dadurch besser nachvollziehen, dass diese Codestelle eine Schwachstelle ist
    • Die Wirksamkeit von Patches vom Dev-Team kann dadurch bewiesen werden

Tools

FindSecBugs

Es gibt verschiedene Tools für die statische Codeanalyse. Am einfachsten sind Pattern-basierte Tools wie FindSecBugs – einem Plugin für das weit verbreitete SpotBugs. Die Ergebnisse sind ganz ordentlich.

Xanitizer

Weit mehr Abdeckung kann man mit einer gezielteren Datenflußanalyse erreichen, wie es mit Xanitizer möglich ist. Man hat damit mehr Aufwand, als nur einen Scanner über den Code laufen zu lassen, aber auch bessere Resultate. Die Idee dahinter ist, dass sämtliche Benutzereingaben simuliert und durch den Code verfolgt werden. Benutzereingaben müssen generell als Gefahrenpotential, als böse eingestuft werden. Werden diese nicht gefiltert und damit neutralisiert, dann muss davon ausgegangen werden, dass dies ein Einfallstor für Angriffsvektoren ist.

Die verschiedenen Stationen, die die Benutzereingaben, in der Anwendung durchlaufen, werden von Xanitizer in 3 Kategorien eingeteilt:

  • Sources
  • Sinks
  • Sanitizer

Als Source wird die Station bezeichnet, wo Daten von außen ins System eindringen. Also Schnittstellen aller Art, sowohl von der Benutzerschnittstelle her, als auch technische Schnittstellen, beispielsweise bei einem Web-Service. Daten die hier ankommen, werden als tainted bezeichnet, also als schmutzig, die noch “gewaschen” werden müssen.

Sinks sind die Datensenken, wohin die Daten letztendlich wandern. Wenn die Daten immer noch tainted sind, wenn sie bei den Sinks ankommen, dann ist dies ein Finding und wird im Report als Schwachstelle angezeigt.

Damit die Daten “gewaschen” werden, braucht es die genannten Filter, die Sanitizer, die die potenziell schadhaften Daten neutralisieren. Angriffsvektoren die solche Schwachstellen ausnutzen, werden von den Sanitizern sozusagen außer Gefecht gesetzt.

Von Haus aus erkennt Xanitizer bereits viele dieser Elemente im Quellcode vollautomatisch, allerdings muss meist auch noch nachjustiert werden, damit insbesondere Sourcen erkannt werden. Sie sind die wichtigsten Elemente bei der Datenflußanalyse, da sie die Eintrittspunkte ins System repräsentieren.

Insgesamt wird eine gute Analyse durch Xanitizer ermöglicht, die allerdings einiges an Aufwand mit sich bringt. Belohnt wird man aber durch brauchbare Ergebnisse und das gute Gefühl, die Sicherheit in seiner Anwendung deutlich zu verbessern.

Wie man genau mit Xanitizer arbeitet und ihn in den Software-Development-Life-Cycle (SDLC) einbindet und so automatisiert und regelmäßig Sicherheitsanalysen durchführen kann, werde ich in weiteren Blogbeiträgen zeigen.

Neues YT-Video: Broken Authentication

Gerade eben habe ich mein neues YouTube-Video veröffentlicht. Es ist aus der Secure Coding Reihe zum Platz 2 der OWASP-Top10 “Broken Authentication – Fehler in Authentifizierung und Session-Management.

Mich würde sehr interessieren, was Ihr darüber denkt. Konstruktive Kritik oder auch nur kurzes Feedback ist also willkommen. Entweder hier, oder auch bei YT als Kommentar.

Sicheres Passwort?

Wann ist ein Passwort eigentlich sicher?

Als Benutzer werden wir dazu erzogen, komplexe Passwörter zu verwenden. Aus gutem Grund werden zu einfache Passwörter zumeist abgelehnt, da Passwörter die in einem Wörterbuch vorkommen, innerhalb weniger Sekunden geknackt werden können durch einen sogenannten Wörterbuch-Angriff. Auch ein “123” davor oder dahinter bringen da nicht viel, da man solche Varianten dabei gleich mit prüft.

Wenn nicht mindestens Gross- und Kleinbuchstaben, sowie Zahlen und Sonderzeichen verwendet werden, kommt man bei immer weniger Systemen weiter bei der Passwortauswahl. Leider wird oft auch nur ein roter Balken angezeigt, zusammen mit einer Warnung. Passwörter mit weniger als 12 Zeichen gelten aber auch als unsicher, wenn sie diese Kriterien erfüllen.

Lang soll es also sein. Mehr als 12 Zeichen. Und es darf nicht in Wörterbüchern vorkommen.

Alles Nutella?

Nutella findet es anscheinend sicher genug, ein 7-stelliges Passwort zu verwenden. In einem Tweet rufen sie dazu auf, mit “Nutella” seine Geheimnisse zu sichern. Ein schlechter Scherz, dem leider vermutlich zu viele folgen:

Die am häufigsten verwendeten Passwörter sind eine Katastrophe. Mehr als 5 Millionen gekaperte Passwörter wurden durch SplashData statistisch ausgewertet. Zum fünften Mal in folge wurde “123456” als das am meisten verwendete Passwort des Jahres ermittelt, gefolgt von “password”. 

Hier die aktuelle Top-10 Liste:

  1. 123456
  2. password 
  3. 123456789
  4. 12345678
  5. 12345
  6. 111111
  7. 1234567 
  8. sunshine
  9. qwerty
  10. iloveyou

Den meisten Benutzern ist anscheinend nicht klar, dass sie durch derartigen Leichtsinn riskieren, Opfer von automatisierten Angriffen zu werden. Es kann sehr schnell passieren, dass ein Erpressungs-Trojaner dann die Dateien auf dem eigenen PC verschlüsselt, so dass sie nicht mehr zu lesen sind. Nur durch Zahlung von einigen tausend Euro bekommt man seine Dateien dann wieder entschlüsselt, zusammen mit dem unguten Gefühl, nicht mehr Herr seiner Privatsphäre zu sein.

Doch was tun, wenn man sich für unzählige Konten Passwörter merken muss, die man dann auch noch regelmäßig ändern soll? Auf gar keinen Fall sollte man übrigens das gleiche Passwort für mehrere Konten verwenden, denn ist eines der Konten kompromittiert, haben die Angreifer dann auch gleich Zugriff auf die anderen Konten, wo das gleiche Passwort gilt. “Credential Stuffing” nennt man einen solchen Angriff, bei dem bekannt gewordene Zugangsdaten bei anderen Webseiten ausprobiert werden. Die Erfolgsrate ist dabei relativ hoch.

Was also tun?

Solange wir uns mit Benutzernamen und Passwörtern authentifizieren müssen, sollten wir Passwortmanager-Programme verwenden. Dort werden die Passwörter sicher verwaltet, und durch Copy&Paste in die Webanwendung übernommen. Das hat den Vorteil, dass wir sehr lange und komplexe Passwörter verwenden können, die kein Mensch von Hand eintippen möchte. Es spricht also nichts dagegen, ein 100-stelliges Passwort zu verwenden, wenn das von der Webanwendung unterstützt wird. Ein Brute-Force-Angriff wird das nicht so schnell knacken können, so dass die Angreifer weiterziehen werden, und es mit anderen Opfern probieren wird, die es noch nicht kapiert haben.

Folgende Passwortmanager-Programme sind gängig:

  • KeePass
  • LastPass
  • Dashlane
  • 1Password
  • StickyPassword
  • Steganos Passwort-Manager

Sichererer?

Noch besser als sehr gute Passwörter zu verwenden ist, wenn man neben diesen auch noch ein weiteres Merkmal verwendet, wir ein Token, das z.B. über eine Authenticator-App generiert wird. Multifakor-Authentifizierung ist der Fachbegriff dafür. Dadurch ist es für Angreifer nicht mehr möglich, durch abgefischte Passwörter den Account zu übernehmen. Im Online-Banking Bereich setzt sich das mehr und mehr durch, auch wenn viele Banken nach wie vor SMS als 2. Faktor verwenden. Dass das nicht sicher ist, darüber habe ich in einem vorigen Post berichtet.

UPnProxy – oder zu was Plug and Play/Pray noch so alles missbraucht werden kann

Wer erinnert sich noch an “Universal Plug and Play”? Es wurde von Microsoft in den 90ern erfunden, um die lästigen Treiber-Installationen unter Windows zu vereinfachen. Die Idee dabei war, dass sich Geräte über Port 1900 von ganz alleine finden können, und der Benutzer gar nichts mehr tun muss, um beispielsweise seinen neuen Joystick zu verwenden. Also Einstecken und Spielen. Die Idee dahinter war also wie so oft eine Gute, aber in der Praxis lief das nicht immer (um nicht zu sagen selten) reibungslos, so dass sich schnell der Begriff “Plug and Pray” verbreitete, der dieses Protokoll verspotten sollte.

Da dieses Protokoll keinerlei Sicherheit beinhaltet, da ihm Authentifizierung und Autorisierung fehlen, ist es ausschließlich für das interne LAN gedacht. UPnP darf also unter keinen Umständen ins offene Internet exponiert werden, denn dann werden Tür und Tor geöffnet für Neugierige und Angreifer. “Hey, kommt in mein LAN, ich zeige Euch gerne alles was ich habe” – das wäre die native Botschaft von einem ins Internet losgelassene UPnP.

Man sollte meinen, dass es deshalb klar sein sollte, dass UPnP niemals ins Internet losgelassen werden sollte, da es so ganz ohne Sicherheitsmechanismen nur für absolut vertrauenswürdige Umgebungen gemacht ist. Leider, leider… ist dem nicht so. Im Gegenteil. Viele namhafte Hersteller von Routern bieten ein “Feature” an: “Expose UPnP to WAN”. Gemäß einer Analyse von Akamai sind bis zu 4,8 Millionen Geräte betroffen.

Ein nicht-versierter Heim-Admin, der dieses Feature aktiviert, würde damit das Unvernünftigste tun, was in der heutigen Zeit in der Internet-Welt denkbar ist. Aber er wird noch schlimmer: Einige der Hersteller haben dieses Feature standardmäßig auch noch aktiviert. Das ist wirklich das Allerletzte – beim Schreiben dieser Zeilen fehlen mir vor lauter Entsetzen fast schon die Worte. Also am besten gleich den eigenen Router zuhause checken, ob dieser ein solches Feature hat und sicherstellen, dass es inaktiv ist.

Die Folge eines über UPnP ins Internet exponierten Routers ist, dass dieser zunächst für Brute-Force-Angriffe auf die Admin-Oberfläche erreichbar ist. Was vorher nicht der Fall war. Es ist nur eine Frage der Zeit und der Qualität des verwendeten Passworts, wie lange dieses dem Brute-Forcing standhält. Üblicherweise nicht besonders lange. Es kommt dann wie es kommen muss: der Router wird übernommen und von den bösen Buben geentert und missbraucht. Für Botnetze und andere Schweinereien.

Ein neuer Trend der kriminellen Machenschaften im Zusammenhang mit Botnetzen ist UPnProxy. Dazu wird einer der Millionen verwundbaren privaten Heimroutern für zur Verschleierung von Angriffen missbraucht, in dem er als Proxy fungiert. Wenn ein Opfer bzw. eine Strafverfolgungsbehörde versucht, einen Angreifer zurückzuverfolgen, dann führt die Route dadurch nicht direkt zum Angreifer, sondern über die verwendeten Proxies, die die Route dadurch zu verschleiern versuchen. UPnProxy ist damit ein weiteres wichtiges Instrument der organisierten Kriminalität, Angriffe noch schwerer zurückzuverfolgen.

Einmal mehr zeigt sich hier, wie ein zunächst gut gemeintes Feature (bzw. Protokoll) missverstanden wird, und durch Unwissenheit und Ignoranz zum Desaster der Internet-Sicherheit wird.

Mehr zu diesem Thema bei Bleeping Computer.

Erste Geldstrafe in Deutschland für fahrlässige Sicherheit in Web-Anwendung

Seit dem die DSGVO in Kraft ist, drohen Geldstrafen für Betreiber von Web-Anwendungen, die fahrlässig mit dem Thema Sicherheit umgehen. Wie heise Security berichtet, wurde deshalb gegen Knuddels.de eine Strafe von EUR 20.000 verhängt, weil Passwörter von Benutzern im Klartext gespeichert wurden. Dies ist nach den Untersuchungen herausgekommen, nachdem ein Hackerangriff erfolgt ist und analysiert wurde. Weitaus größer als die finanzielle Strafe dürfte jedoch die nun stark beschädigte Reputation von Knuddels.de sein, sowie das verlorene Vertrauen bei den 2 Millionen registrierten Usern.

Wie wichtig es ist, Passwörter sicher abzuspeichern, zeigt sich mustergültig an diesem Beispiel. Ist der Zugriff auf die unverschlüsselten Passwörter erst einmal möglich, dann sind zahlreiche Benutzer betroffen und damit kompromittiert. Da es von vielen Personen außerdem gängige Praxis ist, ein und das selbe Passwort auf mehren Portalen zu verwenden, sind durch einen solchen Raub gleich alle Accounts gefährdet, auf denen dieses Passwort gültig ist. Die Aufklärungsarbeit, die dazu bei den Anwendern gemacht werden muss, stößt oft auf taube Ohren. Aus Bequemlichkeit setzen sich Passwort-Management Programme wie KeePass oder LastPass nur sehr schleppend durch, aber sie scheinen der einzige Ausweg zu sein, um auf jeder Webseite ein eigenständiges, genügend komplexes Passwort zu haben.

Der einzig richtige Weg, wie ein Passwort abgespeichert werden muss, ist: überhaupt nicht. Zumindest nicht im Klartext – und auch nicht verschlüsselt. Verschlüsselte Passwörter können nämlich wieder entschlüsselt werden, was bei einer Passwortprüfung überhaupt nicht notwendig ist. Statt dessen sollte nur der Passwort-Hash abgespeichert werden, und zwar mit einem sicheren Hash-Algorithmus, z.B. PBKDF2 oder bcrypt. Die Prüfung, ob das vom Benutzer eingegebene Passwort dann das Richtige ist, findet folgendermaßen statt: Die Web-Anwendung, die die Benutzereingabe verarbeitet, hasht das Passwort ebenfalls und vergleicht dann nur noch den Hash mit dem Hash aus der Datenbank. Stimmen diese überein, wurde das Passwort richtig eingegeben.

Mehr Informationen über sichere Passwortverwaltung und sichere Programmierung finden sich auf den OWASP-Seiten, und können auch auf einer Secure Coding Schulung gelernt werden.