MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Bảo mật MongoDB khỏi các cuộc tấn công từ bên ngoài

Bảo mật MongoDB không được đảm bảo đầy đủ bằng cách chỉ định cấu hình chứng chỉ xác thực hoặc mã hóa dữ liệu. Một số kẻ tấn công sẽ “đi xa hơn” bằng cách chơi với các tham số nhận được trong các yêu cầu HTTP được sử dụng như một phần của quy trình truy vấn của cơ sở dữ liệu.

Cơ sở dữ liệu SQL dễ bị tấn công kiểu này nhất, nhưng việc chèn bên ngoài cũng có thể xảy ra trong các DBM NoSQL như MongoDB. Trong hầu hết các trường hợp, việc đưa vào bên ngoài xảy ra do sự nối các chuỗi không an toàn khi tạo truy vấn.

Tấn công Chèn ép Bên ngoài là gì?

Chèn mã về cơ bản là tích hợp dữ liệu chưa được kiểm chứng (vectơ không điều chỉnh) vào một chương trình dễ bị tấn công mà khi được thực thi sẽ dẫn đến việc truy cập thảm hại vào cơ sở dữ liệu của bạn; đe dọa sự an toàn của nó.

Khi các biến chưa được mã hóa được chuyển vào truy vấn MongoDB, chúng sẽ phá vỡ cấu trúc hướng truy vấn tài liệu và đôi khi được thực thi như chính mã javascript. Trường hợp này thường xảy ra khi chuyển trực tiếp các đạo cụ từ mô-đun body-parser cho máy chủ Nodejs. Do đó, kẻ tấn công có thể dễ dàng chèn một đối tượng Js vào nơi bạn mong đợi một chuỗi hoặc số, do đó nhận được kết quả không mong muốn hoặc bằng cách thao túng dữ liệu của bạn.

Hãy xem xét dữ liệu dưới đây trong bộ sưu tập của sinh viên.

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

Giả sử chương trình của bạn phải tìm nạp tất cả sinh viên có độ tuổi bằng 20, bạn sẽ viết mã như thế này ...

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

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

})

Bạn sẽ gửi một đối tượng JSON trong yêu cầu http của mình dưới dạng

{age: 20}

Kết quả này sẽ trả về tất cả sinh viên có tuổi bằng 20 như kết quả mong đợi và trong trường hợp này chỉ có {username:'John Doc', email:'[email protected] ', age:20} .

Bây giờ, giả sử kẻ tấn công gửi một đối tượng thay vì một số, tức là {‘$ gt:0’};

Truy vấn kết quả sẽ là:

db.collections (“sinh viên”). find ({age:{‘$ gt:0’}); là một truy vấn hợp lệ mà khi thực hiện sẽ trả về tất cả các sinh viên trong bộ sưu tập đó. Kẻ tấn công có cơ hội hành động trên dữ liệu của bạn theo ý định xấu của chúng. Trong hầu hết các trường hợp, kẻ tấn công chèn một đối tượng tùy chỉnh có chứa các lệnh MongoDB cho phép chúng truy cập vào tài liệu của bạn mà không cần quy trình thích hợp.

Một số lệnh MongoDB thực thi mã Javascript trong công cụ cơ sở dữ liệu, một nguy cơ tiềm ẩn cho dữ liệu của bạn. Một số lệnh này là ‘$ where’, ‘$ group’ và ‘mapReduce’. Đối với các phiên bản trước MongoDB 2.4, mã Js có quyền truy cập vào đối tượng db từ bên trong truy vấn.

MongoDB Bảo vệ Naitive

MongoDB sử dụng dữ liệu BSON (Binary JSON) cho cả truy vấn và tài liệu của nó, nhưng trong một số trường hợp, nó có thể chấp nhận các biểu thức JSON và Js chưa được chuẩn hóa (chẳng hạn như các biểu thức được đề cập ở trên). Hầu hết dữ liệu được chuyển đến máy chủ ở định dạng chuỗi và có thể được đưa trực tiếp vào truy vấn MongoDB. MongoDB không phân tích cú pháp dữ liệu của nó, do đó tránh được các rủi ro tiềm ẩn có thể xảy ra do các tham số trực tiếp được tích hợp.

Nếu một API liên quan đến việc mã hóa dữ liệu dưới dạng văn bản được định dạng và văn bản đó cần được phân tích cú pháp, nó có khả năng tạo ra sự bất đồng giữa trình gọi của máy chủ và cơ sở dữ liệu về cách chuỗi đó sẽ được phân tích cú pháp . Nếu dữ liệu vô tình bị hiểu sai thành siêu dữ liệu, trường hợp này có thể tiềm ẩn các mối đe dọa bảo mật đối với dữ liệu của bạn.

Ví dụ về việc tiêm thuốc bên ngoài MongoDB và cách xử lý chúng

Hãy xem xét dữ liệu dưới đây trong bộ sưu tập sinh viên.

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

Tiêm bằng toán tử $ ne (không bằng)

Nếu tôi muốn trả lại tài liệu với tên người dùng và mật khẩu được cung cấp từ một yêu cầu, mã sẽ là:

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

    });

});

Nếu chúng tôi nhận được yêu cầu bên dưới

POST https://localhost/students HTTP/1.1

Content-Type: application/json

{

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

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

}

Truy vấn chắc chắn sẽ trả về sinh viên đầu tiên trong trường hợp này vì tên người dùng và mật khẩu của anh ta không có giá trị là null. Đây không phải là kết quả mong đợi.

Để giải quyết vấn đề này, bạn có thể sử dụng:

mô-đun mongo-sanitize ngăn bất kỳ khóa nào bắt đầu bằng ‘$’ được chuyển vào công cụ truy vấn MongoDB.

Cài đặt mô-đun trước

​npm install mongo-sanitize

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

var query = {

username: req.body.username,

password: req.body.password

}

Sử dụng mongoose để xác thực các trường lược đồ của bạn sao cho nếu nó mong đợi một chuỗi và nhận một đối tượng, truy vấn sẽ xuất hiện một lỗi. Trong trường hợp của chúng tôi, giá trị null ở trên sẽ được chuyển đổi thành một chuỗi “” mà theo nghĩa đen không có tác động.

Tiêm bằng Toán tử $ where

Đây là một trong những toán tử nguy hiểm nhất. Nó sẽ cho phép một chuỗi được đánh giá bên trong chính máy chủ. Ví dụ:để tìm nạp học sinh có độ tuổi trên giá trị Y, truy vấn sẽ là

var query = { 

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

}

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

        res(student);

    });

Việc sử dụng mô-đun sanitize sẽ không hữu ích trong trường hợp này nếu chúng ta có ‘0; return true ’vì kết quả sẽ trả về tất cả các sinh viên chứ không phải là những sinh viên có tuổi lớn hơn một số giá trị nhất định. Các chuỗi khả thi khác mà bạn có thể nhận được là ‘\’; return \ ‘\’ ==\ ’’ hoặc this.email ===‘’; return ‘’ ==‘’. Truy vấn này sẽ trả về tất cả các sinh viên thay vì chỉ những sinh viên phù hợp với mệnh đề.

Nên tránh rất nhiều mệnh đề $ where. Bên cạnh những trở ngại đã nêu, nó cũng làm giảm hiệu suất vì nó không được tối ưu hóa để sử dụng các chỉ mục.

Cũng có khả năng lớn là chuyển một hàm trong mệnh đề $ where và biến sẽ không thể truy cập được trong phạm vi MongoDB do đó có thể dẫn đến việc ứng dụng của bạn bị treo. Tức là

var query = {

   $where: function() {

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

   }

}

Bạn cũng có thể sử dụng các toán tử $ eq, $ lt, $ lte, $ gt, $ gte để thay thế.

Bảo vệ bản thân khỏi MongoDB tiêm từ bên ngoài

Đây là ba điều bạn có thể làm để bảo vệ bản thân ...

  1. Xác thực dữ liệu người dùng. Nhìn lại cách biểu thức $ where có thể được sử dụng để truy cập dữ liệu của bạn, bạn nên luôn xác thực những gì người dùng gửi đến máy chủ của bạn.
  2. Sử dụng khái niệm trình xác thực JSON để xác thực giản đồ của bạn cùng với mô-đun mongoose.
  3. Thiết kế các truy vấn của bạn sao cho mã Js không có toàn quyền truy cập vào mã cơ sở dữ liệu của bạn.

Kết luận

Cũng có thể tiêm bên ngoài với MongoDB. Nó thường được kết hợp với việc dữ liệu người dùng chưa được xác thực đi vào các truy vấn MongoDB. Điều quan trọng luôn là phát hiện và ngăn chặn việc đưa NoSQL vào bằng cách kiểm tra bất kỳ dữ liệu nào có thể được máy chủ của bạn nhận. Nếu sơ ý, điều này có thể đe dọa sự an toàn của dữ liệu người dùng. Quy trình quan trọng nhất là xác thực dữ liệu của bạn ở tất cả các lớp liên quan.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Node.js - Tạo mối quan hệ với Mongoose

  2. Toán tử tổng hợp MongoDB $ sortByCount

  3. Tính tổng của cột trong MongoDB

  4. 7 cách đếm tài liệu trong MongoDB

  5. Cách cài đặt MongoDB Community Edition trên Ubuntu