Mổ xẻ SELinux

Các phương pháp điều khiển truy cập

Hầu hết các hệ điều hành dùng các phương pháp điều khiển truy cập (acess control) để xác định một thực thể (người dùng hay chương trình) có thể truy cập vào một tài nguyên nào đó hay không. Các hệ thống dựa trên Unix dùng một dạng discretionary access control (DAC). Phương pháp này giới hạn truy cập vào các đối tượng dựa trên các nhóm mà chúng thuộc về. Ví dụ, các file trong GNU/Linux có một owner, một group, và một tập các permission. Các permission định nghĩa ai có thể truy cập vào một file nào, ai có thể đọc, ai có thể ghi, và ai có thể thực thi file đó. Những permission này được chia thành ba tập hợp gồm có user, đại diện cho người dùng (owner của file), group (tất cả các user thuộc một group), và others (các user không thuộc hai nhóm trên).

Cơ chế điều khiển cồng kềnh này nảy sinh một vấn đề, vì một chương trình xâm nhập vào hệ thống sẽ thừa hưởng quyền truy cập của user thực thi chương trình. Do đó chương trình có thể làm mọi việc mà user đó được quyền. Thay vì định nghĩa cơ chế điều khiển theo cách này, việc thực hiện theo nguyên tắc “quyền tối thiểu” tỏ ra an toàn hơn. Nguyên tắc này phát biểu như sau: các chương trình chỉ có thể làm những gì chúng cần để thực hiện nhiệm vụ, ngoài ra không được làm gì khác. Ví dụ, nếu bạn có một chương trình đáp ứng các yêu cầu đến một socket mà không cần phải truy cập vào file system, thì chương trình đó chỉ được phép lắng nghe trên một socket cố định và không có quyền đụng đến file system. Với cách này, nếu chương trình bị xâm nhập, quyền truy cập của nó cũng được tối thiểu hoá rõ ràng. Kiểu điều khiển này được gọi là mandatory access control (MAC).

Một cách tiếp cận khác để điều khiển truy cập là role-based access control (RBAC). Trong cơ chế RBAC, permission được cung cấp dựa trên các vai trò (role) được gán bởi hệ thống bảo mật. Khái niệm của một role khác với khái niệm của một “group” truyền thống ở chỗ một group đại diện cho một hay nhiều user. Một role có thể đại diện cho nhiều user, nhưng nó cũng đại diện cho các permission mà một tập các user có thể thực hiện.

SELinux bổ sung cả cơ chế MAC và RBAC cho hệ thống GNU/Linux. Phần tiếp theo sẽ đi sâu vào hiện thực của SELinux và việc thi hành các quy tắc bảo mật được thêm vào Linux kernel một cách trong suốt như thế nào.

Hiện thực bảo mật trên Linux

Trong thời kỳ đầu của SELinux, khi nó vẫn còn là một bộ các bản vá, nó đã đưa ra framework security riêng. Điều này trở thành rắc rối bởi vì nó gắn cứng GNU/Linux vào một kiến trúc acess control duy nhất. Thay vì chấp nhận một cách điều khiển duy nhất như vậy, Linux kernel thừa kế một framework chung, trong đó tách biệt phần policy và phần thi hành (kiểu như lập pháp và hành pháp – ND). Giải pháp này được biết đến với tên gọi Linux Security Module (LSM) framework. LSM cung cấp một framework đa năng dành cho bảo mật, trong đó cho phép các mô hình bảo mật được hiện thực như là những module mà kernel có thể tải lên được (xem hình 1).

Security policy and enforcement are independent using SELinux.

Hình 1. Security policy and enforcement are independent using SELinux.

Mã nguồn của kernel được hiệu chỉnh để trước khi truy cập vào các đối tượng bên trong, nó sẽ gọi một hook đại diện cho một hàm thi hành. Hàm này hiện thực cho security policy, nó xác thực hành động có được tiến hành hay không dựa trên những policy được khai báo trước. Các hàm security được chứa trong một cấu trúc các thao tác security bao gồm những thao tác cơ bản cần phải được bảo vệ. Ví dụ, hàm security_socket_create hook (security_ops->socket_create) kiểm tra các permission trước khi tạo một socket mới và xem xét họ giao thức, loại, giao thức, và socket được tạo trong kernel-space hay user-space. Dưới đây là mã nguồn minh hoạ của file /linux/net/socket.c khi tạo socket.

static int __sock_create(int family, int type, int protocol,
                          struct socket **res, int kern)
{
        int err;
        struct socket *sock;

        /*
         *      Check protocol is in range
         */
        if (family < 0 || family >= NPROTO)
                return -EAFNOSUPPORT;
        if (type < 0 || type >= SOCK_MAX)
                return -EINVAL;

        err = security_socket_create(family, type, protocol, kern);
        if (err)
                return err;

Hàm security_socket_create được định nghĩa trong ./linux/include/linux/security.h. Nó làm trung gian để gọi đến hàm được cài đặt động trong security_ops structure. Xem mã nguồn minh hoạ:

static inline int security_socket_create (int family, int type,
                                          int protocol, int kern)
{
        return security_ops->socket_create(family, type, protocol, kern);
}

Hàm trong cấu trúc được cài đặt bởi security module. Bằng cách này, các hook được định nghĩa trong module SELinux mà kernel có thể tải lên được. Mỗi lời gọi SELinux được định nghĩa trong một file chứa các hook hoàn tất việc trung gian giữa hàm của kernel đến lời gọi động cho một security module cụ thể. Xem mã nguồn minh hoạ từ /linux/security/selinux/hooks.c

static int selinux_socket_create(int family, int type,
                                 int protocol, int kern)
{
        int err = 0;
        struct task_security_struct *tsec;

        if (kern)
                goto out;

        tsec = current->security;
        err = avc_has_perm(tsec->sid, tsec->sid,
                           socket_type_to_security_class(family, type,
                           protocol), SOCKET__CREATE, NULL);

out:
        return err;
}

Trọng tâm của đoạn code là lời gọi xác nhận hành động hiện tại của tác vụ hiện tại (được định nghĩa bởi current->security, trong đó current đại diện cho tác vụ hiện tại đang thực thi ) có được cho phép không. Access Vector Cache (AVC) là một cache của những quyết định SELinux trước đó (để tăng hiệu suất xử lý). Lời gọi này bao gồm source security identifier (sid), security class (được tạo thành từ những chi tiết của hành động được yêu cầu), lời gọi socket cụ thể, và tùy chọn cho hỗ trợ kiểm tra dữ liệu. Nếu không tìm thấy quyết định trong cache, máy chủ security sẽ được gọi để ra quyết định (quy trình được mô tả trong hình 2).

Hình 2. Layered Linux security process

Hình 2. Layered Linux security process

Các hàm hook mà security_ops gọi đến được định nghĩa động như là một module kernel có thể tải lên được (thông qua register_security()), còn trong trường hợp không có module nào được load thì nó sẽ chứa những hàm dummy (xem /linux/security/dummy.c ). Những hàm này sẽ hiện thực policy theo chuẩn Linux DAC. Các hook tồn tại ở tất cả những điểm mà sự can thiệp vào object cần phải được cung cấp để đảm bảo an toàn. Sự can thiệp này gồm có thao tác quản lý (creation, signaling, waiting), nạp chương trình (execve), quản lý hệ thống file (superblock, inode, và filehooks), IPC (message queues, shared memory, và semaphore operations), module hooks (chèn và xoá), và network hooks (gồm có sockets, netlink, network devices, và những giao diện protocol khác). Có thể xem thêm về các loại hook này trong file security.h.

Những cách tiếp cận khác

SELinux là một trong những security framework dễ hiểu nhất hiện nay, nhưng dĩ nhiên nó không phải là duy nhất. Ngoài ra còn có:

AppArmor

Solaris 10 (was Trusted Solaris)

TrustedBSD

Operating system virtualization

Tham khảo

About dongthao

The best things in life, they are free ... (Cry on my shoulder lyric)
This entry was posted in Linux Tutorial and tagged . Bookmark the permalink.

Có 5 phản hồi tại Mổ xẻ SELinux

  1. pclouds nói:

    Có thể framework dễ hiểu, nhưng khó xài.

  2. Security framework mà Thao đang sử dụng (hoặc sắp sử dụng) là cái này à ?

  3. dongthao nói:

    @pclouds: Đồng ý với anh, vì vậy mới có AppArmor.
    @Ninja: đã sử dụng :p. SELinux rất phổ biến, bài này mình chỉ muốn tìm hiểu thêm 1 chút về cơ chế của nó. Có thể sau này sẽ cần đến.

  4. Hùng Cường nói:

    Tôi cũng đã vấp phải một số lỗi liên quan đến selinux, và cũng tìm thấy một số hướng dẫn để khắc phục lỗi này thông qua lệnh chcon. Tuy nhiên tôi không hiểu lắm về một số tham số của lệnh ví dụ như:
    + role, có những role thế nào, làm thế nào để biết được danh sách các role như vậy.
    + type, làm sao để biết được các kiểu đươc selinux hỗ trợ.

    Trong man page của chcon không thấy nói đến điều đó.

    Bạn có thể nói thêm về nó được không?

  5. Trần Nam nói:

    ai biết cách tắt SELinux và iptables. trên CentOS7 k a

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s