Tập lệnh người dùng hộp cát an toàn trong chương trình C ++


8

Tôi đã làm việc trên một dự án cá nhân trong C # với mục đích ít nhiều là cho phép người dùng thực thi các tập lệnh được viết bởi người dùng khác và hạn chế quyền của tập lệnh đó. Chương trình của tôi biên dịch các tập lệnh bằng thư viện của bên thứ ba, tạo hộp cát cho chúng bằng các cơ chế bảo mật truy cập mã .NET và đảm bảo rằng chúng chỉ có các quyền mà người dùng muốn cấp cho chúng.

Nói rộng ra, yêu cầu bảo mật của tôi là:

  • người dùng sẽ có thể hạn chế quyền truy cập của tập lệnh không đáng tin cậy vào chỉ một số phần nhất định của hệ thống tệp, bao gồm cấm tất cả quyền truy cập hệ thống tệp
  • người dùng sẽ có thể hạn chế các kết nối mạng của tập lệnh không tin cậy ở một số địa chỉ IP hoặc tên máy chủ nhất định, bao gồm cấm tất cả các kết nối mạng
  • Không sao nếu tập lệnh người dùng quản lý để treo hoặc chấm dứt ứng dụng máy chủ, nhưng tập lệnh người dùng không thể tránh được các hạn chế về quyền (nghĩa là từ chối dịch vụ là được, vi phạm không được)

Tôi đang suy nghĩ về việc cố gắng làm một cái gì đó tương tự trong C ++, như một dạng bài tập cá nhân. Rõ ràng, mọi thứ phức tạp hơn khi chạy mã gốc trực tiếp, ngay cả khi tập lệnh người dùng được viết bằng ngôn ngữ kịch bản như Lua.

Cách tiếp cận đầu tiên tôi có thể nghĩ đến là chèn các hook của riêng tôi vào các chức năng thư viện chuẩn của môi trường script. Ví dụ: nếu ngôn ngữ kịch bản là Lua, thay vì hiển thị io.open bình thường, tôi sẽ phải hiển thị trình bao bọc kiểm tra các đối số chống lại quyền của tập lệnh trước khi chuyển chúng sang triển khai ban đầu.

Mối quan tâm của tôi với cách tiếp cận này là nó làm tăng đáng kể số lượng mã của riêng tôi chịu trách nhiệm bảo mật và do đó, một lỗ hổng bảo mật tiềm ẩn mà tôi tự viết. Nói cách khác, khi làm việc với .NET CAS, tôi có thể tin tưởng rằng Microsoft đã làm tốt công việc của mình trong mã hộp cát, trái ngược với việc phải tin vào mã hộp cát của riêng tôi.

Có bất kỳ sự thay thế nào tôi không biết?



@RobertHarvey Các kỹ thuật đóng gói Linux như Seccomp thường chỉ trợ giúp khi chạy mã không tin cậy trong một quy trình riêng biệt, nhưng không áp dụng cho cách ly trong quá trình. Tất nhiên, một giải pháp khá đơn giản cho vấn đề có thể bao gồm chính xác đó là một quy trình riêng biệt hoạt động như một dịch vụ cho chương trình chính và chỉ giao tiếp qua các cơ chế IPC. Tôi tự hỏi nếu Windows có các tính năng cách ly cấp hệ điều hành tương tự?
amon

1
@amon: Ý bạn là như một ... quy trình Windows ? Chắc chắn là có.
Robert Harvey

Trước hết bạn đã giới thiệu lỗ hổng lớn nhất vào hệ thống của mình: Mã nước ngoài . Mọi thứ khác là một nỗ lực để giảm thiểu tác hại đó. Về cơ bản, bạn đang xây dựng một trình thông dịch hy vọng thực thi mã nước ngoài đó một cách an toàn. Đi và cải thiện sự hiểu biết của bạn về giải thích sau đó áp dụng những ý tưởng đó để thực thi các hành vi và sự an toàn tương đối mà bạn mong muốn. Thứ hai, đừng cho rằng một hộp cát là an toàn, luôn luôn thêm các lớp phòng thủ.
Kain0_0

1
@VojislavStojkovic Bạn không thể sử dụng một công cụ javascript? Theo mặc định, các công cụ này không có quyền truy cập vào hệ thống tập tin (không hoàn toàn chắc chắn về mạng nhưng bạn có thể kiểm tra). Một ví dụ là QJSEngine . Ngoài ra với các công cụ này, bạn có thể cung cấp các chức năng mã c ++ tùy chỉnh cho javascript để có khả năng tương tác.
RandomGuy

Câu trả lời:


1

Như những người khác đã tuyên bố, chạy mã nước ngoài là vấn đề lớn nhất liên quan đến loại thực hiện này. Giống như nhận xét của Kain0_0 đã đề xuất, VM sẽ là cách thích hợp nhất để duy trì tự do mã nước ngoài mà không ảnh hưởng đến máy chủ (quá nhiều). Đây là cơ bản những gì dịch vụ tích hợp liên tục như CircleCI làm.

Điều này cũng giúp việc triển khai giao diện dễ dàng hơn nhiều vì bạn có thể kéo hình ảnh với tất cả các tính năng cấu hình và bảo mật mà bạn muốn. Bạn cũng không phải lo lắng nếu mã của họ sẽ được quản lý để chạy trong máy chủ của bạn.

Vì vậy, đối với điều này, tôi sẽ:

  • Tạo ảnh chụp nhanh môi trường tập lệnh người dùng mà tôi muốn trình bày với Docker (một môi trường cho C #, một môi trường cho Python, v.v., với các cấu hình bảo mật thích hợp)

  • Theo yêu cầu của người dùng, hãy quay các trường hợp có liên quan đến Docker thông qua trình kích hoạt mã, đưa tập lệnh nước ngoài vào điểm nhập của đối tượng Docker.

  • Mã được chạy trong phiên bản Docker với quyền của người dùng, các tệp được ghi, có thể một kết nối được tạo ở đây và ở đó, lấy đầu ra và môi trường sau đó bị hủy

  • Vì các container Docker chạy như các tiến trình, chúng có thể bị chấm dứt khá dễ dàng, tức là nếu chúng vượt quá giới hạn thời gian nhất định. Nếu có lỗi, họ có thể chấm dứt ngay lập tức.

Về cơ bản, có mã chính của bạn quản lý trình kích hoạt người dùng, tiêm điểm nhập và logic hủy tự động cho Docker, phụ trách thực hiện việc tạo hộp cát cho loại hoạt động này.


1
Câu trả lời chính xác. Nếu có điều gì đó để thêm vào câu trả lời của bạn, thì đó là tất cả các giải pháp hộp cát phổ biến cho thấy nhiều lỗ hổng cho phép mã độc thoát khỏi hộp cát của nó. Điều này đúng với CAS (ví dụ CVE-2015-2504) và thậm chí còn đúng hơn với Java (khai thác cho trình cắm Java trình duyệt quá nhiều để liệt kê ở đây). Mặc dù Docker cũng có lỗ hổng bảo mật, tôi có một ấn tượng rằng bề mặt tấn công thấp hơn nhiều so với bất kỳ thứ gì được triển khai ở cấp độ của một ngôn ngữ / khung nhất định.
Arseni Mourzenko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.