Bài học đầu tiên: don lồng rò rỉ bí mật của bạn trong một minh họa bài trung bình

Cách tốt nhất để lưu trữ bí mật trong ứng dụng của bạn là không lưu trữ bí mật trong ứng dụng của bạn

Disclaimer: phương pháp được mô tả trong bài viết này phụ thuộc rất nhiều vào AWS. Điều đó đang được nói, khái niệm này vẫn có thể áp dụng cho các nhà cung cấp khác

Nếu bạn đã từng xây dựng một ứng dụng trên Internet, bạn đã gặp phải cuộc đấu tranh giữ bí mật (thông tin cơ sở dữ liệu, khóa api, v.v.) trên máy chủ của bạn.

Trong lịch sử, các nhà phát triển đã tìm thấy một số cách để đạt được điều này. Mỗi người trong số họ mang một mức độ an toàn và thuận tiện nhất định. Tôi sẽ dẫn bạn đi qua chúng để bạn có thể cảm nhận được nơi chúng ta đến.

Lưu trữ bí mật trong mã của bạn

# settings / instance_sinstall.py
STRIPE_API_KEY = '3ef8-843a-49dc-a34d' # Đừng nói với ai! làm ơn

Đây rõ ràng là phương pháp thuận tiện nhất. Bạn viết khóa API trong mã của mình dưới dạng hằng số, sau đó bạn đẩy nó vào kiểm soát nguồn của mình và voilà!

Nhưng, nó cũng là phương pháp ít an toàn nhất. Bạn chỉ cho phép một bí mật quan trọng được lan truyền trên mọi máy tính của nhà phát triển (hoặc ổ đĩa ngoài), trên bộ lưu trữ của nhà cung cấp kiểm soát nguồn của bạn, trên máy chủ của nhà cung cấp CI của bạn, v.v. Điều này làm tăng nguy cơ bí mật này có thể bị rò rỉ.

Lưu trữ bí mật trong môi trường

Stripe_api_key = os.envir ["STRIPE_API_KEY"]

Đây là một cái tôi đã sử dụng khá thường xuyên. Bạn có thể cần phải tự đặt các biến môi trường đó trên mỗi máy chủ hoặc sử dụng một số loại trình điều khiển để xử lý việc đó cho bạn, điều này hơi thuận tiện hơn so với phương pháp trước đó. Mặc dù vậy, nó có lợi ích là chỉ một số cá nhân đáng tin cậy có quyền truy cập vào nó.

Vẫn còn một số vấn đề: cấu hình sai đơn giản (như chạy máy chủ sản xuất ở chế độ gỡ lỗi) hoặc lỗi bảo mật có thể dẫn đến rò rỉ tất cả các biến môi trường.

Lưu trữ bí mật trong cơ sở dữ liệu

Tôi sẽ giải quyết ngắn gọn về vấn đề này: bạn sẽ vẫn cần phải có thông tin cơ sở dữ liệu của mình bên ngoài ở đâu đó do đó đánh bại mục đích đưa bí mật của bạn vào đó. Ngoài ra, việc sao lưu hàng ngày tất cả các dịch vụ của bạn Các khóa API API cũng làm tăng nguy cơ rò rỉ tại một số điểm.

Sử dụng dịch vụ đồng bộ hóa bí mật

Có SaaS đề nghị chăm sóc các khóa API và các bí mật khác cho bạn. Họ giữ chúng an toàn và cho phép bạn truy vấn chúng từ dịch vụ của họ khi cần thiết. Chúng tôi vẫn phải đối mặt với cùng một vấn đề như phương pháp trước: bạn sẽ cần một khóa API rất bí mật để có được tất cả các khóa API của mình.

Lưu trữ bí mật trong mã của bạn nhưng được mã hóa

Một phiên bản hiện đại của phương pháp đầu tiên là mã hóa các bí mật trong mã của bạn, do đó không tiết lộ giá trị của chúng cho kiểm soát nguồn của bạn, các nhà phát triển khác, v.v. Tuy nhiên, để giải mã những bí mật đó, máy chủ vẫn cần quản lý khóa. Điều này trở lại với vấn đề phân phối và duy trì một bí mật lớn mở ra tất cả các bí mật khác.

Tại sao nó không an toàn?

Các phương pháp này đều có chung đặc điểm; họ vẫn liên quan đến việc có những bí mật trên máy chủ của bạn và những thứ đó có thể bị rò rỉ hoặc bị đánh cắp

Trường hợp xấu nhất

Hãy tưởng tượng kịch bản sau đây. Kẻ tấn công đã đột nhập vào máy chủ của bạn bằng lỗ hổng trong Apache. Anh ấy / cô ấy sau đó bắt đầu tìm kiếm thông tin xác thực cơ sở dữ liệu và khóa API trong tệp cấu hình, mã của bạn, môi trường. Nếu bí mật của bạn bằng cách nào đó được ẩn / mã hóa đủ, kẻ tấn công đã giành được bất cứ thứ gì. Nhưng điều đó không có nghĩa là anh ấy / cô ấy sẽ dừng ở đó. Sử dụng một cái gì đó như LiME, tin tặc vẫn có thể duyệt trong bãi chứa bộ nhớ máy chủ để giải nén những bí mật đó.

Chúng ta có thể làm tốt hơn

Giới thiệu:

Truy cập dịch vụ không có thông tin xác thực bằng Cổng API xác thực IAM làm proxy ™

(Tôi rất kinh khủng khi tìm thấy những cái tên hấp dẫn và điều này không thực sự được đăng ký nhãn hiệu)

Tổng quan

Tóm lại, chúng tôi sử dụng vai trò cá thể của đối tượng EC2 để thực hiện cuộc gọi an toàn tới API Gateway, sau đó ủy quyền cho dịch vụ mong muốn, sau khi đã thay đổi yêu cầu bằng cách thêm thông tin đăng nhập cần thiết. Ew! Rằng rất nhiều thông tin cho một câu.

Họ nói rằng một bức tranh đáng giá 1000 từ. THÁCH THỨC CHẤP NHẬN

Vẫn bị mất? Hãy cùng mổ xẻ điều này

Trước tiên, để làm việc này, chúng ta cần sử dụng cách riêng cho các thể hiện EC2 (hoặc ECS Container và Lambdas) để thực hiện các cuộc gọi đến các tài nguyên AWS khác, bằng cách sử dụng các vai trò IAM.

Thứ hai, chúng ta cần tạo tài nguyên API còn lại trong API Gateway. Có một số cấu hình cụ thể cần được áp dụng để phần thân, tiêu đề và tham số truy vấn có thể được chuyển qua. Ngoài ra, chúng tôi cần thay đổi yêu cầu để có thể đưa thông tin xác thực dịch vụ được nhắm mục tiêu. Cuối cùng, chúng ta phải kích hoạt vũ khí bí mật: ủy quyền dựa trên IAM.

Bước thứ ba và cuối cùng bao gồm việc ký URL trước khi thực hiện cuộc gọi đến các dịch vụ ủy quyền mong muốn.

¿Quế?

Đối với những người bạn không quá quen thuộc với các công nghệ mà tôi đã đề cập và vẫn không chắc chắn về tất cả những thứ này, thì đây là một so sánh trước và sau khi sử dụng quyền truy cập dịch vụ không có Thông tin xác thực bằng cách sử dụng Cổng API xác thực IAM làm proxy ™:

Tôi sẽ sử dụng API và Postman GitHub nổi tiếng cho phần trình diễn này:

Trước (Gọi trực tiếp đến GitHub):

After (Gọi proxy qua API Gateway):

Tôi đã có thể nghe bạn nói:

Bạn nói với chúng tôi đây là thông tin không có thông tin xác thực và tôi thấy khóa truy cập, khóa bí mật và mã thông báo !!!

Điều này là do máy tính xách tay của tôi không có vũ khí bí mật. Khi bạn nhận được điều này và chạy trên một phiên bản EC2, các thông tin bảo mật tạm thời này sẽ được tự động truy xuất từ ​​siêu dữ liệu phiên bản. Nếu khái niệm thông tin đăng nhập tạm thời là mới đối với bạn, thì đây là một đoạn trích từ tài liệu (nhấn mạnh của tôi):

Một ứng dụng trên ví dụ [Hoài] được cấp quyền cho các hành động và tài nguyên mà bạn đã xác định cho vai trò thông qua thông tin xác thực bảo mật được liên kết với vai trò. Các thông tin bảo mật này là tạm thời và chúng tôi tự động xoay chúng. Chúng tôi cung cấp thông tin đăng nhập mới ít nhất năm phút trước khi hết hạn thông tin đăng nhập cũ.

Vì vậy, công bằng mà nói, một mô tả chính xác hơn cho phương pháp này sẽ là truy cập Dịch vụ bằng cách sử dụng Cổng API xác thực IAM làm proxy mà không cần sử dụng thông tin xác thực dài hạn. Tuy nhiên, chúng tôi có thể đồng ý rằng các thông tin tạm thời ngắn hạn được sử dụng để ký các cuộc gọi đến các dịch vụ ủy quyền bị giới hạn thông qua IAMiến là cách ít hấp dẫn hơn đối với những kẻ tấn công so với các khóa API thông thường và các bí mật dài hạn khác.

Đây là một nâng cấp lớn từ góc độ bảo mật

Cải tiến bảo mật đáng chú ý:

  • Thông tin tạm thời không bao giờ phải được xử lý bởi các nhà phát triển
  • Chúng được truy vấn theo chương trình, do đó, không cần phải ghi chúng vào tập tin cấu hình
  • Nếu bị rò rỉ hoặc bị đánh cắp, những thông tin tạm thời này sẽ hoạt động tối đa một giờ
  • Tất cả các yêu cầu có thể được đăng nhập vào CloudWatch để kiểm toán
  • Bạn có thể hạn chế API được nhắm mục tiêu bằng chính sách IAM

Điểm đạn cuối cùng đặc biệt hữu ích khi làm việc với API như GitHub thiếu mô hình cấp phép chi tiết hơn. Sử dụng chính sách IAM sau đây, tôi có thể hạn chế API của mình chỉ cho phép phương thức GET trên điểm cuối / repos / PokaInc / test-github-api / vấn đề.

{
    "Phiên bản": "2012-10-17",
    "Tuyên bố": [
        {
            "Hoạt động": [
                "thực thi-api: Gọi"
            ],
            "Nguồn": [
                "arn: aws: exec-api: us-East-1: 123456789010: w974f1rs6e / dev / GET / repos / PokaInc / test-github-api / vấn đề"
            ],
            "Hiệu ứng": "Cho phép"
        }
    ]
}

Nhưng xin chờ chút nữa !

Các lợi ích khác của việc sử dụng API Gateway làm proxy

  • Thống kê sử dụng. Điều này có thể hữu ích để xác định xu hướng và ngăn chặn giới hạn tỷ lệ từ các dịch vụ của bên thứ ba.
  • Ghi nhật ký. Khi được bật, bạn có thể có nhật ký chi tiết của từng yêu cầu bao gồm nguồn gốc và tham số được sử dụng.
  • Bộ nhớ đệm. Có vấn đề về độ trễ hoặc giới hạn tỷ lệ? Với ba dòng mã CloudFormation, bạn có thể thêm phụ trợ bộ đệm vào proxy của mình.
  • Phát triển địa phương. Các nhà phát triển sử dụng người dùng IAM tại địa phương có thể truy cập trực tiếp vào các dịch vụ ủy quyền thay vì dựa vào thông tin được mã hóa cứng trên máy tính của họ.

Tại thời điểm này, tôi sẽ cho rằng bạn đã bán ý tưởng và bạn muốn thử phương pháp này cho chính mình.

Mật mã

Xem xét ở đây tại Poka, chúng tôi là CloudFormation afi · cio · nados, tôi đã tạo ra một mẫu bằng chứng khái niệm có sẵn trên GitHub.

Dự phòng

Để tạo proxy, hãy làm theo các hướng dẫn trong README.md.

Sử dụng proxy

Điều này cũng được mô tả trong readme, nhưng tôi sẽ nhúng nó vào đây để tôi có thể thuyết phục bạn rằng nó không phải là ma thuật đen.

Hãy cùng xem lại khối mã này:

trả lại AWSRequestsAuth (
      [...]
      ** boto_utils.get_credentials ()
)

Đây là nơi chúng ta thường sẽ thấy các thông tin được mã hóa cứng, truy cập vào tệp cấu hình hoặc truy vấn môi trường. Thay vào đó, phương pháp này yêu cầu dịch vụ siêu dữ liệu cho các khóa tạm thời. Nếu vai trò EC2 có đủ quyền, cuộc gọi sẽ chuyển đến GitHub, nếu không, API Gateway sẽ từ chối nó.

Phần kết luận

Tôi hy vọng bài đăng này đã giúp nâng cao nhận thức về các bí mật được bảo mật kém trong các máy chủ ứng dụng và cách sử dụng API Gateway làm proxy có thể mang lại lợi ích cho bạn ngoài bảo mật được thêm vào.

Hãy cẩn thận (và cách giải quyết của họ)

  • Điều gì xảy ra nếu tôi muốn ủy quyền một dịch vụ nội bộ không được tiếp xúc với internet?

Các giải thích có thể có bài viết blog riêng của mình. Nhưng câu chuyện dài, bạn có thể cung cấp AWS Lambda được bật VPC làm mục tiêu cho proxy API Gateway của bạn. Lambda sẽ phải chuyển các tiêu đề, tham số truy vấn và phần thân cho dịch vụ nội bộ, thu thập phản hồi và trả lại cho API Gateway.

  • Điều này hoạt động rất tốt với API REST nhưng còn các dịch vụ TCP như cơ sở dữ liệu quan hệ hoặc máy chủ bộ đệm thì sao?

Một lần nữa, điều này sẽ xứng đáng với một bài viết blog hoàn chỉnh. Tóm lại, chúng tôi có thể tạo một dịch vụ vi mô (có thể truy cập thông qua, bạn đoán nó, Cổng API xác thực IAM) sẽ tạo thông tin đăng nhập nhanh chóng cho các dịch vụ mong muốn. Ví dụ: nếu dịch vụ vi mô được yêu cầu thông tin đăng nhập PostgreSQL, nó có thể ban hành lệnh CREATE ROLE với mật khẩu được tạo ngẫu nhiên. Ngoài ra, vai trò có thể có thời gian tồn tại bằng cách sử dụng thuộc tính VALID UNTIL.

Lựa chọn thay thế

Bạn không chạy khối lượng công việc sản xuất của mình trên AWS? Phương pháp này có thể làm việc cho bạn? Có những công cụ khác có thể giúp bạn giải quyết vấn đề quản lý bí mật.

  • http://engineering.nike.com/cerberus/
  • https://www.vaultproject.io/
  • https://docs.docker.com/engine/swarm/secrets/

Tài liệu tham khảo cho bài viết này:

http://blog.arkency.com/2017/07/how-to-safely-store-api-keys-in-rails-apps/
https://blog.rackspace.com/securing-application-secrets-with-ec2-parameter-store
https://www.envkey.com/
https://www.hashicorp.com/blog/Vault-announcement/
https://docs.docker.com/engine/swarm/secrets/
http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html
http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html
http://docs.aws.amazon.com/general/latest/gr/signature-v4-examples.html

Đặc biệt cảm ơn Tea Rudolf, Etienne Talbot, Simon-Pierre Gingras, Maxime Leblanc và Marilou Simard-Baril vì đã sửa chữa (Vâng, tôi cần nhiều người xem lại tiếng Anh của tôi) và cảm ơn Julie Dorion-Bélanger cho các minh họa.

Có câu hỏi / gợi ý về bài đăng này? Viết bình luận bên dưới và tôi sẽ cố hết sức để trả lời.