Thực tiễn tốt nhất để thực thi mã không tin cậy


31

Tôi có một dự án mà tôi cần cho phép người dùng chạy mã python tùy ý, không đáng tin cậy ( hơi giống như thế này ) đối với máy chủ của tôi. Tôi còn khá mới với python và tôi muốn tránh mắc phải bất kỳ lỗi nào gây ra lỗ hổng bảo mật hoặc các lỗ hổng khác vào hệ thống. Có bất kỳ thực hành tốt nhất nào có sẵn, đọc khuyến nghị hoặc các gợi ý khác mà bạn có thể cung cấp cho tôi để làm cho dịch vụ của tôi có thể sử dụng được nhưng không thể sử dụng được không?

Đây là những gì tôi đã xem xét cho đến nay:

  • Xóa __builtins__khỏi execbối cảnh để cấm sử dụng các gói nguy hiểm tiềm tàng như os. Người dùng sẽ chỉ có thể sử dụng các gói tôi cung cấp cho họ.
  • Sử dụng các chủ đề để thực thi một thời gian chờ hợp lý.
  • Tôi muốn giới hạn tổng số lượng bộ nhớ có thể được phân bổ trong execngữ cảnh, nhưng tôi không chắc liệu nó có khả thi hay không.

Có một số lựa chọn thay thế cho một đường thẳng exec, nhưng tôi không chắc cách nào trong số này sẽ hữu ích ở đây:

  • Sử dụng ast.NodeVisitorđể bắt bất kỳ nỗ lực truy cập các đối tượng không an toàn. Nhưng những đối tượng nào tôi nên cấm?
  • Tìm kiếm bất kỳ dấu gạch dưới kép trong đầu vào. (kém duyên dáng hơn so với tùy chọn trên).
  • Sử dụng PyPyhoặc một cái gì đó tương tự như hộp cát mã.

LƯU Ý: Tôi biết rằng có ít nhất một trình thông dịch dựa trên JavaScript. Điều đó sẽ không hoạt động trong kịch bản của tôi.



3
@MartijnPieters: Tuyệt vời. Có lẽ xứng đáng với một câu trả lời, nếu bạn tóm tắt từng người.
Robert Harvey

Cũng xem xét: rác còn lại trên đĩa, mạng (không cho phép họ gửi thư rác hoặc bất cứ điều gì), quyền đối với các tệp khác (đọc tệp của bạn). Ngay cả việc đẩy vào vòng lặp while cũng có thể phá hủy cơ học CD ... Tôi sẽ đi ảo hóa (nhà tù hoặc một số kvm mà bạn đặt tên cho nó) hoặc ít nhất là người dùng gần như không có đặc quyền. Đặt số lượng đẹp và dung lượng bộ nhớ hợp lý để tận dụng các chương trình của riêng bạn.
kyticka


1
Hãy thử PyPy :> Sandboxing: PyPy cung cấp khả năng chạy mã không tin cậy theo cách hoàn toàn an toàn.
Vorac

Câu trả lời:


28

Python sandboxing là khó . Python vốn dĩ không thể hướng nội, ở nhiều cấp độ.

Điều này cũng có nghĩa là bạn có thể tìm thấy các phương thức xuất xưởng cho các loại cụ thể từ chính các loại đó và xây dựng các đối tượng cấp thấp mới , sẽ được trình thông dịch trực tiếp chạy mà không giới hạn.

Dưới đây là một số ví dụ về việc tìm các cách sáng tạo để thoát ra khỏi hộp cát Python:

  • Ned Batchelder bắt đầu với một minh chứng rằng thực sự nguy hiểmeval() như thế nào ; eval()thường được sử dụng để thực thi các biểu thức Python; như một hộp cát nguyên thủy và ngây thơ cho một lớp lót.

    Sau đó, anh tiếp tục thử và áp dụng các nguyên tắc tương tự cho Python 3 , cuối cùng đã thành công khi thoát ra với một số gợi ý hữu ích.

  • Pierre Bourdon sử dụng các kỹ thuật tương tự để hack hệ thống python tại hack-a-thon

Ý tưởng cơ bản là luôn tìm cách tạo ra các loại Python cơ bản; các hàm và các lớp và thoát ra khỏi trình bao bằng cách yêu cầu trình thông dịch Python thực thi mã byte tùy ý (không được kiểm tra!).

Điều tương tự và nhiều hơn áp dụng cho execcâu lệnh ( exec()hàm trong Python 3).

Vậy bạn muốn:

  • Kiểm soát chặt chẽ việc biên dịch byte của mã Python hoặc ít nhất là xử lý hậu kỳ mã byte để loại bỏ mọi quyền truy cập vào tên bắt đầu bằng dấu gạch dưới.

    Điều này đòi hỏi kiến ​​thức sâu sắc về cách trình thông dịch Python hoạt động và cách cấu trúc mã byte của Python. Các đối tượng mã được lồng nhau; Ví dụ , mã byte của mô-đun chỉ bao gồm cấp độ câu lệnh cao nhất, mỗi hàm và lớp bao gồm chuỗi mã byte riêng của chúng cộng với siêu dữ liệu, có chứa các đối tượng mã byte khác cho các hàm và lớp được lồng vào nhau.

  • Bạn cần lập danh sách trắng các mô-đun có thể được sử dụng. Cẩn thận.

    Một mô-đun python chứa các tham chiếu đến các mô-đun khác . Nếu bạn nhập os, có một tên cục bộ ostrong không gian tên mô-đun của bạn tham chiếu đến osmô-đun. Điều này có thể dẫn một kẻ tấn công xác định đến các mô-đun có thể giúp chúng thoát ra khỏi hộp cát. Các picklemô-đun, ví dụ, cho phép bạn tải đối tượng mã bất kỳ ví dụ, vì vậy nếu bất kỳ con đường thông qua module danh sách cho phép dẫn đến các picklemô-đun, bạn có một vấn đề vẫn còn.

  • Bạn cần hạn chế nghiêm ngặt hạn ngạch thời gian. Ngay cả mã trung tính nhất vẫn có thể cố gắng chạy mãi mãi, buộc tài nguyên của bạn.

Hãy xem RestrictedPython , công cụ này cố gắng cung cấp cho bạn quyền kiểm soát mã byte nghiêm ngặt. RestrictedPythonchuyển đổi mã Python thành một cái gì đó cho phép bạn kiểm soát tên, mô-đun và đối tượng nào được cho phép trong Python 2.3 đến 2.7.

Nếu RestrictedPythonđủ an toàn cho mục đích của bạn không phụ thuộc vào chính sách bạn thực hiện. Không cho phép truy cập vào tên bắt đầu bằng dấu gạch dưới và liệt kê hoàn toàn danh sách trắng các mô-đun sẽ là một sự khởi đầu.

Theo tôi, tùy chọn thực sự mạnh mẽ duy nhất là sử dụng một Máy ảo riêng biệt, một máy không có quyền truy cập mạng vào thế giới bên ngoài mà bạn phá hủy sau mỗi lần chạy. Mỗi tập lệnh mới được cung cấp một VM mới thay thế. Theo cách đó, ngay cả khi mã quản lý thoát ra khỏi hộp cát Python của bạn (điều không thể xảy ra), tất cả những kẻ tấn công đều có quyền truy cập trong thời gian ngắn và không có giá trị.


10

TL; DR Sử dụng chroot / jail và chạy như một người dùng tùy chỉnh mà không có bất kỳ đặc quyền nào.

Cách thực hành tốt nhất để thực thi mã không tin cậy là tách biệt nó thông qua hộp cát hệ thống . Để bảo mật nhất:

  • tạo một thùng chứa chỉ với Python và nó phụ thuộc và phụ thuộc của container
  • tạo một thùng chứa mà không cần tất cả các thiết bị không thực sự cần thiết (ví dụ: mạng và lưu trữ)
  • tạo một thùng chứa với các hạn chế về bộ nhớ và quá trình sử dụng
  • tạo lại container với mỗi lần chạy (hoặc ít nhất là với mỗi người dùng duy nhất và khoảng thời gian tối đa)
  • chạy như một người dùng với ít đặc quyền cần thiết nhất
  • chạy như một người dùng không có quyền ghi tập tin

Bạn cũng tuân theo các thực hành tiêu chuẩn để chạy mọi thứ một cách an toàn trong một chiếc chroot. Bạn có thể xây dựng lại hệ thống tập tin của chroot với mỗi cuộc gọi cũng đặc biệt hoang tưởng. Thông thường, bạn chỉ khiến người dùng không thể thực hiện sửa đổi hệ thống tập tin mà chroot chạy.


Đây là điều duy nhất mà bạn sẽ thậm chí từ xa chắc chắn rằng bạn đã hiểu đúng - hãy cho nó là quy trình riêng.
Michael Kohne

3

Không có cách nào bạn có thể làm điều này một cách an toàn.

Nếu bạn muốn làm một cái gì đó như thế này một cách an toàn, bạn phải bắt đầu bằng cách tự thực hiện python chạy trong môi trường được kiểm soát hoàn toàn, tốt nhất là chạy trong trình duyệt của người dùng thay vì trên hệ thống của bạn. Bạn có thể bắt đầu với Jython (python cho java) và gói nó dưới dạng một applet java. Vì nó sẽ chạy trong hộp cát java, nên trên máy của người dùng, hệ thống của bạn sẽ an toàn một cách hợp lý.


4
Câu hỏi về an toàn là cho máy chủ của anh ấy, không phải cho máy của khách hàng. Các mối nguy hiểm bảo mật tiềm tàng của Java, giống như các mối nguy đối với bất kỳ công nghệ web nào khác, là máy chủ có thể được sử dụng để triển khai các chương trình nguy hiểm cho máy khách.
ddyer

1
@grasGendarme rất giống những câu chuyện mới về tai nạn máy bay thực sự cho bạn biết rất nhiều về mức độ hiếm của chúng; những câu chuyện về lỗ hổng bảo mật java cho bạn biết rằng java tương đối an toàn. Bạn sẽ không bao giờ có được một câu chuyện như vậy về C bởi vì câu trả lời bạn nhận được sẽ là "duh; nếu bạn chạy nó, nó sẽ làm bất cứ điều gì nó muốn"
Richard Tingle

2

Như Martijn đã nói ở trên, điều này thực sự, thực sự khó khăn trong Python. Nói thẳng ra là vì Python quá phức tạp, tôi không nghĩ nó có thể bằng cách giới hạn các tính năng ngôn ngữ. Và nếu bạn nhận được một hộp cát làm việc cho một phiên bản Python, có khả năng phiên bản tiếp theo sẽ phá vỡ nó.

Tôi sẽ xem PyPy thay vì CPython tiêu chuẩn. Nói tóm lại, đây là một triển khai thay thế phù hợp của Python. Nó có một số ưu điểm và tính năng riêng biệt, và một trong số đó là sandbox thông qua việc thay thế các cuộc gọi hệ thống thay vì giới hạn các tính năng ngôn ngữ.


0

Miễn là hiệu suất không quá quan trọng đối với bạn, bạn luôn có thể chạy nó trong Brython, điều này sẽ đưa nó vào hộp cát JavaScript một cách hiệu quả

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.