sql >> Database >  >> NoSQL >> MongoDB

MongoDB beveiligen tegen externe injectie-aanvallen

MongoDB-beveiliging is niet volledig gegarandeerd door simpelweg authenticatiecertificaten te configureren of de gegevens te versleutelen. Sommige aanvallers zullen "een stapje verder gaan" door te spelen met de ontvangen parameters in HTTP-verzoeken die worden gebruikt als onderdeel van het queryproces van de database.

SQL-databases zijn het meest kwetsbaar voor dit type aanval, maar externe injectie is ook mogelijk in NoSQL DBM's zoals MongoDB. In de meeste gevallen vinden externe injecties plaats als gevolg van een onveilige aaneenschakeling van tekenreeksen bij het maken van zoekopdrachten.

Wat is een externe injectie-aanval?

Code-injectie is in feite het integreren van niet-gevalideerde gegevens (onbeperkte vector) in een kwetsbaar programma dat, wanneer het wordt uitgevoerd, leidt tot rampzalige toegang tot uw database; zijn veiligheid in gevaar brengen.

Als niet-opgeschoonde variabelen worden doorgegeven aan een MongoDB-query, breken ze de oriëntatiestructuur van de documentquery en worden ze soms uitgevoerd als de javascript-code zelf. Dit is vaak het geval wanneer rekwisieten rechtstreeks vanuit de body-parser-module voor de Nodejs-server worden doorgegeven. Daarom kan een aanvaller gemakkelijk een Js-object invoegen waar u een tekenreeks of cijfer zou verwachten, waardoor ongewenste resultaten worden verkregen of door uw gegevens te manipuleren.

Beschouw de onderstaande gegevens in de verzameling van een leerling.

{username:'John Doc', email:'[email protected]', age:20},

{username:'Rafael Silver', email:'[email protected]', age:30},

{username:'Kevin Smith', email:'[email protected]', age:22},

{username:'Pauline Wagu', email:'[email protected]', age:23}

Stel dat je programma alle leerlingen moet ophalen van wie de leeftijd gelijk is aan 20,  zou je een code als deze schrijven...

app.get(‘/:age’, function(req, res){

  db.collections(“students”).find({age: req.params.age});

})

U heeft een JSON-object in uw http-verzoek ingediend als 

{age: 20}

Hiermee worden alle leerlingen van wie de leeftijd gelijk is aan 20 als het verwachte resultaat geretourneerd en in dit geval alleen {username:'John Doc', email:'[email protected]', age:20} .

Stel nu dat een aanvaller een object indient in plaats van een getal, bijv. {‘$gt:0’};

De resulterende zoekopdracht is:

db.collections(“studenten”).find({leeftijd:{‘$gt:0’}); wat een geldige zoekopdracht is die bij uitvoering alle leerlingen in die verzameling zal retourneren. De aanvaller heeft een kans om op uw gegevens te reageren volgens hun kwaadaardige bedoelingen. In de meeste gevallen injecteert een aanvaller een aangepast object dat MongoDB-opdrachten bevat waarmee hij toegang kan krijgen tot uw documenten zonder de juiste procedure.

Sommige MongoDB-opdrachten voeren Javascript-code uit in de database-engine, een potentieel risico voor uw gegevens. Sommige van deze commando's zijn '$where', '$group' en 'mapReduce'. Voor versies vóór MongoDB 2.4 heeft Js-code toegang tot het db-object vanuit de query.

MongoDB eigen bescherming

MongoDB gebruikt de BSON-gegevens (Binary JSON) voor zowel zijn zoekopdrachten als documenten, maar in sommige gevallen kan het niet-geserialiseerde JSON- en Js-expressies accepteren (zoals de hierboven genoemde). De meeste gegevens die aan de server worden doorgegeven, hebben de indeling van een tekenreeks en kunnen rechtstreeks in een MongoDB-query worden ingevoerd. MongoDB ontleedt zijn gegevens niet, waardoor potentiële risico's worden vermeden die kunnen voortvloeien uit de integratie van directe parameters.

Als een API gegevens codeert in een opgemaakte tekst en die tekst moet worden geparseerd, kan dit leiden tot onenigheid tussen de aanroeper van de server en de aanroeper van de database over hoe die tekenreeks zal worden geparseerd . Als de gegevens per ongeluk verkeerd worden geïnterpreteerd als metagegevens, kan het scenario mogelijk een beveiligingsrisico vormen voor uw gegevens.

Voorbeelden van MongoDB externe injecties en hoe ermee om te gaan

 Laten we de onderstaande gegevens eens bekijken in een verzameling leerlingen.

{username:'John Doc', password: ‘16djfhg’, email:'[email protected]', age:20},

{username:'Rafael Silver',password: ‘djh’, email:'[email protected]', age:30},

{username:'Kevin Smith', password: ‘16dj’, email:'[email protected]', age:22},

{username:'Pauline Wagu', password: ‘g6yj’, email:'[email protected]', age:23}

Injectie met de $ne (niet gelijk aan) operator

Als ik het document wil terugsturen met gebruikersnaam en wachtwoord die zijn geleverd door een verzoek, is de code:

app.post('/students, function (req, res) {

    var query = {

        username: req.body.username,

        password: req.body.password

    }

    db.collection(students).findOne(query, function (err, student) {

        res(student);

    });

});

Als we het onderstaande verzoek ontvangen

POST https://localhost/students HTTP/1.1

Content-Type: application/json

{

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

    "password": {"$ne": null}

}

De vraag zal in dit geval zeker de eerste student opleveren, aangezien zijn gebruikersnaam en wachtwoord niet als nul worden gewaardeerd. Dit is niet volgens de verwachte resultaten.

Om dit op te lossen, kun je het volgende gebruiken:

mongo-sanitize-module die voorkomt dat een sleutel die begint met '$' wordt doorgegeven aan de MongoDB-query-engine.

Installeer eerst de module  

​npm install mongo-sanitize

var sanitize = require(‘mongo-sanitize’);

var query = {

username: req.body.username,

password: req.body.password

}

Mongoose gebruiken om je schemavelden te valideren, zodat als het een string verwacht en een object ontvangt, de query een foutmelding geeft. In ons bovenstaande geval wordt de null-waarde omgezet in een tekenreeks "" die letterlijk geen impact heeft.

Injectie met behulp van de $where-operator

Dit is een van de gevaarlijkste operators. Hiermee kan een string in de server zelf worden geëvalueerd. Als u bijvoorbeeld leerlingen wilt ophalen van wie de leeftijd hoger is dan een waarde Y, is de zoekopdracht 

var query = { 

   $where: “this.age > ”+req.body.age

}

 db.collection(students).findOne(query, function (err, student) {

        res(student);

    });

Het gebruik van de ontsmettingsmodule zal in dit geval niet helpen als we een '0; return true' omdat het resultaat alle studenten zal retourneren in plaats van degenen van wie de leeftijd groter is dan een bepaalde waarde. Andere mogelijke strings die u kunt ontvangen zijn '\'; return \ ‘\’ ==\’’ of  this.email ===‘’;return ‘’ ==‘’. Deze zoekopdracht retourneert alle studenten in plaats van alleen degenen die overeenkomen met de clausule.

De $where-clausule moet absoluut worden vermeden. Naast de geschetste tegenvaller vermindert het ook de prestaties omdat het niet is geoptimaliseerd om indexen te gebruiken.

Er is ook een grote mogelijkheid om een ​​functie door te geven in de $where-clausule en de variabele zal niet toegankelijk zijn in de MongoDB-scope en kan ertoe leiden dat uw toepassing crasht. Dwz

var query = {

   $where: function() {

       return this.age > setValue //setValue is not defined

   }

}

Je kunt in plaats daarvan ook de $eq, $lt, $lte, $gt, $gte operators gebruiken.

Uzelf beschermen tegen MongoDB externe injectie

Hier zijn drie dingen die je kunt doen om jezelf te beschermen...

  1. Gebruikersgegevens valideren. Terugkijkend op hoe de $where-expressie kan worden gebruikt om toegang te krijgen tot uw gegevens, is het raadzaam om altijd te valideren wat gebruikers naar uw server sturen.
  2. Gebruik het JSON-validatorconcept om uw schema samen met de mangoestmodule te valideren.
  3. Ontwerp uw zoekopdrachten zodanig dat Js-code geen volledige toegang heeft tot uw databasecode.

Conclusie

Externe injectie is ook mogelijk met MongoDB. Het wordt vaak geassocieerd met niet-gevalideerde gebruikersgegevens die in MongoDB-query's terechtkomen. Het is altijd belangrijk om NoSQL-injectie te detecteren en te voorkomen door alle gegevens te testen die door uw server kunnen worden ontvangen. Als dit wordt verwaarloosd, kan dit de veiligheid van gebruikersgegevens in gevaar brengen. De belangrijkste procedure is om uw gegevens op alle betrokken lagen te valideren.


  1. Hoe moet ik Booksleeve gebruiken met protobuf-net?

  2. Hoe stel ik een Elasticache Redis-cluster in als een slaaf?

  3. redis en watch + multi staan ​​gelijktijdige gebruikers toe

  4. SCAN vs KEYS-prestaties in Redis