Express.js Best Security Paractices

Express.js là một trong những framework phổ biến nhất trong làng dev Node.js, nó là một framework đơn giản nhưng đủ mạnh để giúp chúng ta tiếp cận cũng như phát triển website dựa trên framwork này. Cũng giống như với các framework khác, với Express.js chúng ta cũng có khá nhiều điểm cần lưu ý để đảm bảo ứng dụng của mình hoạt động linh hoạt và an toàn trên môi trường production. Thuật ngữ "production" được dùng để chỉ định giai đoạn trong vòng đời phát triển phần mềm mà khi đó ứng dụng hoặc api đã được public đến người dùng cuối hoặc khách hàng. Ngược lại, giao đoan "development" là giai đoạn khi mà chúng ta vẫn còn đang tiếp tục công việc coding hoặc testing. Hai môi trường Production và Development thường có những cài đặt, cấu hình khác nhau nhằm phục vụ cho việc debug, testing khi development và đảm bảo performance, security khi lên production; trong đó thì có rất nhiều thứ hợp lý và hữu ích khi development nhưng lại hoàn toàn không nên hoặc bị cấm khi lên production (như là logging, debugging...) Dưới đây là một số lưu ý khi triển khai production cho một ứng dụng Express.js

Không sử dụng những phiên bản có lỗi hoặc không được khuyến khích (deprecated)

Phiên bản mới nhất (hiện tại) của Express.js là 4.16.1, với rất nhiều tính năng cải tiến về tốc độ cũng như bảo mật; các phiên bản tiền nhiệm như Express 2.x hoặc Express 3.x cũng rất mạnh mẽ và được đánh giá cao, tuy nhiên các phiên bản cũ này đã không còn được hỗ trợ nữa. Điều đó có nghĩa là tất cả những vấn đề về hiệu năng hay bảo mật của Express 2.x và Express 3.x sẽ không còn được khắc phục nữa. Vậy nên nếu bạn đang làm một ứng dụng mới sử dụng Express.js thì hãy nên sử dụng phiên bản mới nhất; nếu bạn vẫn đang sử dụng Express.js cũ cho các ứng dụng của mình thì nên xem xét cập nhật lên Express 4 nếu có thể. Ngoài ra thì để đảm bảo phiên bản mình sử dụng không phải là phiên bản lỗi thì bạn cũng có thể kiểm tra danh sách các phiên bản có lỗi tại đây

Sử dụng Transport Layer Security (TLS)

Nếu ứng dụng của bạn có làm việc với những dữ liệu quan trọng, hãy sử dụng Transport Layer Security (TLS) để bảo mật các kết nối và dữ liệu của mình. Công nghệ này sẽ mã hóa dữ liệu trước khi nó được gửi đi từ client lên server, điều này sẽ giúp ngăn chặn một số kỹ thuật hacking phổ biến. Mặc dù với Ajax và Post requets thì có vẻ như dữ liệu truyền đi đã bị che dấu (chúng ta không nhìn thấy nó như với GET request), tuy nhiên thì trong thực tế chúng vẫn có thể bị tấn công bởi các công cụ hỗ trợ packet sniffing hoặc tấn công man-in-the-middle Mã hóa Secure Socket Layer (SSL) được sử dụng rất phổ biến và chắc hẳn bạn đã gặp nó rất nhiều rồi. TLS đơn giản chỉ là quá trình tiền theo của SSL. Nói theo một cách khác thì nếu bạn đã sử dụng SSL trước đó thì hãy nên xem xét để nâng cấp lên TLS, TLS có thể được cài đặt rất dễ dàng thông qua Nginx. Bạn có thể tìm hiểu về cấu hình TLS với Nginx tại đây Ngoài ra thì bạn nên thử Let's Encrypt, đó là một công cụ miễn phí, tự động hoàn toàn với chứng chỉ xác thực được cung cấp bởi Internet Security Research Group (ISRG)

Sử dụng Helmet

Helmet là một package được viêt để giúp bạn bảo vệ ứng dụng của mình khỏi những lỗ hổng đã biết bằng cách thiết lập các Http headers một cách phù hợp Thực tế thì Helmet chỉ là một tập hợp các Middleware nhỏ làm nhiệm vụ thiết lập các Http headers liên quan đến bảo mật, cụ thể như sau:

  • csp Thiết lập header Content-Security-Policy giúp ngăn chặn tấn công cross-site scripting và các tấn công cross-site injections khác.
  • hidePoweredBy Xóa header X-Powered-By header khỏi response, giúp dấu đi thông tin mã nguồn bạn sử dụng.
  • hpkp Thêm header Public Key Pinning giúp bản vệ ứng dụng khỏi tấn công man-in-the-middle với chứng chỉ giả mạo.
  • hsts Cài đặt header Strict-Transport-Security giúp thực thi kết nối bảo mật (HTTP over SSL/TLS) đến server.
  • ieNoOpen set header X-Download-Options cho IE8+.
  • noCache set header Cache-ControlPragma để tắt client-side caching.
  • noSniff set header X-Content-Type-Options giúp ngăn chặn trình duyệt khỏi MIME-sniffing.
  • frameguard set header X-Frame-Options để bảo vệ ứng dụng khỏi clickjacking.
  • xssFilter set header X-XSS-Protection giúp kích hoạt bộ lọc Cross-site scripting (XSS).

Cài đặt và sử dụng Helmet

npm install --save helmet
var helmet = require('helmet')
app.use(helmet())

Nếu bạn không muốn sử dụng Helmet thì tốt nhất vẫn nên tắt header X-Powered-By. Hacker có thể sử dụng header này để xác định ứng dụng của bạn sử dụng Express.js

app.disable('x-powered-by')

Lưu ý rằng tắt header x-powered-by không đảm bảo chắc chắn được hacker không thể xác định app của bạn viết trên Express.js, tuy nhiên nó là cách khá đơn giản và cũng có hiệu quả rất tốt

Bảo mật với cookie

Để đảm bảo rẳng cookies không khiến ứng dụng của bạn bị hack, tuyệt đối không sử dụng cookie name mặc định cũng như cần phải thiết lập đúng cách các options với cookie Đối với việc bảo mật cookies, chúng ta có thể sử dụng 2 packages sau:

  • express-session thay thế middleware mặc định express.session lên phiên bản Express 3.x.
  • cookie-session thay thế middleware mặc định express.cookieSession lên phiên bản Express 3.x. Điểm khác biệt chính giữa hai packages này nằm ở cách chúng lưu trữ dữ liệu cookie session. express-session lưu trữ dữ liệu session tại server, nó chỉ sử dụng cookie để lữu trữ Session ID. Mặc định nó sẽ sử dụng bộ lưu trữ in-memory và cách lưu trữ này không được thiết kế để chạy với môi trường production. Với môi trường Production, bạn sẽ cần phải cài đặt một bộ lưu trữ session có tính linh hoạt cao và có khả năng mở rộng, xem danh sách được hỗ trợ: https://github.com/expressjs/session#compatible-session-stores cookie-session thì ngược lại, nó triển khai một bộ lưu trữ cookie-backed: cookie-session sẽ serializes toàn bộ dữ liệu session thành cookie. Chỉ sử dụng cách này khi dữ liệu session nhỏ và có thể dễ dàng để mã hóa. Mặc dù browser có thể hỗ trợ tối thiểu 4096 bytes cho mỗi cookie nhưng để đảm bảo bạn không bị quá giới hạn này thì tốt nhất không để cho size vượt quá 4093 bytes với mỗi cookie domain. Bạn cũng nên lưu ý rằng dữ liệu cookie là mở và có thể can thiệp bởi client, do đó trong trường hợp dữ liệu cookie là quan trọng thì tốt hơn nên sử dụng express-session.

Không sử dụng cookie name mặc định

Cũng giống như với việc dấu đi header X-Powered-By, chúng ta cũng nên thay đổi tên mặc định của cookie, điều này sẽ giúp ẩn dấu thông tin framework ta sử dụng

var session = require('express-session')
app.set('trust proxy', 1) // trust first proxy
app.use(session({
  secret: 's3Cur3',
  name: 'sessionId'
}))

Thiết lập các options nâng cao bảo mật

Cài đặt các options sau đây để giúp tăng cường bảo mật cho cookie:

  • secure - Đảm bảo rằng browser sẽ chỉ gửi cookie qua HTTPS.
  • httpOnly - Đảm bảo rằng cookie chỉ được gửi qua HTTP(S), không phải thông qua client JavaScript, giúp ngăn chặn tấn công cross-site scripting.
  • domain - Chỉ định domain của cookie; Cookie chỉ hợp lệ đối với domain phát sinh request.
  • path - Chỉ định path của cookie.
  • expires - Thiết lập thời gian hết hạn cho cookie. Ví dụ về thiết lập bảo mật cho cookie
var session = require('cookie-session')
var express = require('express')
var app = express()

var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
  name: 'session',
  keys: ['key1', 'key2'],
  cookie: {
    secure: true,
    httpOnly: true,
    domain: 'example.com',
    path: 'foo/bar',
    expires: expiryDate
  }
}))

Cập nhật tất cả các packages hiện tại

NPM là một công cụ rất mạnh mẽ hỗ trợ quản lý các dependencies của ứng dụng, tuy nhiên các packages có thể tồn tại các lỗ hổng bảo mật có thể ảnh hưởng đến ứng dụng của bạn. Ứng dụng của bạn không thể đảm bảo được bảo mật nếu một trong các packages có lỗ hổng. Sử dụng các packages sau để kiểm tra bảo mật các packages bạn sử dụng:

Use either or both of the following two tools to help ensure the security of third-party packages that you use: nsp and Snyk.

nsp là một công cụ command-line giúp kiểm tra bảo mật dựa trên db các lỗ hổng đã biết.

$ npm i nsp -g
nsp check

Snyk cung cấp cả cli và Github integration để có thể check lỗ hổng nhanh và toàn diện hơn

$ npm install -g snyk
$ cd your-app
snyk test
snyk wizard

Tránh các lỗ hổng đã biết khác

Dưới đây là một số gợi ý bạn nên tham khảo để tăng cường bảo mật cho website của mình (đọc full tại đây https://blog.risingstack.com/node-js-security-checklist/)

  • Triển khai rate-limiting để ngăn chặn tấn công DDOS
  • Sử dụng csurf middleware để ngăn chặn (CSRF).
  • Luôn lọc và tiền xử lý user input để ngăn chặn tấn công cross-site scripting (XSS) và command injection.
  • Sử dụng parameterized queries hoặc prepared statements để ngăn chặn SQL injection.
  • Sử dụng sqlmap để chẩn đoán trước lỗi SQL injection vulnerabilities.
  • Sử dụng nmap and sslyze để test cài đặt SSL ciphers, keys...
  • Sử dụng safe-regex để đảm bảo tất cả các regular expressions không bị ảnh hưởng bởi regular expression denial of service

Tham khảo: https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS https://blog.risingstack.com/node-js-security-checklist/ https://letsencrypt.org/isrg/ https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations https://expressjs.com/en/advanced/best-practice-security.html https://msdn.microsoft.com/en-us/library/windows/desktop/aa380515(v=vs.85).aspx

All Rights Reserved