company_banner

Быстрое создания SELinux-модулей с помощью утилиты sepolicy

  • Tutorial
В пакет policycoreutils-devel входит python-утилита sepolicy, которая сильно облегчает написание модуля. В этой статье мы рассмотрим процесс создания модуля для nmap с помощью этой утилиты.



TL; DR

В предыдущих статьях мы детально рассматривали создание policy module и связанные с этим вопросы. Сейчас же я расскажу о том, как значительно облегчить себе жизнь с man 8 sepolicy


Постановка задачи


Задачи, которые мы решим в статье:

  • Написать модуль для nmap.
  • Разрешить пользователям проводить сканы.
  • Ограничить любые деструктивные действия.

Создание заготовки


У sepolicy есть режим генерации базовых модулей, вызываемый командой sepolicy generate (или sepolgen). Давайте создадим шаблон нашего модуля:

# sepolgen -n nmap --application /usr/bin/nmap -u user_u -u staff_u
Loaded plugins: fastestmirror
Created the following files:
/root/nmap_module/nmap.te # Type Enforcement file
/root/nmap_module/nmap.if # Interface file
/root/nmap_module/nmap.fc # File Contexts file
/root/nmap_module/nmap_selinux.spec # Spec file
/root/nmap_module/nmap.sh # Setup Script

Разберем аргументы командной строки:

  • -n — имя модуля.
  • --application — тип/приложение.
  • /usr/bin/nmap — путь к исполняемому файлу.
  • -u staff_u -u user_u — список пользователей, которые могут использовать это приложение.

Так как путь /usr/bin/nmap уже описан как traceroute_exec_t, сборка модуля as is вызовет конфликт. Поэтому удаляем файл nmap.fc перед сборкой модуля, а после сборки — делаем chcon.

# rm nmap.fc 
rm: remove regular file 'nmap.fc'? y
# ./nmap.sh 
Building and Loading Policy
+ make -f /usr/share/selinux/devel/Makefile nmap.pp
Compiling minimum nmap module
/usr/bin/checkmodule:  loading policy configuration from tmp/nmap.tmp
/usr/bin/checkmodule:  policy configuration loaded
/usr/bin/checkmodule:  writing binary representation (version 17) to tmp/nmap.mod
Creating minimum nmap.pp policy package
rm tmp/nmap.mod tmp/nmap.mod.fc
+ /usr/sbin/semodule -i nmap.pp
...
# chcon -t nmap_exec_t /usr/bin/nmap 

Отладка


Сейчас модуль работает в permissive-режиме, т. е. политики проверяются, но реальной блокировки не происходит. Это можно понять по строке permissive nmap_t в файле nmap.te.

Теперь запустим nmap с различными опциями для формирования достаточного количества логов. Предварительно рекомендую выполнить команду semodule -DB для отключения dontaudit-правил (правила, которые не дают писать в лог те или иные запреты).

# chmod u+s /usr/bin/nmap
# semodule -DB
$ id
user_u:user_r:user_t:s0
$ nmap -sS -A -PI jnode.in
....
$ nmap -A -sU -PI jnode.in
....
$ nmap jnode.in -o out.log
....

Смотрим результаты:

# audit2allow -bl -R -t nmap_t
allow nmap_t self:capability {net_raw dac_read_search dac_override};
allow nmap_t self:unix_dgram_socket { create ioctl };
allow nmap_t self:packet_socket { bind create getopt ioctl read setopt write };
allow nmap_t self:rawip_socket { create setopt write };
corenet_tcp_connect_http_port(nmap_t)
corenet_tcp_connect_smtp_port(nmap_t)
corenet_tcp_connect_ssh_port(nmap_t)
kernel_read_network_state(nmap_t)
kernel_read_system_state(nmap_t)
userdom_use_inherited_user_ptys(nmap_t)

Заодно видим, что out.log создался с контекстом user_home_dir_t — нужно создать новый тип (nmap_result_log_t) и дать необходимые права доступа.

Финализация


Итак, нам нужно сделать следующее:

  • Разрешить необходимые доступы к сети.
  • Разрешить писать логи.
  • Сделать новый тип для логов.
  • Сделать правило перехода типов для логов.
  • Дать права пользователям и приложению на правку этих логов.

Правим модуль и получаем следующий код:

policy_module(nmap, 1.0.0)
########################################
#
# Declarations
#

attribute_role nmap_roles;
roleattribute system_r nmap_roles;

type nmap_t;
type nmap_exec_t;
application_domain(nmap_t, nmap_exec_t)
role nmap_roles types nmap_t;

# log files type
type nmap_result_log_t;
files_type(nmap_result_log_t)
# home transition
userdom_user_home_dir_filetrans(nmap_t, nmap_result_log_t, { dir file })
# permissive nmap_t;
########################################
#
# nmap local policy
#
allow nmap_t self:process { setrlimit };

allow nmap_t self:fifo_file manage_fifo_file_perms;
allow nmap_t self:unix_stream_socket create_stream_socket_perms;

domain_use_interactive_fds(nmap_t)

files_read_etc_files(nmap_t)

auth_use_nsswitch(nmap_t)

miscfiles_read_localization(nmap_t)

sysnet_dns_name_resolve(nmap_t)

optional_policy(`
        gen_require(`
                type user_t;
                role user_r;
        ')

        nmap_run(user_t, user_r)
       # nmap log files access
        manage_files_pattern(user_t, nmap_result_log_t, nmap_result_log_t)
')

optional_policy(`
        gen_require(`
                type staff_t;
                role staff_r;
        ')

        nmap_run(staff_t, staff_r) # autogenerated macro from nmap.if
       # nmap log files access
        manage_files_pattern(staff_t, nmap_result_log_t, nmap_result_log_t)
')

# from audit2allow
allow nmap_t self:capability { dac_override net_raw dac_read_search };
allow nmap_t self:packet_socket { bind create getopt ioctl read setopt write };
allow nmap_t self:rawip_socket { create setopt write };
kernel_read_network_state(nmap_t)
kernel_read_system_state(nmap_t)
userdom_use_inherited_user_ptys(nmap_t)
corenet_tcp_connect_all_ports(nmap_t)
#nmap log files access
manage_files_pattern(nmap_t, nmap_result_log_t, nmap_result_log_t)

Пересобираем модуль:

# ./nmap.sh
....

И проверяем в enforcing-режиме:

$ nmap -A -PI -sX -p 53 jnode.in -o out.log

Starting Nmap 6.40 ( http://nmap.org ) at 2018-05-13 13:29 CEST
WARNING: Running Nmap setuid, as you are doing, is a major security risk.

Nmap scan report for jnode.in (79.137.74.224)
Host is up (0.012s latency).
PORT   STATE SERVICE VERSION
53/tcp open  domain  ISC BIND hostmaster
...
$ ls -laZ out.log 
-rw-rw-r--. root user user_u:object_r:nmap_result_log_t:s0 out.log
$ rm out.log
$

Что еще может sepolicy?


Показать списки макросов интерфейсов

# sepolicy interface -v -l|grep filetrans|grep user_home_dir
userdom_user_home_dir_filetrans(domain, private_type, object_class, name)  Create objects in a user home directory with an automatic type transition to a specified private type.
# sepolicy interface -v -l|grep corenet_tcp_connect|grep all
corenet_tcp_connect_all_ports(domain)  Connect TCP sockets to all ports.
# sepolicy interface -v -l|grep files_pattern|grep manage   
manage_files_pattern

Отслеживать возможные переходы типов

# sepolicy transition -s user_t -t nmap_t
user_t @ nmap_exec_t --> nmap_t

Отслеживать «общие» типы для обмена данными

# sepolicy communicate -s user_t -t nmap_t
xserver_tmpfs_t
user_tmp_t
user_fonts_t
nmap_result_log_t

А также генерировать документацию, показывать состояние booleans и прочие полезные вещи. Очень хорошая утилита, на самом деле.

Вместо заключения


SELinux не так страшен, как его малюют. Пользуйтесь вспомогательными утилитами, и написание полиси станет для вас легким и приятным делом.

Если вы хотите узнать больше — приходите на PHDays 18, где я буду вести четырехчасовой семинар по настройке SELinux-окружения.

P.S. Скачать исходники этого модуля (и других) можно здесь.
Wargaming 84,67
Компания
Поделиться публикацией
Комментарии 0

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое