FlawOpen

flawopen.com/Referenz/MongoDB NoSQL Injection: wenn Eingaben Abfragen verändern

MongoDB NoSQL Injection: wenn Eingaben Abfragen verändern

Leitfaden zur Datenbanksicherheit

MongoDB führt kein SQL aus; SQL-String-Verkettung ist daher nicht das Problem. Eine NoSQL-Injection kann trotzdem entstehen, wenn eine Anwendung ein nicht vertrauenswürdiges verschachteltes Objekt erwartet, obwohl sie einen Skalar erwartet, und dieses an einen MongoDB-Filter weitergibt. Das ist ein Eingabevalidierungsfehler der Anwendung, keine MongoDB-Server-CVE.

Einfach erklärt: Ein Wert wird zur Regel

Stellen Sie sich ein Formular vor, das nach einem Namen fragt, aber das ganze Ablageanweisungen im Feld akzeptiert. Die Datenbank befolgt dann die Anweisungen, statt einen Namen zu vergleichen. Prüfen Sie den erwarteten Werttyp und erstellen Sie die Suchregel selbst.

Vertrauensgrenze: vom Request-JSON zum MongoDB-Filter

Abfragefilter
BSON-Dokument, das MongoDB als Feldvergleiche und gegebenenfalls ausdrücklich enthaltene Abfrageoperatoren interpretiert.
Operator-Injection
Die Anwendung übernimmt eine vom Benutzer kontrollierte Struktur an einer Stelle, an der ein einzelner Literalwert erwartet wird.
Skalarvalidierung
Typ, Länge und zulässiges Format prüfen, bevor die Eingabe einen Datenbankvorgang beeinflussen kann.
Projektion
Serverseitig ausgewählte Feldliste, die versehentliche Datenoffenlegung begrenzt.

So entsteht der Fehler

1

Der Endpunkt erwartet einen Skalar

Der API-Vertrag definiert username als String; ein JSON-Parser kann jedoch auch Arrays, Objekte, Booleans und null liefern.

2

Die Anwendung überspringt die Typprüfung

Der Handler setzt den geparsten Wert direkt in einen serverseitig erstellten Filter ein. Ein Objekt bleibt dadurch Abfragestruktur, statt als literaler String behandelt zu werden.

3

MongoDB wertet die übergebene Struktur aus

Enthält das verschachtelte Dokument Abfrageoperatoren, kann das Prädikat von der beabsichtigten exakten Wertprüfung abweichen. Betroffene Datensätze hängen von der Abfrage und den Autorisierungsprüfungen der Anwendung ab.

4

Die Antwort bestimmt die Offenlegung

Zurückgegebene Felder und Datensatzanzahl hängen von Projektion, Endpunkt und Rechten des Datenbankkontos ab. Das belegt für sich allein weder eine Umgehung der Authentifizierung noch Zugriff auf die gesamte Datenbank.

Umfang und Belege

Die offizielle MongoDB-Treiberdokumentation beschreibt diese Grenze, wenn ein Endpunkt ungeprüftes JSON in BSON umwandelt und als Filter nutzt. Dieser Leitfaden zeigt den Fehler auf Anwendungsebene. Er behauptet weder, dass jede MongoDB-Installation betroffen ist, noch nennt er eine Server-CVE oder beschreibt einen Authentifizierungs-Bypass.

Unsichere und gehärtete Node.js-Muster

VULNERABLE — UNVALIDATED VALUE ENTERS FILTER
app.post("/users/lookup", async (req, res, next) => {
  try {
    // The route expects a string, but req.body.username is untrusted JSON.
    const user = await users.findOne({ username: req.body.username });
    res.json(user ? { username: user.username } : null);
  } catch (error) {
    next(error);
  }
});
HARDENED — VALIDATE SHAPE, BUILD FILTER, VERIFY HASH
const loginSchema = z.object({
  username: z.string().trim().min(1).max(128),
  password: z.string().min(1).max(1024)
}).strict();

app.post("/login", async (req, res, next) => {
  try {
    const parsed = loginSchema.safeParse(req.body);
    if (!parsed.success) return res.sendStatus(400);

    const { username, password } = parsed.data;
    // The application owns the filter key; input supplies only a string value.
    const user = await users.findOne(
      { username },
      { projection: { _id: 1, username: 1, passwordHash: 1 } }
    );
    const passwordMatches = user &&
      await argon2.verify(user.passwordHash, password);
    if (!passwordMatches) return res.sendStatus(401);

    return res.sendStatus(204); // Session creation is application-specific.
  } catch (error) {
    next(error);
  }
});

Der gehärtete Ablauf weist Felder zurück, die keine Zeichenketten sind, bevor auf die Datenbank zugegriffen wird. Er akzeptiert keine vom Client gelieferten Filterobjekte, erstellt den festen Filterschlüssel im Anwendungscode, gibt nur ausgewählte Felder zurück und prüft nach dem Abruf des Benutzers den Passwort-Hash. Im Beispiel steht z für Zod, users für die MongoDB-Collection und argon2 für eine konfigurierte Passwort-Hashing-Bibliothek; die Sitzungserstellung ist bewusst nicht enthalten.

Prüfungen für die Korrektur

Primärquellen

Weitere Sicherheitsleitfäden:Sicherheitsverzeichnis öffnen →
Siehe auch SQL-Injection (CWE-89): Funktionsweise und Schutz in jeder Sprache — flawopen.com Können auch numerische IDs SQL Injection verursachen? Was ist eine parametrisierte Abfrage? Ist Prisma $queryRaw vor SQL-Injection sicher? Ist String-Interpolation in Rails where() sicher? Ist Sequelize query() vor SQL-Injection sicher? Ist SQLAlchemy text() vor SQL-Injection sicher?