Ga naar hoofdinhoud

SQL/NoSQL-injectieaanvallen in MongoDB voorkomen

Beveilig MongoDB tegen NoSQL-injectie door input te valideren, queries te beveiligen en in te zetten op defense-in-depth. Leer aanvals­patronen en preventie in deze gids.
· 6 min lezen

Verken met AI

MongoDB-applicaties lopen serieuze veiligheidsrisico’s wanneer gebruikersinput niet gevalideerd wordt. NoSQL-injectieaanvallen kunnen ongemerkt je database binnendringen, gevoelige data blootleggen en de integriteit van je systeem ondermijnen. Deze gids laat beproefde defensieve strategieën zien om input te schonen, databasequeries te beveiligen en robuuste bescherming op te bouwen tegen injectiegebaseerde dreigingen.

Wat is NoSQL-injectie?

NoSQL-injectie treedt op wanneer aanvallers onvoldoende gevalideerde gebruikersinput misbruiken om de logica van databasequeries te manipuleren. Door kwaadaardige payloads te injecteren kunnen ze authenticatiemechanismen omzeilen, ongeautoriseerde data extraheren of beveiligingscontroles van de applicatie ondermijnen.

In tegenstelling tot SQL-injectie, dat kwetsbaarheden in stringgebaseerde queryconstructie uitbuit, maakt NoSQL-injectie misbruik van flexibele datastructuren en dynamische queries. Dit is vooral gevaarlijk wanneer applicaties los getypte input accepteren zoals interface{} of map[string]interface{} zonder de juiste validatie.

Waarom MongoDB anders is

MongoDB-queries worden opgebouwd met BSON-objecten (Binary JSON)—gestructureerde key-valueparen—in plaats van ruwe strings. Dit ontwerp voorkomt veel traditionele injectierisico’s omdat queries niet via stringconcatenatie worden samengesteld.

Maar als gebruikersinput direct in deze BSON-objecten wordt opgenomen zonder goede validatie, kunnen aanvallers MongoDB-operatoren zoals $ne, $gt of $or injecteren om de querylogica te veranderen.

Voorbeeld: operatorinjectie in Go

filter := bson.M{"name": inputName}
collection.Find(ctx, filter)

Als inputName een gewone string is zoals "Joe", dan is het veilig. Maar als je code map[string]interface{} of ruwe JSON toestaat, kan een aanvaller operatorobjecten injecteren zoals:

{ "$ne": null }

Deze payload transformeert de querylogica en matcht elk document waar de naam bestaat in plaats van te filteren op een specifieke waarde—waardoor de beoogde toegangscontroles van de applicatie effectief worden omzeild.

Onveilige patronen en valkuilen herkennen

1. Impliciet vertrouwen in request bodies

Het direct parsen van request bodies naar BSON-maps creëert een injectieroute waarbij aanvallers kwaadaardige query-operatoren en complexe logische constructies rechtstreeks in database­operaties kunnen opnemen.

// Unsafe
var filter bson.M
_ = json.NewDecoder(req.Body).Decode(&filter)

Parse in plaats daarvan alleen bekende velden en types:

type QueryInput struct {
    Name string json:"name" validate:"required"
}

2. Losse types accepteren

Injectiekwetsbaarheden ontstaan vaak wanneer API’s te permissieve datatypes accepteren zoals interface{} of generieke maps. Deze flexibele structuren kunnen ingebedde MongoDB-operatoren of kwaadaardige objectconstructies bevatten die de beoogde querylogica omzeilen.

Minimaliseer het gebruik van losse types tenzij absoluut noodzakelijk en implementeer strikte validatie wanneer het niet te vermijden is. Definieer in plaats daarvan expliciete datastructuren die overeenkomen met je verwachte inputformaat en beperk toegestane waarden.

3. JSON in querystrings of query-operatoren

API’s die dynamische filtermogelijkheden via URL-queryparameters of zoekendpoints blootstellen, vormen een aantrekkelijk aanvalsoppervlak. Aanvallers richten zich vaak op deze interfaces door JSON-gecodeerde operatoren en conditionele logica direct in querystrings op te nemen. Dit transformeert legitieme filterparameters in kwaadaardige database­operaties:

GET /search?filter={"price":{"$gt":0}}

Zonder rigoureuze inputvalidatie kunnen aanvallers hiermee querystructuren manipuleren en beveiligingscontroles omzeilen, wat mogelijk ongeautoriseerde data blootlegt of privileges verhoogt buiten de beoogde toegangsniveaus.

Maatregelen:

  • Implementeer allowlists voor velden en operatoren om queryparameters te beperken tot vooraf gedefinieerde, veilige waarden.
  • Wikkel alle door gebruikers aangeleverde waarden expliciet in $eq-operatoren bij het samenstellen van databasefilters om injectie van alternatieve operatoren te voorkomen.

4. Logische queries uitbreiden via injectie

Applicaties die gebruikers controle geven over logische operatoren zoals $or bieden kansen voor query-expansieaanvallen. Aanvallers kunnen extra conditionele expressies in deze operatoren injecteren, waardoor de querysemantiek fundamenteel verandert en mogelijk authenticatiecontroles of toegangsbeperkingen voor data worden omzeild. 

filter := bson.M{
  "$or": []bson.M{
    {"role": "user"},
    {"active": true},
  },
}

Als gebruikersinput de $or-clausule direct manipuleert, kunnen aanvallers ongeautoriseerde voorwaarden injecteren:

{ "$or": [ {"role": "user"}, {"active": true}, {"isAdmin": true} ] }

Deze aangepaste query kan role-based access controls omzeilen, waardoor mogelijk administratieve data wordt blootgesteld of verhoogde privileges aan ongeautoriseerde gebruikers worden verleend. Voorkom dynamische aanpassing van logische operatoren door strikte inputvalidatie te implementeren en directe gebruikerscontrole over de querystructuur te vermijden. 

GET /search?filter={"price":{"$gt":0}}

Zonder rigoureuze inputvalidatie kunnen aanvallers hiermee querystructuren manipuleren en beveiligingscontroles omzeilen, wat mogelijk ongeautoriseerde data blootlegt. 

Maatregelen:

  • Implementeer allowlists voor toegestane velden en operatoren en weiger alle queryparameters buiten deze vooraf gedefinieerde grenzen.
  • Handhaaf expliciete gelijkheidsmatching door alle gebruikersinput in $eq-operatoren te wikkelen om vervanging door vergelijkings- of logische operatoren te voorkomen.

JavaScript-uitvoeringsfeatures

MongoDB biedt verschillende server-side JavaScript-mogelijkheden die potentiële veiligheidsrisico’s introduceren, waaronder:

Deze features creëren aanzienlijke blootstelling en moeten worden vermeden tenzij kritieke bedrijfsvereisten hun gebruik noodzakelijk maken. Schakel scripting uit in de MongoDB-configuratie om misbruik te voorkomen:

Voor mongod:

--noscripting

Of via configbestand:

security:
  javascriptEnabled: false

Pas dezelfde configuratie toe op mongos in een geshardede deployment.

MongoDB’s native query-operatoren bieden uitgebreide functionaliteit die de noodzaak van JavaScript-uitvoering in vrijwel alle use-cases wegneemt. Vermijd $where-clausules volledig, tenzij je absolute controle hebt over inputvalidatie en uitvoeringscontext.

Hoe NoSQL-injectie te voorkomen

1. Valideer input rigoureus

Implementeer strikte typevalidatie die alleen verwachte primitieve datatypes accepteert zoals strings, integers of booleans. Weiger geneste objecten, arrays of onbekende veldnamen die ingebedde operaties of kwaadaardige constructies kunnen bevatten.

type LoginInput struct {
    Username string json:"username" validate:"required,alphanum"
    Password string json:"password" validate:"required,min=8"
}

2. Vertrouw niet op querystructuren van gebruikers

Stel alle databasequeries samen met vooraf gedefinieerde, door de applicatie beheerde veldmappings en querytemplates. Voorkom dat gebruikersinput invloed heeft op queryarchitectuur, logische operatoren of conditionele structuren die de beoogde datapadtoegang kunnen ondermijnen.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Vermijd:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

De meeste MongoDB-drivers bieden sterk getypeerde querybuilders die gestructureerde queryconstructie afdwingen en toevallige injectiekwetsbaarheden voorkomen. Maak gebruik van deze native interfaces in plaats van ruwe querymaps of BSON-objecten via applicatie-endpoints bloot te stellen.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Vermijd:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

3. Blokkeer injectie van MongoDB-operatoren

Voorkom dat door gebruikers aangestuurde input fungeert als queryoperatoren of logische constructies. Behandel alle gebruikersdata als letterlijke waarden in plaats van uitvoerbare querycomponenten.

In plaats van:

filter := bson.M{
    "status": input.Status,
}

Gebruik:

filter := bson.M{
    "status": bson.M{"$eq": input.Status},
}

Deze aanpak dwingt strikte gelijkheidsmatching af en voorkomt de uitvoering van geïnjecteerde operatoren zoals $ne, $in of $regex of andere logische modifiers die de beoogde querylogica kunnen omzeilen.

4. Gebruik least privilege voor databasegebruikers

Configureer databaseverbindingen van de applicatie met gebruikersaccounts die alleen de minimale rechten hebben die nodig zijn voor de beoogde operaties. Vermijd het gebruik van admin-credentials in applicatieconfiguraties om potentiële schade door geslaagde injectieaanvallen te beperken.

5. Monitor en test

Implementeer uitgebreide logging om ongebruikelijke querypatronen te detecteren en stel regelmatige securitytests in. Valideer endpointbeveiliging door injectieaanvallen te proberen met malafide payloads zoals:

{ "$ne": null }

Controleer of de applicatie dit afwijst.

Testcases om te overwegen:

  • Objecten in plaats van strings: { "username": { "$ne": null } }
  • Arrays in plaats van scalars: { "roles": [ { "$gt": "" } ] }
  • Operatoren als querywaarden: { "field": { "$regex": ".*" } }

Samenvattende checklist

  • Inputvalidatie: Dwing strikte datatypes af, valideer formaten en weiger onverwachte velden.
  • Queryconstructie: Bouw alle queries op basis van vooraf gedefinieerde schema’s en door de applicatie beheerde templates
  • Operatorbescherming: Blokkeer MongoDB-operatoren in gebruikersinput door waarden in $eq te wikkelen of getypeerde API’s te gebruiken.
  • Server-side JavaScript: Schaf $where-clausules af en schakel JavaScript-uitvoering uit in productieconfiguraties.
  • DB-toegangsbeheer: Configureer applicatieverbindingen met minimaal vereiste rechten en vermijd administratieve credentials.
  • Testing en monitoring: Voer regelmatig injectietests uit en implementeer logging voor afwijkende querypatronen.

Tot slot

NoSQL-injectiekwetsbaarheden zijn volledig te voorkomen met gedisciplineerde, veilige codeerpraktijken. Door rigoureuze inputvalidatie, gestructureerde queryconstructie en defense-in-depthmaatregelen te implementeren, behouden developers de flexibiliteit en performance van de applicatie terwijl injectie-aanvalsvectoren worden geëlimineerd.

Succes vereist begrip van de volledige dataflow van je applicatie—van het eerste parsen van requests tot de uiteindelijke queryuitvoering. Hanteer een zero-trustbenadering voor alle inputbronnen, implementeer validatie aan systeemgrenzen en geef defensief programmeren prioriteit in je hele technologiestack.

Veelgestelde vragen

Waarom is NoSQL-injectie een risico als MongoDB BSON gebruikt in plaats van strings

Injectie kan nog steeds plaatsvinden vóórdat het BSON-object wordt opgebouwd. Als gebruikersinput zonder validatie wordt geparset naar flexibele types zoals map[string]interface{} of interface{}, kunnen aanvallers MongoDB-operatoren zoals $ne of $or injecteren en de querylogica manipuleren.

Is het veilig om een request body direct te decoderen naar een bson.M of map[string]interface{}?

Nee. Dit stelt gebruikers in staat om willekeurige query-operatoren te injecteren. Map requestdata altijd naar strikte types (bijv. Go-structs) en valideer input vóórdat je queries bouwt.

Wat is er mis met $where gebruiken als de input gevalideerd is?

Zelfs als input deels wordt gevalideerd, voert $where JavaScript uit op de server. Elke fout in escaping of validatie kan tot code-injectie leiden. Het is veiliger om $where geheel te vermijden of scripting in je MongoDB-config uit te schakelen.

Hoe test ik of mijn endpoint kwetsbaar is voor NoSQL-injectie?

Probeer payloads te injecteren zoals:

{ "username": { "$ne": null } }

Als het endpoint een geldige response geeft of logica omzeilt (bijv. inloggen), wordt de input niet goed gevalideerd of begrensd.

Wat is de beste manier om veilig queries te bouwen in Go?

Gebruik getypeerde structs voor input, vermijd decoderen naar generieke maps, en wikkel waarden in $eq wanneer nodig. Laat de gebruiker nooit operatoren definiëren of delen van de query direct injecteren.

Onderwerpen

Gerelateerd