[Bài đọc] Các phương thức xác thực web

14. Bảo mật

HTTP Basic authentication

Xác thực HTTP Basic là một phương thức để client cung cấp username và password khi thực hiện yêu cầu.

Đây là cách đơn giản nhất có thể để thực thi kiểm soát truy cập vì nó không yêu cầu cookie, session hoặc bất kỳ thứ gì khác. Để sử dụng, client phải gửi tiêu đề Cấp phép (Authorization) cùng với mọi yêu cầu mà nó thực hiện. username và password không được mã hóa, nhưng được xây dựng theo cách:

  • username và password được nối vào một chuỗi duy nhất: username:password
  • chuỗi này được mã hóa với Base64
  • Từ khóa Basic  được đặt trước giá trị được mã hóa này

Ví dụ cho người dùng có tên là john  với mật khẩu secret:

curl --header "Authorization: Basic am9objpzZWNyZXQ=" my-website.com

Điều tương tự cũng có thể được quan sát thấy trong Chrome:

Việc thực hiện nó cũng khá dễ dàng trong Node.js – đoạn mã sau đây cho thấy cách bạn có thể làm một phần mềm trung gian Express.

import basicAuth from 'basic-auth';

function unauthorized(res) {
res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return res.send(401);
};

export default function auth(req, res, next) {
const {name, pass} = basicAuth(req) || {};

if (!name || !pass) {
return unauthorized(res);
};

if (name === 'john' && pass === 'secret') {
return next();
}
return unauthorized(res);
};
Tất nhiên, bạn có thể làm điều đó ở cấp độ cao hơn, như trong nginx.
Những hạn chế của việc sử dụng HTTP Basic authentication là gì?
Các khuyết điểm:
  • username và password được gửi cùng với mọi yêu cầu, có khả năng hiển thị chúng – ngay cả khi được gửi qua kết nối an toàn
  • Được kết nối với SSL / TLS, nếu trang web sử dụng mã hóa yếu hoặc kẻ tấn công có thể phá vỡ nó, tên người dùng và mật khẩu sẽ được hiển thị ngay lập tức
  • Không có cách nào để đăng xuất người dùng bằng cách sử dụng xác thực cơ bản
  • Hạn của thông tin đăng nhập không phải là không quan trọng – bạn phải yêu cầu người dùng thay đổi mật khẩu để làm như vậy
Cookies

Khi máy chủ nhận được HTTP request trong phản hồi, máy chủ có thể gửi tiêu đề Set-Cookie. Trình duyệt sẽ đưa nó vào một bình chứa cookie và cookie sẽ được gửi cùng với mọi yêu cầu được thực hiện cho cùng một nguồn gốc trong Cookie HTTP header
Để sử dụng cookie cho mục đích xác thực, có một vài nguyên tắc chính mà bạn phải tuân theo.
Luôn sử dụng HttpOnly cookies
Để giảm thiểu khả năng tấn công XSS luôn sử dụng cờ HttpOnly khi thiết lập cookie. Bằng cách này, họ sẽ không hiển thị trong document.cookies.

Luôn sử dụng cookie đã ký

Với cookie đã ký, máy chủ có thể biết cookie có được khách hàng sửa đổi hay không.
Điều này cũng có thể được quan sát thấy trong Chrome - trước tiên chúng ta hãy xem cách máy chủ thiết lập cookie:

Sau đó, tất cả các yêu cầu sử dụng tập hợp cookie cho miền đã cho:

Các khuyết điểm:

  • Cần phải nỗ lực nhiều hơn để giảm thiểu các cuộc tấn công CSRF
  • Không tương thích với REST – vì nó đưa vào một trạng thái thành một giao thức không trạng thái

Tokens
Ngày nay JWT (Mã thông báo Web JSON) ở mọi nơi – vẫn rất đáng xem xét các vấn đề bảo mật tiềm ẩn.
Trước tiên hãy xem JWT là gì!
JWT bao gồm ba phần:

  • Tiêu đề, chứa loại mã thông báo và thuật toán băm
  • Tải trọng, chứa các xác nhận quyền sở hữu
  • Chữ ký, có thể được tính như sau nếu bạn chọn HMAC SHA256:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Thêm JWT vào ứng dụng Koa chỉ một vài dòng mã:

var koa = require('koa');
var jwt = require('koa-jwt');
var app = koa();
app.use(jwt({
secret: 'very-secret'
}));
// Protected middleware
app.use(function *(){
// content of the token will be available on this.state.user
this.body = {
secret: '42'
};
});

Sử dụng ví dụ – (để kiểm tra tính hợp lệ / nội dung của mã thông báo, bạn có thể sử dụng jwt.io):

curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
my-website.com

Cũng giống như các phiên bản trước, các mã thông báo cũng có thể được quan sát trong Chrome:

Nếu bạn đang viết API cho các ứng dụng di động gốc hoặc SPA, JWT có thể phù hợp. Một điều cần nhớ: sử dụng JWT trong trình duyệt, bạn phải lưu trữ nó trong LocalStorage hoặc SessionStorage, điều này có thể dẫn đến các cuộc tấn công XSS.
Các khuyết điểm:
Cần phải nỗ lực nhiều hơn để giảm thiểu các cuộc tấn công XSS.

Signatures
Sử dụng cookie hoặc tokens, nếu lớp vận chuyển vì bất kỳ lý do nào bị lộ thông tin đăng nhập của bạn đều dễ truy cập – và với mã thông báo hoặc cookie, kẻ tấn công có thể hoạt động giống như người dùng thực.
Một cách có thể để giải quyết vấn đề này – ít nhất là khi chúng ta nói về các API và trình duyệt không phải ký vào mỗi yêu cầu. Nó hoạt động như thế nào?
Khi một người tiêu dùng của một API đưa ra một yêu cầu, nó phải ký nó, có nghĩa là nó phải tạo một băm từ toàn bộ yêu cầu bằng cách sử dụng một khóa riêng. Đối với phép tính băm mà bạn có thể sử dụng:
•    Phương thức HTTP
•    Đường dẫn của yêu cầu
•    Tiêu đề HTTP
•    Kiểm tra tải trọng HTTP
•    và một khóa riêng để tạo băm

Để làm cho nó hoạt động, cả người dùng API và nhà cung cấp phải có cùng khóa riêng. Khi bạn có chữ ký, bạn phải thêm chữ ký đó vào yêu cầu, trong chuỗi truy vấn hoặc tiêu đề HTTP. Ngoài ra, một ngày cũng nên được thêm vào, vì vậy bạn có thể xác định ngày hết hạn.

AWS Request Signing Flow
Tại sao phải trải qua tất cả các bước này? Bởi vì ngay cả khi lớp vận chuyển bị xâm nhập, kẻ tấn công chỉ có thể đọc lưu lượng truy cập của bạn, sẽ không thể hoạt động với tư cách người dùng vì kẻ tấn công sẽ không thể ký yêu cầu – vì khóa riêng không thuộc sở hữu của họ . Hầu hết các dịch vụ AWS đang sử dụng loại xác thực này.
node-http-signature giao dịch với HTTP Request Signing và đáng để kiểm tra.

Các khuyết điểm:
Không thể sử dụng trong trình duyệt / ứng dụng khách, chỉ giữa các API.

One-Time Passwords

Thuật toán One-Time passwords tạo mật khẩu một lần với bí mật dùng chung và thời gian hoặc bộ đếm hiện tại:
•    Thuật toán Time-based One-time Password dựa trên thời gian hiện tại,
•    Thuật toán HMAC-based One-time Password dựa trên bộ đếm.
Các phương thức này được sử dụng trong các ứng dụng tận dụng xác thực hai yếu tố: người dùng nhập username và password, sau đó cả máy chủ lẫn máy khách đều tạo mật khẩu một lần.
Trong Node.js, việc thực hiện điều này bằng cách sử dụng notp là tương đối dễ dàng.
Nhược điểm:
•    với mã thông báo người dùng được chia sẻ bí mật (nếu bị đánh cắp) có thể được mô phỏng
•    bởi vì khách hàng có thể bị đánh cắp / đi sai mỗi ứng dụng thời gian thực có phương pháp bỏ qua điều này, như thiết lập lại email bổ sung thêm hướng tấn công bổ sung vào ứng dụng

Phương thức xác thực web nào cần chọn khi nào?

Nếu bạn chỉ hỗ trợ ứng dụng web, cookie hoặc Tokens là tốt. Đối với cookie, hãy nghĩ về XSRF, để JWT quản lý XSS.
Nếu bạn phải hỗ trợ cả ứng dụng web và ứng dụng khách trên thiết bị di động, hãy đi với API hỗ trợ xác thực dựa trên Tokens.
Nếu bạn đang xây dựng các API giao tiếp với nhau, hãy thực hiện Signatures.

Leave a Reply

Your email address will not be published.