Hiển thị các bài đăng có nhãn SQL. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn SQL. Hiển thị tất cả bài đăng

2019-02-17

NOSQL có đồng nghĩa với NO Injection?

NOSQL có đồng nghĩa với NO Injection?


NOSQL có đồng nghĩa với NO Injection?


Chắc hẳn chúng ta đã khá quen thuộc với khái niệm SQL Injection đây là một lỗi hổng phổ biến nhất cũng như nguy hiểm nhất với các trang web trên Internet. "Gần đây" với sự phất triển của những loại database mới như graph database và NoSql đã làm phong phú hơn lựa chọn dataabase của các dự án phàn mềm.
Với những ưu điểm của mình như:
  • Mã nguồn mở
  • khả năng mở rộng linh hoạt
  • Phù hợp với điện toán đám mây và bigData.
các csld NoSql như MongoDb hay redis là những lựa chọn đáng để cân nhắc với những hệ thống lớn, những một khía cạnh có lẽ không được nhắc đến nhất là ở Việ Nam mình đó chính là tính bảo mật của những csld này, cuối tuần rảnh rỗi sinh nông nổi mình quyết định viết một bài để đánh giá tính bảo mật của csld NoSQL.
Trước khi bắt đầu để tránh gạch đá mình xin làm rõ một vắn để là bản thân CSLD chỉ là: "một tập hợp thông tin có cấu trúc. Tuy nhiên, thuật ngữ này thường dùng trong công nghệ thông tin và nó thường được hiểu rõ hơn dưới dạng một tập hợp liên kết các dữ liệu, thường đủ lớn để lưu trên một thiết bị lưu trữ như đĩa hay băng. Dữ liệu này được duy trì dưới dạng một tập hợp các tập tin trong hệ điều hành hay được lưu trữ trong các hệ quản trị cơ sở dữ liệu." vậy nên nếu vọi vàng đánh giá csld này an toàn csld kia không an toàn chưa hẳn đã chính xác mà một nhân tố vô cùng quan trọng nữa là hện quản trị CSDL (HQTCSDL) ta sử dụng cũng như driver mà ta sử dụng để giao tiếp với HQTCSDL, nội bài biết này mình sẽ giới thiệu một bài lỗ hổng thường gặp trong các HQTCSDL NoSQL., mà cụ thể là MongoDb HQTCCSDL NoSQL phổ biến nhất hiện nay.

Cơ Chế Hoạt Động

Ngay trên trang MongoDB Developer FAQ có nói:
"... with MongoDB we are not building queries from strings, so traditional SQL injection attacks are not a problem."
tức là MongoDb có thể tránh được tất cả các loại SQL injection truyển thống, thay vào đó các hacker lại sự dụng một ký thuật đặc thù cho NoSql đó là NoSQL Injection.

cũng như SQL injection để có thể thực hiện NoSQL Injection hacker cũng phải truy vấn lên server, dựa vào request từ client server sẽ truy vấn đến Database và nhận lại kết quả từ database để trả cho client. Nhiệm vụ của hacker là phải làm sao để hiểu sai request dẫn đến thực hiện một câu truy vấn không mong muốn đến database cuối cùng hacker sẽ lấy được thông tin mong mốn hoặc ngiêm trọng hơn là tthay đổi thậm chí là xóa dự liệu trong csdl.
điểm khác của NoSQL Injection so với SQL Injection truyển thống là:
  • câu truy vấn cho khối dữ liệu không cấu trúc.
  • các HQTCSDL rất đa dạng và khác biệ nhau khá nhiều trong cachs tổ chức dữ liệu cũng như truy vấn.
  • cho phép truy cập trực tiếp client-database thông qua RESTfull API.

Các Loại Tấn Công

có 3 loại tấn công **NoSQL Injection chủ yêu là:
  • Login bypass for MongoDB on PHP and NodeJS
  • String concatenation
  • Escaping flaws of drivers

1. LOGIN BYPASS

đây là loại tấn công rất nguy hiểm vì hacker có thể bỏ qua quy trình đăng nhập và giành quên một cách không mất khó khăn.

giả sử ta có một đoạn login sử dụng NodeJs - express.js - mongodb như sau:
// NodeJS with Express.js
db.collection('users').find({
"user": req.query.user,
"password": req.query.password
});
ở đây ta sử dụng luôn tham số trong request của client để thuwchj hiện câu truy vấn đên database. với dự đoán than số mà người dùng gửi lên sẽ dạng như này:
✔ https://example.org/login?user=patrick&password=1234
trong trường hợp này nếu ông hacker vui tính nào đó gửi lên một request dang như này thì chuyện gì sẽ sảy ra:
⚡ https://example.org/login?user=patrick&password[%24ne]=
khi đó câu query của chúng ta sẽ như thế này
// NodeJS with Express.js
db.collection('users').find({
"user": "patrick",
"password": {"&ne": ""}
});
serlector &ne (not equals) sẽ tìm những bản gì khong bằng giá trị "" tức là trường password sẽ luôn luôn true, hacker đã by pass thanh công.

2. String Concat

Tương tự như SQL Injection vấn đề nối chuỗi (string concat) vẫn là một vấn đề, nếu dev code cẩu thả thì hacker có thể lợi dụng để injectect những đoạn ký tự đặc biệt làm câu query bị thực thui sai mục địch.
vẫn là chức năng đăng nhập trên làn này ta chọn một cách cài đặt khác như sau:
// nodejs example
var string query = “{ username: ‘“ + user + “’, password: ‘” + password + “’ }”

một đoạn có trông có vẻ ngây thơ vô tội nhỉ? nhưng với hacker thì đây đúng là một cơ hội vàng.
⚡ https://example.org/login?username=admin’, $or: [ {}, { ‘a’:’a&password=’ } ], $comment:’hacked’
với request trên câu query của chúng ta sẽ biến thành thế này:

{ username: ‘tolkien’ , $or: [ {}, { ‘a’: ‘a’, password: ‘’ } ], $comment: ‘hacked’ }

OMG, một lần nữa chúng ta đã bypass được login với biểu thức toán tử $or : [true, false ] sex trar laij keets quar true :D
Ngoài ra còn khá nhiều kỹ thuật tấn công khác nếu hứng thú anh em có thể hỏi bác gut gồ nhé.

2018-12-15

Sử dụng chung MongoDB database cho cả development và production

Sử dụng chung MongoDB database cho cả development và production

Tất nhiên đây chỉ là một trick không hề được khuyến khích áp dụng vào bất cứ một dự án Company nào (vốn đòi hỏi yêu cầu bảo mật và an toàn dữ liệu cực kì lớn). App của mình cũng nhỏ thôi, và mình thì... lười. Giả sử như có một bảng user, tất nhiên, user phải vượt qua màn đăng nhập mới được phép truy cập vào app. Và một quãng thời gian đen đủi xảy ra, bạn phải vác chính cái app của mình đi deploy hết từ máy này cho đến máy nọ, vì mất lap, vì chó ỉa lên bàn phím hay sao sao đó chẳng hạn thì việc phải tạo ra một cái DB nữa cho development server nó khiến bạn muốn chán sống đúng không?
Mấy cái chuyện như thế này vốn có nhiều cách giải quyết mà. Dump sẵn một database demo phía client cũng được. Tái sử dụng mongoDB database phía server như mình cũng là một lựa chọn. Chả cái nào hơn cái nào, về phía mình, chỉ là... mình không có nhiều thời gian đi nghiên cứu những cái gì khiến chuyện mình phải focus vào cái app trở nên khó kiểm soát thôi. Mình chỉ là một frontend developer kiêm fullstack developer cho một startup cỡ nhỏ, và bản thân mình nghèo kiết xác k có tiền túi để thuê đứa khác làm giùm mấy cái backend này.

Public port 27017

Cảnh báo cực mạnh: trong mọi trường hợp, đây là cách làm nguy hiểm, trừ khi bạn đã thiết lập chặt chẽ việc bảo mật quá trình kết nối đến MongoDB bằng auth và SSL/TLS hoặc mấy thứ tương tự.
Nói đến chuyện SSL/TLS, chừng nào mình nghiên cứu xong vụ này mình sẽ có một bài viết, đây là trò mình khá thích. Thiết lập Nginx như là một stream reverse-proxy cho MongoDB phía sau hoặc public cổng 27017 rồi cài đặt để bắt buộc sử dụng SSL/TLS khi kết nối chẳng hạn.
Trò này thì đơn giản thôi không khó. Mở file mongod.conf lên (thường thì nằm ở /etc/mongod.conf vì server mình chạy CentOS), comment out dòng bind_ip đi hoặc khai báo rõ nó như dưới đây
# Listen to local interface only. Comment out to listen on all interfaces. 
# bind_ip=127.0.0.1
bind_ip=0.0.0.0
Rồi khởi động lại Mongo là xong. Dưới development, sửa lại localhost thành IP của server, ví dụ mongodb://user:password@aaa.bbb.ccc.ddd/database

SSH Tunnel

Về mặt hình thức thì trò này cũng tương tự như việc bạn sử dụng Robo3T hay mấy phần mềm MongoAdmin tương tự, cho phép kết nối đến mongo server thông qua SSH Tunnel. Kết nối từ máy local sẽ không đi thẳng đến mongo server mà thông qua SSH trước, bằng cách này, tất nhiên sẽ không cần phải public port 27017 nữa, vẫn đảm bảo tính an toàn cho dữ liệu bên trong MongoDB. Để giữ an toàn cho việc đọc/ghi dữ liệu, đừng quên thiết lập bảo mật cho SSH (ví dụ bắt buộc đăng nhập có mật khẩu hay sử dụng private key nhằm mã hoá kết nối SSH cũng như tránh việc bị thằng mấy dạy nào đó chôm được quyền đăng nhập vào server, nhất là tài khoản root, nói tới đây tự hiểu hậu quả nhe).
Bản thân NodeJS có một vài package cho phép hỗ trợ tunnel SSH kiểu này, mình thì ưa thích dùng package tunnel-ssh. Cách sử dụng tunnel-ssh để kết nối đến mongoDB phía server được demo chi tiết trong đoạn code dưới đây
// dev-tunnel.js
import tunnel from 'tunnel-ssh'
import fs from 'fs'

const devSSHTunnel = cb => {
  const sshConfig = {
    host: 'aaa.bbb.ccc.ddd',
    username: 'root',
    agent: process.env.SSH_AUTH_SOCK,
    privateKey: fs.readFileSync(process.env.DEV_SSH_PRIVATE_KEY, 'utf-8'),
    port: 22, // An toàn hơn nữa là đổi luôn cổng mặc định của SSH
    dstPort: 27017
  }

  tunnel(sshConfig, (err, server) => {
    if (err) {
      console.error(err.message)
      return
    }
    console.log('SSH connection successfully')
    cb()
  })
}

export default devSSHTunnel

// mongoose-connect.js
import mongoose from 'mongoose'
import devSSHTunnel from './dev-tunnel'

mongoose.Promise = global.Promise
const conf = {
  useNewUrlParser: true,
  // useMongoClient: true,
  poolSize: 2,
  promiseLibrary: global.Promise
}

function connectDevelopment() {
  return new Promise(resolve => {
    devSSHTunnel(() => {
      const connectPromise = mongoose.connect(
        'mongodb://user:pass@localhost/database',
        conf
      )
      var db = mongoose.connection
      db.on('error', console.error.bind(console, 'DB connection error:'))
      db.once('open', function() {
        console.log('DB connection successful')
      })
      resolve(connectPromise)
    })
  })
}
Mình chả biết viết linh tinh mấy cái này có giúp mình bớt gãy sau 14 tiếng liền ngủ vì cơ thể kiệt sức không chịu nổi. Nhưng thôi kệ, nevermind, anh em có cái để đọc để biết là được. Haha.

2018-12-05

SQL Series: Tăng tốc query của bạn với Indexes

SQL Series: Tăng tốc query của bạn với Indexes

Bạn có thể tưởng rằng… Database cũng giống như thư viện.
và các table giống như sách trong thư viện.
Trong khi đó, các hàng (row) chính là các trang của một cuốn sách.
Lật qua một cuốn sách để tìm kiếm một trang bạn cần sẽ tốn khá nhiều thời gian. Tương tự, khi bạn phải quét tìm kiếm với hàng triệu row trong một table sẽ vô cùng tốn thời gian và tẻ nhạt. Đây chính là lúc mà index tỏa sáng.

Vì sao chúng ta lại cần tới index?

Indexes speed up performance by either ordering the data on disk so it’s quicker to find your result or telling the SQL engine where to go to find your data. If you don’t apply an index, the SQL engine will scan through every row one by one.
While this isn’t necessarily a bad thing, as your database grows things could start to slow down.
Index giúp tăng tốc hiệu suất bằng cách sắp đặt các hàng dữ liệu để giúp việc tìm kiếm kết quả được nhanh hơn hoặc nói cho công cụ SQL biết phải tìm dữ liệu của bạn ở đâu. Nếu bạn không áp dụng một index, công cụ SQL sẽ quét qua từng hàng một.
Mặc dù điều này không nhất thiết là một điều xấu, nhưng khi cơ sở dữ liệu của bạn bành trướng về qui mô thì mọi thứ có thể bắt đầu chậm lại.

Có bao nhiêu loại index?

Có 2 loại chính trong SQL Server:

Clustered Index – trang nội dung

  • Trực tiếp sắp xếp dữ liệu trên đĩa theo cách khiến cho việc truy cập dữ liệu nhanh hơn.
  • Bạn chỉ có thể áp dụng một index cho mỗi bảng vì dữ liệu chỉ có thể được đặt hàng theo một cách.
indexes1

Non-clustered Index

  • Chỉ điểm đến tới nơi dữ liệu cần thiết.
  • Bạn có thể tạo tối đa 999 nhưng vì mỗi index đều cần phải được bảo trì, có thể bạn sẽ chỉ muốn chỉ cần một vài cái thôi.
indexes2

Tôi có thể kiếm index ở đâu sau khi được tạo ra?

Bạn có thể tìm thấy các index trong một table bằng cách mở rộng table ở vị trí chứa index.
indexes3
Đây cũng là nơi bạn có thể tạo index bằng wizard. Trong ví dụ dưới đây, phần option cho Clustered Index giờ sẽ không còn xài được vì chúng ta đã có nó trong table rồi.
indexes4

Những đối tượng nào thích hợp cho index?

Các cột ID, tên, số tài khoảng, etc. Lí tưởng nhất là những gì độc đáo, tuần tự và nhỏ mà bạn đang sử dụng trong SELECTs và JOINs.
Giới tính, năm, và quốc tịch lại không phải là lựa chọn lí tưởng. Bạn chỉ nên áp dụng index cho những cột mà bạn phải query thường xuyên.

Tôi không thể làm việc này sau à?

Tất nhiên là được. Đôi khi bạn nên query data trước rồi sau đó mới thêm index vào.
Nhưng nếu bạn không hề có index trong table chứa data. Việc này sẽ dẫn tới hiện tượng “Heaped Storage” – tốn nhiều bộ nhớ để lưu chữ một spreadsheet.
Lưu ý rằng áp dụng index sẽ mất thời gian nếu table của bạn có qui mô lớn.

Tôi có thật sự cần tới nó không?

Hoàn toàn tùy thuộc vào mục đích cũng như điều bạn cần. Lợi thế của việc không thêm index là INSERTs và UPDATEs của bạn sẽ nhanh hơn cũng như database cũng bạn cũng sẽ luôn nhỏ hơn.
Nếu bạn thấy mọi thứ đang bị chậm lại, hãy thử kiểm tra phần Execution Plan cho thông tin về những nơi tốn nhiều công sức để thực hiện query của bạn.

indexes5

Bao nhiêu Index là quá nhiều?

Tương tự, nó thật sự tùy vào bạn. Quá nhiều index sẽ làm chậm hiệu năng. Khi bạn đã tạo index cho Primary Key và Unique Keys thì mọi thứ còn lại tùy vào bạn, hãy xem Execution Plan và quyết định mình nên làm gì tiếp theo.

Đây có phải là giải pháp giúp cải thiện hiệu năng không?

Indexes luôn cần được bảo trì. Chúng có thể cải thiện hiệu năng lúc đầu nhưng cần phải được review, update và bảo dưỡng mỗi khi database của bạn mở rộng. Vì vậy hãy dùng tới Execution Plan để xem những điều cần thiết mà bạn nên thực hiện.