Xem lại trang này để làm quen với các khái niệm về SELinux.
Kiểm soát quyền truy cập bắt buộc
Security Enhanced Linux (SELinux) là một hệ thống kiểm soát truy cập bắt buộc (MAC) dành cho hệ điều hành Linux. Là một hệ thống MAC, hệ thống này khác với hệ thống kiểm soát quyền truy cập tuỳ ý (DAC) quen thuộc của Linux. Trong hệ thống DAC, có một khái niệm về quyền sở hữu, theo đó, chủ sở hữu của một tài nguyên cụ thể sẽ kiểm soát các quyền truy cập liên kết với tài nguyên đó. Điều này thường là thô và có thể dẫn đến việc nâng cấp đặc quyền ngoài ý muốn. Tuy nhiên, hệ thống MAC sẽ tham khảo một cơ quan trung tâm để đưa ra quyết định về tất cả các lần truy cập.
SELinux đã được triển khai như một phần của khung Mô-đun bảo mật Linux (LSM), giúp nhận dạng nhiều đối tượng nhân hệ điều hành và các hành động nhạy cảm được thực hiện trên các đối tượng đó. Tại thời điểm thực hiện từng hành động trong số này, một hàm móc LSM sẽ được gọi để xác định xem có cho phép hành động đó hay không dựa trên thông tin được lưu trữ trong một đối tượng bảo mật mờ. SELinux cung cấp phương thức triển khai cho các trình bổ trợ này và quản lý các đối tượng bảo mật này, kết hợp với chính sách riêng của SELinux để xác định các quyết định về quyền truy cập.
Cùng với các biện pháp bảo mật khác của Android, chính sách kiểm soát quyền truy cập của Android giúp hạn chế đáng kể thiệt hại tiềm ẩn của các máy tính và tài khoản bị xâm nhập. Việc sử dụng các công cụ như các chế độ kiểm soát quyền truy cập bắt buộc và tuỳ ý của Android sẽ cung cấp cho bạn một cấu trúc để đảm bảo phần mềm của bạn chỉ chạy ở cấp đặc quyền tối thiểu. Điều này giúp giảm thiểu tác động của các cuộc tấn công và giảm khả năng các quy trình bị lỗi ghi đè hoặc thậm chí truyền dữ liệu.
Trong Android 4.3 trở lên, SELinux cung cấp một biện pháp kiểm soát quyền truy cập bắt buộc (MAC) trên các môi trường kiểm soát quyền truy cập tuỳ ý (DAC) truyền thống. Ví dụ: phần mềm thường phải chạy dưới dạng tài khoản người dùng gốc để ghi vào các thiết bị khối thô. Trong môi trường Linux dựa trên DAC truyền thống, nếu người dùng gốc bị xâm phạm, thì người dùng đó có thể ghi vào mọi thiết bị khối thô. Tuy nhiên, bạn có thể sử dụng SELinux để gắn nhãn cho các thiết bị này để quy trình được chỉ định đặc quyền gốc chỉ có thể ghi vào các thiết bị được chỉ định trong chính sách liên quan. Bằng cách này, quá trình này không thể ghi đè dữ liệu và chế độ cài đặt hệ thống bên ngoài thiết bị khối thô cụ thể.
Hãy xem phần Trường hợp sử dụng để biết thêm ví dụ về các mối đe doạ và cách giải quyết các mối đe doạ đó bằng SELinux.
Mức độ thực thi
Bạn có thể triển khai SELinux theo nhiều chế độ:
- Cho phép – Chính sách bảo mật SELinux không được thực thi, chỉ được ghi lại.
- Thực thi – Chính sách bảo mật được thực thi và ghi lại. Các lỗi sẽ xuất hiện dưới dạng lỗi EPERM.
Lựa chọn này là nhị phân và xác định xem chính sách của bạn có thực hiện hành động hay chỉ cho phép bạn thu thập các lỗi tiềm ẩn. Chế độ cho phép đặc biệt hữu ích trong quá trình triển khai.
Loại, thuộc tính và quy tắc
Android dựa vào thành phần Thực thi loại (TE) của SELinux cho chính sách của mình. Điều này có nghĩa là tất cả đối tượng (chẳng hạn như tệp, quy trình hoặc ổ cắm) đều có một loại liên kết với chúng. Ví dụ: theo mặc định, một ứng dụng có loại untrusted_app
. Đối với một quy trình, loại của quy trình đó cũng được gọi là miền. Bạn có thể chú thích một loại bằng một hoặc nhiều thuộc tính. Thuộc tính rất hữu ích để tham chiếu đến nhiều loại cùng một lúc.
Các đối tượng được liên kết với các lớp (ví dụ: tệp, thư mục, đường liên kết tượng trưng, ổ cắm) và các loại quyền truy cập khác nhau cho từng lớp được biểu thị bằng quyền.
Ví dụ: quyền open
tồn tại cho lớp file
. Mặc dù các loại và thuộc tính thường xuyên được cập nhật trong chính sách SELinux của Android, nhưng các quyền và lớp được xác định tĩnh và hiếm khi được cập nhật trong bản phát hành Linux mới.
Quy tắc của chính sách có dạng:
allow source target:class permissions;
trong đó:
- Nguồn – Loại (hoặc thuộc tính) của đối tượng áp dụng quy tắc. Ai đang yêu cầu quyền truy cập?
- Mục tiêu – Loại (hoặc thuộc tính) của đối tượng. Yêu cầu truy cập vào nội dung gì?
- Lớp – Loại đối tượng (ví dụ: tệp, ổ cắm) đang được truy cập.
- Quyền – Thao tác (hoặc tập hợp thao tác) (ví dụ: đọc, ghi) đang được thực hiện.
Ví dụ về quy tắc:
allow untrusted_app app_data_file:file { read write };
Điều này cho biết rằng các ứng dụng được phép đọc và ghi các tệp được gắn nhãn app_data_file
. Ngoài ra, còn có các loại khác cho ứng dụng. Ví dụ: isolated_app
được dùng cho các dịch vụ ứng dụng có isolatedProcess=true
trong tệp kê khai. Thay vì lặp lại quy tắc cho cả hai loại, Android sử dụng một thuộc tính có tên appdomain
cho tất cả các loại bao gồm ứng dụng:
# Associate the attribute appdomain with the type untrusted_app. typeattribute untrusted_app appdomain; # Associate the attribute appdomain with the type isolated_app. typeattribute isolated_app appdomain; allow appdomain app_data_file:file { read write };
Khi bạn viết một quy tắc chỉ định tên thuộc tính, tên đó sẽ tự động mở rộng thành danh sách các miền hoặc loại được liên kết với thuộc tính đó. Một số thuộc tính đáng chú ý là:
domain
– thuộc tính liên kết với tất cả các loại quy trình,file_type
– thuộc tính liên kết với tất cả các loại tệp.
Macro
Đối với quyền truy cập vào tệp, bạn cần cân nhắc nhiều loại quyền. Ví dụ: quyền read
là chưa đủ để mở tệp hoặc gọi stat
trên tệp đó. Để đơn giản hoá định nghĩa quy tắc, Android cung cấp một bộ macro để xử lý các trường hợp phổ biến nhất. Ví dụ: để thêm các quyền bị thiếu như open
, bạn có thể viết lại quy tắc ở trên như sau:
allow appdomain app_data_file:file rw_file_perms;
Hãy xem các tệp global_macros
và te_macros
để biết thêm ví dụ về các macro hữu ích. Bạn nên sử dụng macro bất cứ khi nào có thể để giảm khả năng xảy ra lỗi do bị từ chối các quyền liên quan.
Sau khi xác định một loại, bạn cần liên kết loại đó với tệp hoặc quy trình mà loại đó đại diện. Hãy xem phần Triển khai SELinux để biết thêm thông tin chi tiết về cách thực hiện liên kết này. Để biết thêm thông tin về các quy tắc, hãy xem SELinux Notebook.
Ngữ cảnh và danh mục bảo mật
Khi gỡ lỗi các chính sách SELinux hoặc gắn nhãn tệp (bằng cách sử dụng file_contexts
hoặc khi ls -Z
), bạn có thể gặp ngữ cảnh bảo mật (còn gọi là nhãn). Ví dụ: u:r:untrusted_app:s0:c15,c256,c513,c768
. Ngữ cảnh bảo mật có định dạng:
user:role:type:sensitivity[:categories]
. Thông thường, bạn có thể bỏ qua các trường user
, role
và sensitivity
của ngữ cảnh (xem phần Đặc thù). Trường type
được giải thích trong phần trước. categories
là một phần của tính năng hỗ trợ Bảo mật nhiều cấp (MLS) trong SELinux. Trong Android 12 trở lên, các danh mục được dùng để:
- Cách ly dữ liệu ứng dụng khỏi quyền truy cập của ứng dụng khác,
- Tách biệt dữ liệu ứng dụng của người dùng thực này với người dùng thực khác.
Tính cụ thể
Android không sử dụng tất cả các tính năng do SELinux cung cấp. Khi đọc tài liệu bên ngoài, hãy lưu ý những điểm sau:
- Phần lớn các chính sách trong AOSP được xác định bằng Ngôn ngữ chính sách nhân kernel. Có một số trường hợp ngoại lệ khi sử dụng Ngôn ngữ trung gian chung (CIL).
- Không sử dụng người dùng SELinux. Giá trị duy nhất do người dùng xác định là
u
. Khi cần, người dùng thực sẽ được biểu thị bằng cách sử dụng trường danh mục của ngữ cảnh bảo mật. - Không sử dụng vai trò SELinux và tính năng Kiểm soát quyền truy cập dựa trên vai trò (RBAC). Hai vai trò mặc định được xác định và sử dụng:
r
cho chủ thể vàobject_r
cho đối tượng. - Không sử dụng mức độ nhạy cảm của SELinux. Độ nhạy
s0
mặc định luôn được đặt. - Không sử dụng boolean SELinux. Khi được tạo cho một thiết bị, chính sách này không phụ thuộc vào trạng thái của thiết bị. Điều này giúp đơn giản hoá việc kiểm tra và gỡ lỗi chính sách.