sql >> Databáze >  >> NoSQL >> MongoDB

Zabezpečení MongoDB před externími vstřikovacími útoky

Bezpečnost MongoDB není plně zaručena pouhou konfigurací ověřovacích certifikátů nebo šifrováním dat. Někteří útočníci „udělají něco navíc“ hraním si s přijatými parametry v požadavcích HTTP, které se používají jako součást procesu dotazování databáze.

Databáze SQL jsou vůči tomuto typu útoku nejzranitelnější, ale externí vkládání je možné také v NoSQL DBM, jako je MongoDB. Ve většině případů k externím injekcím dochází v důsledku nebezpečného zřetězení řetězců při vytváření dotazů.

Co je útok externí injekcí?

Vložení kódu je v podstatě integrace nevalidovaných dat (neomezený vektor) do zranitelného programu, který při spuštění vede ke katastrofálnímu přístupu k vaší databázi; ohrožující jeho bezpečnost.

Když jsou do dotazu MongoDB předány neupravené proměnné, poruší strukturu orientace dotazu na dokument a někdy se spouštějí jako samotný kód javascriptu. To se často stává při předávání rekvizit přímo z modulu analýzy těla pro server Nodejs. Útočník tedy může snadno vložit objekt Js tam, kde byste očekávali řetězec nebo číslo, a získat tak nechtěné výsledky nebo manipulovat s vašimi daty.

Zvažte níže uvedená data ve sbírce studenta.

{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}

Řekněme, že váš program musí získat všechny studenty, jejichž věk se rovná 20,  napsali byste takovýto kód...

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

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

})

Objekt JSON ve svém požadavku http odešlete jako 

{age: 20}

Toto vrátí všechny studenty, jejichž věk je roven 20 jako očekávaný výsledek, a v tomto případě pouze {username:'John Doc', email:'[email protected]', věk:20} .

Nyní řekněme, že útočník odešle objekt namísto čísla, např. {‘$gt:0‘};

Výsledný dotaz bude:

db.collections(“studenti”).find({věk:{‘$gt:0’}); což je platný dotaz, který po spuštění vrátí všechny studenty v dané kolekci. Útočník má šanci jednat s vašimi údaji podle svých nekalých úmyslů. Ve většině případů útočník vloží vlastní objekt, který obsahuje příkazy MongoDB, které jim umožňují přístup k vašim dokumentům bez správného postupu.

Některé příkazy MongoDB spouštějí kód Javascript v databázovém stroji, což představuje potenciální riziko pro vaše data. Některé z těchto příkazů jsou „$where“, „$group“ a „mapReduce“. U verzí před MongoDB 2.4 má kód Js přístup k objektu db z dotazu.

Nativní ochrany MongoDB

MongoDB využívá data BSON (binární JSON) pro své dotazy i dokumenty, ale v některých případech může přijímat neserializované výrazy JSON a Js (jako jsou ty uvedené výše). Většina dat předávaných na server je ve formátu řetězce a lze je vložit přímo do dotazu MongoDB. MongoDB neanalyzuje svá data, čímž se vyhne potenciálním rizikům, která mohou vyplynout z přímé integrace parametrů.

Pokud rozhraní API zahrnuje kódování dat ve formátovaném textu a tento text je třeba analyzovat, může to způsobit neshodu mezi volajícím serveru a volaným z databáze ohledně toho, jak bude tento řetězec analyzován. . Pokud jsou data náhodně nesprávně interpretována jako metadata, scénář může potenciálně představovat bezpečnostní hrozbu pro vaše data.

Příklady externích injekcí MongoDB a jak s nimi zacházet

 Podívejme se na níže uvedená data ve sbírce studentů.

{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}

Injekce pomocí operátoru $ne (není rovno)

Pokud chci vrátit dokument s uživatelským jménem a heslem poskytnutým z požadavku, kód bude:

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);

    });

});

Pokud obdržíme níže uvedený požadavek

POST https://localhost/students HTTP/1.1

Content-Type: application/json

{

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

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

}

Dotaz v tomto případě určitě vrátí prvního studenta, protože jeho uživatelské jméno a heslo nemají hodnotu null. To není podle očekávaných výsledků.

K vyřešení tohoto problému můžete použít:

modul mongo-sanitize, který zastaví předání jakéhokoli klíče začínajícího na „$“ do dotazovacího nástroje MongoDB.

Nejprve nainstalujte modul  

​npm install mongo-sanitize

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

var query = {

username: req.body.username,

password: req.body.password

}

Použití mongoose k ověření polí schématu tak, že pokud očekává řetězec a přijme objekt, dotaz vyvolá chybu. V našem případě výše bude hodnota null převedena na řetězec „“, který nemá doslova žádný dopad.

Injekce pomocí operátoru $where

Toto je jeden z nejnebezpečnějších operátorů. Umožní vyhodnocení řetězce uvnitř samotného serveru. Chcete-li například načíst studenty, jejichž věk je vyšší než hodnota Y, dotaz bude 

var query = { 

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

}

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

        res(student);

    });

Použití modulu sanitize v tomto případě nepomůže, pokud máme „0; return true‘, protože výsledek vrátí všechny studenty spíše než ty, jejichž věk je vyšší než nějaká daná hodnota. Další možné řetězce, které můžete obdržet, jsou „\“; return \ ‘\’ ==\’’ nebo  this.email ===‘’;return ‘’ ==‘’. Tento dotaz vrátí všechny studenty, nikoli pouze ty, kteří odpovídají klauzuli.

Klauzule $where by se měla výrazně vyhnout. Kromě nastíněné překážky také snižuje výkon, protože není optimalizován pro použití indexů.

Existuje také skvělá možnost předání funkce v klauzuli $where a proměnná nebude přístupná v rozsahu MongoDB, a proto může dojít ke zhroucení vaší aplikace. T.j.

var query = {

   $where: function() {

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

   }

}

Místo toho můžete také použít operátory $eq, $lt, $lte, $gt, $gte.

Chraňte se před externí injekcí MongoDB

Zde jsou tři věci, které můžete udělat, abyste se ochránili...

  1. Ověřte uživatelská data. Když se podíváte zpět na to, jak lze výraz $where použít pro přístup k vašim datům, je vhodné vždy ověřit, co uživatelé odesílají na váš server.
  2. Použijte koncept validátoru JSON k ověření schématu společně s modulem mongoose.
  3. Navrhněte své dotazy tak, aby kód Js neměl úplný přístup ke kódu vaší databáze.

Závěr

Externí vstřikování je také možné s MongoDB. Často je to spojeno s tím, že se do dotazů MongoDB dostávají nevalidovaná uživatelská data. Vždy je důležité detekovat a zabránit vkládání NoSQL testováním jakýchkoli dat, která mohou být přijata vaším serverem. Pokud se zanedbá, může to ohrozit bezpečnost uživatelských dat. Nejdůležitějším postupem je ověřit vaše data na všech zúčastněných vrstvách.


  1. Vytvoření posluchače redis - možné v php?

  2. Chyba křížového slotu Redis

  3. Multiparametrový vyhledávač zápasů s Redis

  4. Mohu serializovat objekt instance Ruby Digest::SHA1?