MongoDB-Anwendungen haben echt große Sicherheitsrisiken, wenn Benutzereingaben nicht überprüft werden. nosql-Injection-Angriffe können unbemerkt in deine Datenbank eindringen, sensible Daten offenlegen und die Integrität des Systems gefährden. Dieser Leitfaden zeigt bewährte Strategien, um Eingaben zu bereinigen, Datenbankabfragen zu sichern und einen robusten Schutz gegen Injection-basierte Bedrohungen aufzubauen.
Was ist eine nosql-Injection?
Eine nosql-Injection passiert, wenn Angreifer nicht richtig überprüfte Benutzereingaben nutzen, um die Datenbankabfragelogik zu manipulieren. Durch das Einschleusen von bösartigen Payloads können Angreifer Authentifizierungsmechanismen umgehen, nicht autorisierte Daten extrahieren oder Anwendungssicherheitskontrollen umgehen.
Im Gegensatz zu SQL-Injection, die Schwachstellen in der stringbasierten Abfragekonstruktion ausnutzt, nutzt nosql-Injection flexible Datenstrukturen und dynamische Abfragen. Das ist besonders gefährlich, wenn Apps nicht genau typisierte Eingaben wie interface{} oder map[string]interface{} ohne ordentliche Überprüfung akzeptieren.
Warum MongoDB anders ist
MongoDB-Abfragen werden mit BSON (Binary JSON) – also strukturierte Schlüssel-Wert-Paare – statt mit einfachen Strings. Dieses Design vermeidet viele typische Injektionsrisiken, weil Abfragen nicht durch Zeichenfolgenverkettung zusammengesetzt werden.
Wenn Benutzereingaben aber ohne ordentliche Überprüfung direkt in diese BSON-Objekte eingebettet werden, können Angreifer MongoDB-Operatoren wie $ne, $gtoder $or , um die Logik der Abfrage zu ändern.
Beispiel: Operator-Injektion in Go
filter := bson.M{"name": inputName}
collection.Find(ctx, filter)
Wenn inputName ein einfacher String wie „Joe” ist, ist es sicher. Aber wenn dein Code map[string]interface{} oder rohes JSON zulässt, könnte ein Angreifer Operatorobjekte wie die folgenden einschleusen:
{ "$ne": null }
Diese Nutzlast ändert die Abfragelogik und findet jetzt jedes Dokument, in dem der Name vorkommt, anstatt nach einem bestimmten Wert zu suchen – und umgeht so die vorgesehenen Zugriffskontrollen der App.
Unsichere Muster und häufige Fallstricke erkennen
1. Implizites Vertrauen in Anfrage-Body
Das direkte Parsen von Request-Bodies in BSON-Maps schafft einen Injektionspfad, über den Angreifer bösartige Abfrageoperatoren und komplexe logische Konstrukte direkt in Datenbankoperationen einbetten können.
// Unsafe
var filter bson.M
_ = json.NewDecoder(req.Body).Decode(&filter)
Stattdessen solltest du nur bekannte Felder und Typen analysieren:
type QueryInput struct {
Name string json:"name" validate:"required"
}
2. Akzeptieren von losen Typen
Injection-Schwachstellen tauchen oft auf, wenn APIs zu freizügige Datentypen wie interface{} oder generische Maps akzeptieren . Diese flexiblen Strukturen können eingebettete MongoDB-Operatoren oder bösartige Objektkonstrukte enthalten, die die beabsichtigte Abfragelogik umgehen.
Verwendest du lose Befestigungen nur, wenn es echt nötig ist, und machst eine strenge Überprüfung, wenn es nicht anders geht. Definiere stattdessen klare Datenstrukturen, die zu deinem erwarteten Eingabeformat passen, und lege akzeptable Werte fest.
3. JSON in Abfragezeichenfolgen oder Abfrageoperatoren
APIs, die dynamische Filterfunktionen über URL-Abfrageparameter oder Suchendpunkte anbieten, sind ein attraktives Ziel für Angriffe. Angreifer versuchen oft, diese Schnittstellen anzugreifen, indem sie JSON-codierte Operatoren und bedingte Logik direkt in Abfragezeichenfolgen einbauen. Das verwandelt normale Filterparameter in bösartige Datenbankoperationen:
GET /search?filter={"price":{"$gt":0}}
Ohne strenge Eingabevalidierung können Angreifer mit diesem Ansatz Abfragestrukturen manipulieren und Sicherheitskontrollen umgehen, wodurch möglicherweise nicht autorisierte Daten offengelegt oder Berechtigungen über die vorgesehenen Zugriffsebenen hinaus erweitert werden.
Abschwächung:
- Führ Allowlists für Felder und Operatoren ein, um Abfrageparameter auf vordefinierte, sichere Werte zu beschränken.
- Pack alle Werte, die von Benutzern angegeben werden, explizit in $eq-Operatoren ein, wenn du Datenbankfilter erstellst, um das Einschleusen von anderen Operatoren zu verhindern.
4. Erweitern logischer Abfragen mit Injektion
Apps, die es den Nutzern erlauben, logische Operatoren wie $or, schaffen Möglichkeiten für Angriffe durch Abfrageerweiterung. Angreifer können zusätzliche bedingte Ausdrücke in diese Operatoren einfügen, wodurch die Abfragesemantik grundlegend verändert wird und Authentifizierungsprüfungen oder Datenzugriffsbeschränkungen möglicherweise umgangen werden können.
filter := bson.M{
"$or": []bson.M{
{"role": "user"},
{"active": true},
},
}
Wenn die Benutzereingabe direkt die $or -Klausel beeinflussen, können Angreifer eine nicht autorisierte Bedingung einfügen:
{ "$or": [ {"role": "user"}, {"active": true}, {"isAdmin": true} ] }
Diese geänderte Abfrage könnte rollenbasierte Zugriffskontrollen umgehen und so möglicherweise Verwaltungsdaten offenlegen oder unbefugten Benutzern erhöhte Berechtigungen gewähren. Verhindere dynamische Änderungen an logischen Operatoren, indem du eine strenge Eingabevalidierung machst und direktes Benutzer-Eingreifen in die Abfragestruktur vermeidest.
GET /search?filter={"price":{"$gt":0}}
Ohne strenge Eingabevalidierung können Angreifer mit diesem Ansatz Abfragestrukturen manipulieren und Sicherheitskontrollen umgehen, wodurch möglicherweise nicht autorisierte Daten offengelegt werden.
Abschwächung:
- Mach dir Listen mit erlaubten Feldern und Operatoren, und lehne alle Abfrageparameter ab, die nicht in diese vordefinierten Grenzen passen.
- Mach explizite Gleichheitsprüfungen, indem du alle Benutzereingaben in $eq ein, um zu verhindern, dass Vergleichs- oder logische Operatoren ersetzt werden.
JavaScript-Ausführungsfunktionen
MongoDB hat ein paar Funktionen für die Ausführung von JavaScript auf dem Server, die potenzielle Sicherheitsrisiken mit sich bringen können, darunter:
Diese Funktionen sind ein echtes Sicherheitsrisiko und sollten vermieden werden, es sei denn, wichtige geschäftliche Anforderungen machen ihre Verwendung notwendig. Um Missbrauch zu verhindern, deaktiviere Skripting in der MongoDB-Konfiguration:
Für mongod:
--noscripting
Oder über die Konfigurationsdatei:
security:
javascriptEnabled: false
Wende die gleiche Konfiguration auf r an mongos in einer Shard-Bereitstellung.
Die nativen Abfrageoperatoren von MongoDB bieten umfassende Funktionen, die die Ausführung von JavaScript in fast allen Anwendungsfällen überflüssig machen. Vermeide „ “-Klauseln komplett, es sei denn, du hast die volle Kontrolle über die Eingabevalidierung und den Ausführungskontext.
Wie man nosql-Injection verhindert
1. Überprüfe die Eingaben gründlich.
Mach eine strenge Typprüfung, die nur die erwarteten primitiven Datentypen wie Zeichenfolgen, Ganzzahlen oder Boolesche Werte akzeptiert. Lehn alle verschachtelten Objekte, Arrays oder unbekannten Feldnamen ab, die eingebettete Operationen oder bösartige Konstrukte enthalten könnten.
type LoginInput struct {
Username string json:"username" validate:"required,alphanum"
Password string json:"password" validate:"required,min=8"
}
2. Vertraue der Abfragestruktur von Benutzern nicht
Erstell alle Datenbankabfragen mit vordefinierten, anwendungsgesteuerten Feldzuordnungen und Abfragevorlagen. Verhindere, dass Benutzereingaben die Abfragearchitektur, logische Operatoren oder bedingte Strukturen beeinflussen, die die beabsichtigten Datenzugriffsmuster durcheinanderbringen könnten.
filter := bson.M{
"username": input.Username,
"password": input.Password,
}
Vermeide:
// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)
Die meisten MongoDB-Treiber haben stark typisierte Abfrage-Builder, die eine strukturierte Abfragekonstruktion sicherstellen und versehentliche Injektionsschwachstellen verhindern. Nutze lieber diese nativen Schnittstellen, statt rohe Abfragekarten oder BSON-Objekte über Anwendungsendpunkte freizugeben.
filter := bson.M{
"username": input.Username,
"password": input.Password,
}
Vermeide:
// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)
3. Block-Injektion von MongoDB-Operatoren
Verhindere, dass benutzergesteuerte Eingaben als Abfrageoperatoren oder logische Konstrukte funktionieren. Behandle alle Benutzerdaten als reine Werte und nicht als ausführbare Abfragekomponenten.
Stattdessen:
filter := bson.M{
"status": input.Status,
}
Verwendung:
filter := bson.M{
"status": bson.M{"$eq": input.Status},
}
Dieser Ansatz sorgt für eine strenge Gleichheitsprüfung und verhindert die Ausführung von eingefügten Operatoren wie $ne, $inoder $regex oder andere logische Modifikatoren, die die beabsichtigte Abfragelogik umgehen könnten.
4. Benutzer von Datenbanken mit möglichst wenigen Rechten ausstatten
Richte die Datenbankverbindungen der Anwendung mit Benutzerkonten ein, die nur die minimalen Berechtigungen haben, die für die geplanten Vorgänge nötig sind. Vermeide die Verwendung von Anmeldeinformationen auf Administratorebene aus Anwendungskonfigurationen, um mögliche Schäden durch erfolgreiche Injektionsangriffe zu verhindern.
5. Überwachen und testen
Mach umfassende Protokollierung, um ungewöhnliche Abfragemuster zu erkennen, und leg regelmäßige Protokolle für Sicherheitstests fest. Überprüfe die Endpunktsicherheit, indem du Injektionsangriffe mit fehlerhaften Payloads versuchst, wie zum Beispiel:
{ "$ne": null }
Schau mal, ob die App das ablehnt.
Zu berücksichtigende Testfälle:
- Objekte statt Strings: { „username”: { „$ne”: null } }
- Arrays statt Skalare: { „roles”: [ { „$gt”: „” } ] }
- Operatoren als Abfragewerte: { „field”: { „$regex”: „.*” } }
Checkliste Zusammenfassung
- Eingabevalidierung: Strenge Datentypen durchsetzen, Formate überprüfen und unerwartete Felder ablehnen.
- Abfrageaufbau: Erstelle alle Abfragen mit vordefinierten Schemata und anwendungsgesteuerten Vorlagen.
- Schutz des Bedieners: Blockier MongoDB-Operatoren in Benutzereingaben, indem du Werte in $eq einschließt oder typisierte APIs verwendest.
- Server-side JavaScript: Entferne $where-Klauseln und deaktiviere die JavaScript-Ausführung in Produktionskonfigurationen.
- DB-Zugriffskontroll: Richte App-Verbindungen mit so wenig Berechtigungen wie möglich ein und vermeide dabei Admin-Zugangsdaten.
- Test- und Überwachungs: Mach regelmäßig Injektionstests und logg ungewöhnliche Abfragemuster.
Abschließende Gedanken
Nosql-Injection-Schwachstellen kann man komplett vermeiden, indem man sich an sichere Programmierpraktiken hält. Durch strenge Eingabevalidierung, strukturierte Abfrageerstellung und umfassende Sicherheitskontrollen können Entwickler die Flexibilität und Leistung von Anwendungen aufrechterhalten und gleichzeitig Injektionsangriffe verhindern.
Um erfolgreich zu sein, musst du den kompletten Datenfluss deiner Anwendung verstehen – von der ersten Anfrage bis zur endgültigen Ausführung der Abfrage. Mach bei allen Eingabequellen einen Zero-Trust-Ansatz, setz Validierung an den Systemgrenzen ein und leg Wert auf defensive Programmierprinzipien in deinem ganzen Technologie-Stack.
Häufig gestellte Fragen
Warum ist nosql-Injection ein Risiko, wenn MongoDB BSON statt Strings nutzt?
Die Injektion kann immer noch passieren, bevor das BSON-Objekt erstellt wird. Wenn Benutzereingaben ohne Überprüfung in flexible Typen wie map[string]interface{} oder interface{} umgewandelt werden, können Angreifer MongoDB-Operatoren wie $ne oder $or einschleusen und die Abfragelogik manipulieren.
Ist es okay, einen Request-Body direkt in ein bson.M oder map[string]interface{} zu decodieren?
Nein. Dadurch können Nutzer beliebige Abfrageoperatoren einfügen. Ordne Anfragedaten immer strengen Typen zu (z. B. Go-Strukturen) und überprüfe die Eingaben, bevor du Abfragen erstellst.
Was ist falsch daran, $where zu benutzen, wenn die Eingabe überprüft wird?
Auch wenn die Eingabe teilweise validiert ist, führt $where JavaScript auf dem Server aus. Jeder Fehler beim Entkommen oder bei der Validierung kann zu einer Code-Injektion führen. Es ist sicherer, $where komplett zu meiden oder Skripte in deiner MongoDB-Konfiguration zu deaktivieren.
Wie kann ich checken, ob mein Endpunkt für nosql-Injection anfällig ist?
Versuch mal, Nutzdaten wie die folgenden einzuschleusen:
{ "username": { "$ne": null } }
Wenn der Endpunkt eine gültige Antwort zurückgibt oder die Logik umgeht (z. B. Anmeldung), wird die Eingabe nicht richtig überprüft oder eingeschränkt.
Wie kann man in Go am besten sicher Abfragen erstellen?
Benutz typisierte Strukturen für die Eingabe, vermeide die Dekodierung in generische Maps und pack Werte bei Bedarf in $eq. Lass den Benutzer niemals Operatoren definieren oder Teile der Abfrage direkt einfügen.
