REST (hoặc REpresentational State Transfer) là một phong cách kiến trúc được mô tả lần đầu tiên trong luận án Tiến sĩ của Roy Fielding về Phong cách kiến trúc và Thiết kế Kiến trúc Phần mềm dựa trên Mạng.
Nó được phát triển khi Fielding viết các thông số kỹ thuật cho HTTP/1.1 và URI, và đã được chứng minh là rất phù hợp để phát triển các ứng dụng siêu phương tiện phân tán. Mặc dù REST được áp dụng rộng rãi hơn, nó được sử dụng phổ biến nhất trong bối cảnh giao tiếp với các dịch vụ qua HTTP.
Tài nguyên REST API được xác định bởi một URI, thường là một URL HTTP. Các thành phần REST sử dụng các trình kết nối để thực hiện các hành động trên một tài nguyên bằng cách sử dụng một biểu diễn để nắm bắt trạng thái hiện tại hoặc dự kiến của tài nguyên và chuyển giao biểu diễn đó.
Các loại kết nối chính là client và server, các kết nối phụ bao gồm cache, resolver và tunnel.
REST API không có trạng thái. Các API có trạng thái không tuân theo kiểu kiến trúc REST. Trạng thái (state) trong từ viết tắt REST đề cập đến trạng thái của tài nguyên mà API truy cập, không phải trạng thái của phiên trong đó API được gọi - session. Mặc dù có thể có những lý do chính đáng để xây dựng một API có trạng thái, nhưng điều quan trọng là phải nhận ra rằng việc quản lý các phiên là phức tạp và khó thực hiện một cách an toàn.
Các dịch vụ có trạng thái nằm ngoài phạm vi của Cheat Sheet này: Lưu chuyển trạng thái từ client sang backend, trong khi làm cho dịch vụ không trạng thái về mặt kỹ thuật, là một mô hình nên tránh vì nó dễ bị các cuộc tấn công mạo danh.
Để triển khai các luồng với REST API, các tài nguyên thường được tạo, đọc, cập nhật và xóa. Ví dụ: một trang web thương mại điện tử có thể cung cấp các phương pháp để tạo một giỏ hàng trống, để thêm các mặt hàng vào giỏ hàng và kiểm tra giỏ hàng. Mỗi cuộc gọi REST này không có trạng thái và điểm cuối phải kiểm tra xem người gọi có được ủy quyền để thực hiện hoạt động được yêu cầu hay không.
Một tính năng chính khác của các ứng dụng REST là sử dụng các động từ-verb HTTP tiêu chuẩn và mã lỗi để tránh sự thay đổi không cần thiết giữa các dịch vụ khác nhau.
Một tính năng chính khác của các ứng dụng REST là sử dụng HATEOAS hoặc Hypermedia As The Engine of Application State. Điều này cung cấp cho các ứng dụng REST tính chất tự lập tài liệu, giúp các nhà phát triển tương tác với dịch vụ REST dễ dàng hơn mà không cần phải biết về nó trước.
HTTPS
Các dịch vụ REST an toàn chỉ cung cấp đến các điểm cuối sử dung HTTPS. Điều này bảo vệ thông tin xác thực khi chuyển tiếp, ví dụ: mật khẩu, khóa API hoặc JSON Web Tokens. Nó cũng cho phép khách hàng xác thực dịch vụ và đảm bảo tính toàn vẹn của dữ liệu được truyền.
Cân nhắc việc sử dụng các chứng chỉ ở phía client, đã được xác thực lẫn nhau để cung cấp khả năng bảo vệ bổ sung cho các dịch vụ web có đặc quyền cao.
Kiểm soát truy cập
Các dịch vụ REST không công khai phải thực hiện kiểm soát truy cập tại mỗi điểm cuối API. Các dịch vụ web trong các ứng dụng nguyên khối thực hiện điều này bằng cách xác thực người dùng, logic ủy quyền và quản lý phiên. Điều này có một số hạn chế đối với các kiến trúc hiện đại tạo ra nhiều dịch vụ nhỏ theo phong cách RESTful.
+ Để giảm thiểu độ trễ và giảm sự ghép nối giữa các dịch vụ, quyết định kiểm soát truy cập phải được thực hiện cục bộ bởi các điểm cuối REST
+ Xác thực người dùng phải được tập trung trong Nhà cung cấp danh tính (IdP), nơi cấp access token.
JWT
Dường như có một xu hướng sử dụng JSON Web Tokens (JWT) làm định dạng cho mã thông báo bảo mật. JWT là cấu trúc dữ liệu JSON chứa một tập hợp các xác nhận quyền sở hữu có thể được sử dụng cho các quyết định kiểm soát truy cập. Chữ ký mật mã hoặc mã xác thực tin nhắn (MAC) có thể được sử dụng để bảo vệ tính toàn vẹn của JWT.
Đảm bảo JWT được bảo vệ toàn vẹn bằng chữ ký hoặc MAC. Không cho phép các JWT không an toàn:.
+ Đảm bảo JWT được bảo vệ toàn vẹn bằng chữ ký hoặc MAC. Không cho phép các JWT không an toàn: {"alg":"none"}.
+ Nói chung, chữ ký nên được ưu tiên hơn MAC để bảo vệ tính toàn vẹn của JWT.
Nếu MAC được sử dụng để bảo vệ tính toàn vẹn, mọi dịch vụ có thể xác thực JWT cũng có thể tạo JWT mới bằng cách sử dụng cùng một khóa. Điều này có nghĩa là tất cả các dịch vụ sử dụng cùng một khóa phải tin cậy lẫn nhau. Một hệ quả khác của điều này là sự thỏa hiệp của bất kỳ dịch vụ nào cũng làm ảnh hưởng đến tất cả các dịch vụ khác chia sẻ cùng một khóa.
Bên phụ thuộc hoặc người dùng có mã thông báo xác thực JWT bằng cách xác minh tính toàn vẹn của nó và các claims có trong đó.
Bên phụ thuộc phải xác minh tính toàn vẹn của JWT dựa trên cấu hình riêng hoặc logic được mã hóa cứng. Nó không được dựa vào thông tin của header JWT để chọn thuật toán xác minh.
Một số xác nhận quyền sở hữu đã được tiêu chuẩn hóa và nên có trong JWT được sử dụng để kiểm soát truy cập. Ít nhất những điều sau đây trong số các công bố tiêu chuẩn phải được xác minh:
+ iss hoặc issuers-nhà phát hành - đây có phải là nhà phát hành đáng tin cậy không? Nó có phải là chủ sở hữu của khóa đã ký không?
+ aud hoặc audience - có phải đối tượng có quan tâm đến JWT này không?
+ exp hoặc expiration time - thời điểm hiện tại có phải là thời điểm trước khi kết thúc thời hạn hiệu lực của mã thông báo này không?
+ nbf or not before time- thời điểm hiện tại có phải sau thời điểm bắt đầu thời hạn hiệu lực của mã thông báo này không?
Vì JWT chứa thông tin chi tiết về thực thể được xác thực (người dùng, v.v.), ngắt kết nối có thể xảy ra giữa JWT và trạng thái hiện tại của phiên người dùng, ví dụ: nếu phiên bị kết thúc sớm hơn thời gian hết hạn do đăng xuất rõ ràng hoặc không hoạt động. Khi sự kiện kết thúc phiên xảy ra, thông báo hoặc hash của bất kỳ JWT nào được liên kết phải được gửi đến danh sách khối trên API. Danh sách này sẽ làm mất hiệu lực JWT đó đối với bất kỳ yêu cầu nào cho đến khi token hết hạn.
Khóa API
Các dịch vụ REST public mà không có kiểm soát truy cập có nguy cơ bị khai thác dẫn đến các hóa đơn băng thông hoặc chu kỳ tính toán quá mức. Các khóa API có thể được sử dụng để giảm thiểu rủi ro này. Chúng cũng thường được tổ chức sử dụng để kiếm tiền từ các API; thay vì chặn các cuộc gọi tần suất cao, khách hàng được cấp quyền truy cập theo gói truy cập đã mua.
Khóa API có thể làm giảm tác động của các cuộc tấn công từ chối dịch vụ. Tuy nhiên, khi chúng được phát hành cho khách hàng bên thứ ba, chúng tương đối dễ thỏa hiệp.
+ Yêu cầu khóa API cho mọi yêu cầu tới điểm cuối được bảo vệ.
+ Trả lại Code 429 Too Many Requests trong phản hồi HTTP nếu các yêu cầu đến quá nhanh.
+ Thu hồi khóa API nếu khách hàng vi phạm thỏa thuận sử dụng.
+ Không dựa hoàn toàn vào các khóa API để bảo vệ các tài nguyên nhạy cảm, quan trọng hoặc có giá trị cao.
Siết chặt các phương thức HTTP
+Áp dụng chính sách với danh sách chỉ cho phép một số các Phương thức HTTP, ví dụ: GET, POST, PUT.
+Từ chối tất cả các yêu cầu không khớp với danh sách cho phép với mã phản hồi HTTP 405 Method not allowed.
+Đảm bảo rằng người gọi được phép sử dụng phương thức HTTP đến trên bộ sưu tập tài nguyên, hành động và bản ghi.
Kiểm tra đầu vào
+Không tin tưởng các tham số/đối tượng (parameters/objects) đầu vào.
+Xác thực đầu vào: độ dài / phạm vi / định dạng và loại.
+Đạt được xác thực đầu vào ngầm định bằng cách sử dụng các kiểu dữ liểu như số, boolean, ngày, giờ hoặc phạm vi dữ liệu cố định trong các tham số API.
+Ràng buộc đầu vào chuỗi bằng regexps.
+Từ chối nội dung không mong muốn / bất hợp pháp.
+Sử dụng các thư viện hoặc khuôn khổ xác thực/sàng lọc bằng ngôn ngữ cụ thể của bạn.
+Xác định giới hạn kích thước yêu cầu thích hợp và từ chối các yêu cầu vượt quá giới hạn với mã phản hồi HTTP 413 Request Entity Too Large..
+Phân tích nhật ký xác thực đầu vào không thành công. Giả sử rằng ai đó đang thực hiện hàng trăm lần xác thực đầu vào không thành công mỗi giây là không tốt.
+Hãy xem cheat sheet xác thực đầu vào để được giải thích toàn diện.
+Sử dụng trình phân tích cú pháp an toàn để phân tích cú pháp các tin nhắn đến. Nếu bạn đang sử dụng XML, hãy đảm bảo sử dụng trình phân tích cú pháp không dễ bị XXE và các cuộc tấn công tương tự.
Xác thực các loại nội dung
Nội dung phản hồi hoặc yêu cầu REST phải khớp với loại nội dung đề ra trong tiêu đề. Nếu không, điều này có thể gây ra sự hiểu sai ở phía người dùng / nhà sản xuất và dẫn đến việc chèn / thực thi mã.
Ghi lại tất cả các loại nội dung được hỗ trợ trong API của bạn.
Xác thực các loại nội dung yêu cầu
Từ chối các yêu cầu chứa tiêu đề loại nội dung không mong muốn hoặc bị thiếu với mã phản hồi Unacceptable or 415 Unsupported Media Type.
Đối với các loại nội dung XML, đảm bảo tăng cường trình phân tích cú pháp XML thích hợp.
Tránh vô tình để lộ các loại nội dung không mong muốn bằng cách xác định rõ ràng các loại nội dung, ví dụ: Jersey (Java): @consumes("application/json"); @produces("application/json"). Điều này tránh các vectơ tấn công XXE chẳng hạn.
Gửi các loại nội dung phản hồi an toàn
Thông thường các dịch vụ REST cho phép nhiều loại phản hồi (ví dụ: application/xml hoặc application/json và ứng dụng khách chỉ định thứ tự ưu tiên của các loại phản hồi bằng tiêu đề Accept trong yêu cầu.
KHÔNG chỉ sao chép tiêu đề Accept vào tiêu đề Content-type của phản hồi.
Từ chối yêu cầu (với phản hồi 406 Not Acceptable) nếu tiêu đề Accept không chứa một trong các loại được cho phép cụ thể.
Các dịch vụ bao gồm mã tập lệnh (ví dụ: JavaScript) trong phản hồi của chúng phải đặc biệt cẩn thận để bảo vệ khỏi cuộc tấn công chèn tiêu đề.
Đảm bảo gửi các tiêu đề loại nội dung mong muốn trong phản hồi của bạn phù hợp với nội dung của bạn, ví dụ: application/json chứ không phải application/javascript.
Quản lý điểm cuối
Tránh để lộ các điểm cuối quản lý qua Internet.
Nếu các điểm cuối quản lý phải có thể truy cập được qua Internet, hãy đảm bảo rằng người dùng phải sử dụng cơ chế xác thực mạnh, ví dụ: đa yếu tố multi-factor.
Tốt nhất là hiển thị các điểm cuối quản lý qua các cổng hoặc máy chủ HTTP khác nhau trên một NIC khác và một số subnet nhất định.
Hạn chế quyền truy cập vào các điểm cuối này bằng các quy tắc tường lửa hoặc sử dụng danh sách kiểm soát truy cập.
Xử lý lỗi
Trả lời bằng các thông báo lỗi chung chung - tránh tiết lộ chi tiết về lỗi một cách không cần thiết.
Không chuyển các chi tiết kỹ thuật (ví dụ: call stacks hoặc các thông tin nội bộ khác) cho khách hàng.
Nhật ký - Log kiểm tra
Viết log kiểm tra trước và sau các sự kiện liên quan đến bảo mật.
Cân nhắc ghi lại các lỗi xác thực mã thông báo để phát hiện các cuộc tấn công.
Đề phòng các cuộc tấn công nhằm vào log bằng cách làm sạch trước dữ liệu log
Tiêu đề bảo mật - Security Headers
Có một số tiêu đề liên quan đến bảo mật có thể được trả về trong phản hồi HTTP để hướng dẫn trình duyệt hoạt động theo những cách cụ thể. Tuy nhiên, một số tiêu đề này nhằm mục đích chỉ sử dụng với các phản hồi HTML và như vậy có thể cung cấp ít hoặc không có lợi ích bảo mật trên một API mà không trả về HTML.
Các tiêu đề sau nênđược bao gồm trong tất cả các phản hồi API:
Cache-Control: no-store | Ngăn thông tin nhạy cảm được lưu vào bộ nhớ đệm. |
Content-Security-Policy: frame-ancestors 'none' | Để bảo vệ khỏi các cuộc tấn công clickjacking kiểu kéo và thả. |
Content-Type | Để chỉ định loại nội dung của phản hồi. Đây phải là application/json cho các phản hồi JSON. |
Strict-Transport-Security | Để yêu cầu kết nối qua HTTPS và để bảo vệ khỏi các chứng chỉ giả mạo. |
X-Content-Type-Options: nosniff | Để ngăn trình duyệt thực hiện tính năng dò tìm MIME và phân giải phản hồi dưới dạng HTML một cách không phù hợp. |
X-Frame-Options: DENY | Để bảo vệ khỏi các cuộc tấn công clickjacking kiểu kéo và thả. |
Content-Security-Policy: default-src 'none' | Phần lớn chức năng của CSP chỉ ảnh hưởng đến các trang được hiển thị dưới dạng HTML. |
Feature-Policy: 'none' | Chính sách tính năng chỉ ảnh hưởng đến các trang được hiển thị dưới dạng HTML. |
Referrer-Policy: no-referrer | Các phản hồi không phải HTML sẽ không kích hoạt các yêu cầu bổ sung. |
Chia sẻ tài nguyên đa nguồn - Cross-Origin Resource Sharing (CORS) là một tiêu chuẩn của W3C để chỉ định một cách linh hoạt những yêu cầu miền chéo nào được phép. Bằng cách cung cấp các Tiêu đề CORS thích hợp, các tín hiệu API REST của bạn tới trình duyệt mà các miền hoặc là origins, được phép thực hiện các lệnh gọi JavaScript tới dịch vụ REST.
+Tắt tiêu đề CORS nếu cuộc gọi giữa nhiều miền không được hỗ trợ/mong đợi.
+Hãy cụ thể nhất có thể và chung chung khi cần thiết khi thiết lập nguồn gốc của các cuộc gọi giữa nhiều miền.
Sensitive information in HTTP requests
Các dịch vụ web REST nên cẩn thận để ngăn chặn thông tin xác thực bị rò rỉ. Mật khẩu, mã thông báo bảo mật và khóa API không được xuất hiện trong URL, vì điều này có thể được ghi lại trong nhật ký máy chủ web, điều này làm cho chúng có giá trị về bản chất.
Trong yêu cầu POST / PUT, dữ liệu nhạy cảm phải được chuyển trong phần nội dung yêu cầu hoặc tiêu đề yêu cầu.
Trong yêu cầu GET, dữ liệu nhạy cảm phải được chuyển trong HTTP Header.
OK:
https://example.com/resourceCollection/[ID]/action
NOT OK:
https://example.com/controller/123/a...a53f435643de32
Mã trả về HTTP
HTTP xác định mã trạng thái. Khi thiết kế API REST, đừng chỉ sử dụng 200 cho thành công hoặc 404 cho lỗi. Luôn sử dụng mã trạng thái phù hợp về ngữ nghĩa cho phản hồi.
Đây là bảng chưa đầy đủ các mã trạng thái API REST liên quan đến bảo mật. Sử dụng nó để đảm bảo bạn trả lại đúng mã.
200 | OK | Phản hồi cho một hành động API REST thành công. Phương thức HTTP có thể là GET, POST, PUT, PATCH hoặc DELETE. |
201 | Created | Yêu cầu đã được thực hiện và tài nguyên đã được tạo. Một URI cho tài nguyên đã tạo được trả về trong tiêu đề Location. |
202 | Accepted | Yêu cầu đã được chấp nhận để xử lý, nhưng quá trình xử lý vẫn chưa hoàn tất. |
301 | Moved Permanently | Chuyển hướng trang vĩnh viễn. |
304 | Not Modified | Phản hồi liên quan đến bộ nhớ đệm đã trả về khi client có cùng bản sao của tài nguyên với máy chủ. |
307 | Temporary Redirect | Chuyển hướng tạm thời của tài nguyên. |
400 | Bad Request | Yêu cầu không đúng định dạng, chẳng hạn như lỗi định dạng nội dung thư. |
401 | Unauthorized | ID/mật khẩu xác thực không được cung cấp. |
403 | Forbidden | Nó được sử dụng khi xác thực thành công nhưng người dùng được xác thực không có quyền đối với tài nguyên yêu cầu. |
404 | Not Found | Khi một tài nguyên không tồn tại được yêu cầu. |
405 | Method Not Acceptable | Lỗi đối với một phương thức HTTP không mong muốn. Ví dụ: API REST đang mong đợi HTTP GET, nhưng HTTP PUT được sử dụng. |
406 | Unacceptable | Người dùng đã gửi một loại nội dung trong tiêu đề Accept không được API máy chủ hỗ trợ. |
413 | Payload too large | Sử dụng nó để báo hiệu rằng kích thước yêu cầu đã vượt quá giới hạn đã cho, ví dụ: liên quan đến tải lên tệp. |
415 | Unsupported Media Type | Loại nội dung được yêu cầu không được dịch vụ REST hỗ trợ. |
429 | Too Many Requests | Lỗi khi có thể có cuộc tấn công DOS được phát hiện hoặc yêu cầu bị từ chối do giới hạn tốc độ. |
500 | Internal Server Error | Một điều kiện không mong muốn đã ngăn máy chủ thực hiện yêu cầu. Lưu ý rằng phản hồi không được tiết lộ thông tin nội bộ giúp kẻ tấn công, ví dụ: thông báo lỗi chi tiết hoặc stack traces. |
501 | Not Implemented | Dịch vụ REST chưa triển khai hoạt động được yêu cầu. |
503 | Service Unavailable | Dịch vụ REST tạm thời không thể xử lý yêu cầu. Được sử dụng để thông báo cho khách hàng rằng nó sẽ thử lại sau. |