Sl
Информация
Выполнить команду с желаемыми контекстом безопасности:
$ slrun -l s1 -c sh -- -c '/usr/bin/id -Z > /home/stanv/docs/s1/id' slrun2: DISPLAY variable isn't defined. slrun2: Xorg is present: no slrun2: HOME = /home/stanv slrun2: TMP PREFIX = /tmp/.private/stanv slrun2: TMP = /tmp/.private/stanv/s1 slrun2: TMPDIR = /tmp/.private/stanv/s1 slrun2: User's permanent storage is located at: /home/stanv/docs/s1 generic_u:generic_r:generic_t:s1-s3
Утилита slrun была написана специально для ALTLinux в итоге она вызывает другую команду newrole. slrun - подготавливает окружение чтобы желаемая команда могла удачно запускаться.
Следует понимать, что таким образом нельзя запускать команды, которые будут пытаться читать или писать в текущий терминал, так как этот терминал сохраняет прежний контекст безопасности. Запускать таким образом можно только команды, которые тихо пишут/читают файлы или работают через Xorg.
Изменить максимально-доступный контекст безопасности пользователя:
# id -Z # officer_u:officer_r:officer_t:s0-s5:c0.c15 -- нужно убедится что вы администратор безопасности # semanage login -m stanv -r s0-s3 # semanage login -l Имя входа Пользователь SELinux Диапазон MLS/MCS Служба __default__ generic_u s0 * root officer_u s0-s5:c0.c15 * stanv generic_u s0-s3 *
Офицер безопасности
Офицер безопасности имеет домен officer_t root авторизованный через физическую консоль получает данный контекст безопасности. также officer_t можно получить авторизовавшись через ssh /etc/openssh/sshd_config == PermitRootLogin yes Если пользователь получает права root через su - тогда root не сможет влиять на политику SeLinux так как контекст безопасности остается залогиненого пользователя.
Количество уровней в системе Количество уровней задается в момент компиляции политики.
# seinfo --sensitivity Sensitivities: 6 s0 s1 s2 s3 s4 s5
Howto get working SeLinux AltLinux policy
Факты
libselinux для своей работы требует /proc это требует учитывать для зачрученных приложений, которые могут отказывать работать по необяснимым причинам. Это относится к всяким родам службам, которые в ALT часто делают chroot с целью усиления защищенности.
Force relabeling
touch /.autorelabel
Update Grub config
Update configuration GRUB's file: /etc/sysconfig/grub2:
GRUB_CMDLINE_LINUX_DEFAULT='panic=30 quiet splash security=selinux selinux=1'
It is also possible to add:
- enforcing=1
- log_buf_len=1M
grub-mkconfig > /boot/grub/grub.cfg
PAM configuration
- Add to /etc/pam.d/newrole before pam_namespace.so module
session required pam_exec.so debug /etc/security/alt.newrole/helper /etc/security/alt.newrole/config
- Add to /etc/pam.d/common-login:
# The first `session' module # pam_selinux.so close should be the first session rule session required pam_selinux.so close
# The last `session' module # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open verbose
Reboot
reboot system with enabled selinux
Install policy
Install package selinux-policy-altlinux
Reboot system again
ALT Linux aspects
newrole modifications
Add patch for policycoreutils-newrole has patch, that adds to Linux capabilities: CAP_SETGID & CAP_AUDIT_WRITE. For more info look up at: http://git.altlinux.org/gears/p/policycoreutils.git
Users
When system's users login the __default__ rule takes action. This rule says that:
- all system users are mapped to generic_u SeLinux user.
- all OS users has access only to s0 level.
# semanage login -l Login Name SELinux User MLS/MCS Range __default__ generic_u s0 root officer_u s0-s5:c0.c15
Add for specfic user:
# semanage login -a -s generic_u -r s0-s3:c2.c14 stanv
Новая версия RPM-пакета политики
Когда происходит полное обновление системы через apt-get dist-upgrade нужно убедится что нету установки RPM-пакета новой политики selinux-policy-altlinux. Если необходимо обновить политику SeLinux (RPM-пакет) или apt-get dist-upgrade пытается установить новую версию RPM selinux-policy-altlinux пакета, тогда необходимо деактивировать защиту SeLinux. Для этого нужно выполнить команду до установки RPM пакетов от имени офицера безопасности:
# id -Z officer_u:officer_r:officer_t:s0-s5:c0.c15 # setenforce 0 # <Обновить систему>
Если необходимо чтобы файлы на файловой системе обновили свой контекст безопасности согласно новой политике, необходимо выполнить:
# touch /.autorelabel
При следующей перезагрузке для файловой системы будет применены новый контекст файлов.
# reboot
Policy's internals
systemd
systemd-journald - выполняется в домене trusted_t. Это обусловленно тем, что ему необходимо читать статус процессов из /proc/<PID>. В свою очередь, proc-файлы для каждого процесса имеют контекст процесса.
Network
IPv6 не поддерживается! /* since we don't support any IPv6 labeling protocols right * now we can optimize everything away until we do */ Для конечного дистрибутива должно быть собрано специальное ядро, без IPv6.
Одна TCP транзакция для
auditallow unconfineddomain file_type:{ peer } recv;
# ./getpeercon_server 777 -> running as officer_u:generic_r:generic_t:s3:c3-s15:c0.c31 -> creating socket ... ok -> listening on TCP port 777 ... ok -> waiting ...
Посылает сообщение nc из s4:c4
# echo 'Hello world!' | nc localhost 777
выглядит следующим образом:
granted { recv } for pid=9879 comm="nc" saddr=127.0.0.1 src=58387 daddr=127.0.0.1 dest=777 netif=lo scontext=officer_u:generic_r:generic_t:s3:c3-s15:c0.c31 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9879 comm="nc" saddr=127.0.0.1 src=777 daddr=127.0.0.1 dest=58387 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4-s15:c0.c31 tcontext=generic_u:object_r:unlabeled:s0 tclass=peer granted { recv } for pid=9879 comm="nc" saddr=127.0.0.1 src=58387 daddr=127.0.0.1 dest=777 netif=lo scontext=officer_u:generic_r:generic_t:s3:c3-s15:c0.c31 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9879 comm="nc" saddr=127.0.0.1 src=58387 daddr=127.0.0.1 dest=777 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9867 comm="gs" saddr=127.0.0.1 src=777 daddr=127.0.0.1 dest=58387 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4-s15:c0.c31 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9879 comm="nc" saddr=127.0.0.1 src=58387 daddr=127.0.0.1 dest=777 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9867 comm="gs" saddr=127.0.0.1 src=777 daddr=127.0.0.1 dest=58387 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4-s15:c0.c31 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer granted { recv } for pid=9867 comm="gs" saddr=127.0.0.1 src=58387 daddr=127.0.0.1 dest=777 netif=lo scontext=officer_u:generic_r:generic_t:s4:c4 tcontext=generic_u:object_r:unlabeled:s4:c4 tclass=peer
Разбор:
- getpeercon_server работает как s3:c3-s15:c0.c31<br\>
- nc работает как s4:c4-s15:c0.c31<br\>
- трафик от s4:c4-s15:c0.c31 получается s4:c4<br\>
- tcontext=generic_u:object_r:unlabeled:s0 - SYN, SYN+ACK (видимо, от ядра, поэтому s0)
- tclass == peer относится только к классу трафика
- define(`all_peer_perms',`{ recv }') - у этого класса (трафика) есть только один метод recv
- в сокет scontext=officer_u:generic_r:generic_t:s4:c4 припёрся пакет с tcontext=generic_u:object_r:unlabeled:s4:c4
- получается, что где-то в районе accept новому сокету назначается контекст в соответствии с тем, кто туда пришёл. Cубъект тут — именно сокет, поскольку пакет кладётся в буфер сокета, а какой именно процесс потом его оттуда будет брать, неизвестно.
- сокет - можно и другому процессу передать. смысл в том, что читать из сокета может совсем не тот процесс, который его создавал.
- при системном вызове проверка SOCKET__READ, и вот тут уже субъектом будет процесс, а объектом — сокет
- sid нового сокета делается через security_sid_mls_copy(sksec->sid, peersid, &newsid);
- без CIPSO у тебя peersid не приедет с другого конца
- security_sid_mls_copy() - computes a new sid based on the given * sid and the mls portion of mls_sid.
- вот так у сокета и получается s4:c4, поскольку оно из пакета приходит
- s3:c3 создал себе сокет, в него пришел трафик, и сокет стал == уровню трафика который туда попал.
вот нашёл место, где sock->sk->sk_security->sid всё-таки попадает в SOCK_INODE(sock)->i_security->sid selinux_sock_graft вызывается из inet_accept так что по идее в проверках read для socket можно ловить приём не тем процессом, каким надо с учётом изменения уровня сокета
CIPSOv4
Пакеты маркируются утилитой netlabelctl.
В заголовок IP пакета добавлется security option 134 (0x86)
http://tools.ietf.org/html/draft-ietf-cipso-ipsecurity-01
После добавления в IP заголовок пакета security option некие сетевые протоколы начинают странно себя вести.
ICMP
Каждый ответ приходит с сообщением: unknown option 86. Что само по себе, режет глаза. Но по словам Paul Moore:
I agree it is annoying, but ping is a rather unusual application in that it deals with raw packets (at least the last time I looked at the code). At some point I should probably submit a patch to quiet the CIPSO option but that is a very low priority item on my todo list.
# ping 192.168.55.2 PING 192.168.55.2 (192.168.55.2) 56(84) bytes of data. 64 bytes from 192.168.55.2: icmp_req=1 ttl=64 time=0.125 ms unknown option 86 64 bytes from 192.168.55.2: icmp_req=2 ttl=64 time=0.085 ms unknown option 86
22:36:34.316321 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 96, options (unknown 134,EOL)) 192.168.55.2 > 192.168.55.1: ICMP echo request, id 3627, seq 1, length 64
TCP
TCP подглючивает местами, и именно неправильно выставляется cksum:
192.168.55.1.8811 > 192.168.55.2.38542: Flags [S.], cksum 0xef7a (incorrect -> 0xce92), seq 3815783505, ack 2513766785, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0 или 22:40:35.038984 IP (tos 0x0, ttl 64, id 47912, offset 0, flags [DF], proto TCP (6), length 52, options (unknown 134,EOL)) 192.168.55.1.8811 > 192.168.55.2.38543: Flags [F.], cksum 0xef6e (incorrect -> 0x73c6), seq 1, ack 8, win 115, length 0
Paul Moore отвечает как:
I remember there being an issue with IP/TCP checksum offload and tcpdump/wireshark if it was run on the system being monitored. You can always use netstat or similar tools to verify the number of dropped/bad packets on a system.
А еще некто ответил:
так кривые контрольные суммы для своих исходящих пакетов там всегда были надо сетевуху отупить совсем, чтобы там всё заполнено было в сеть они нормальные уходят просто считаются аппаратно можно в ethtool -K поотрубать всё
sshd
Для openssh нужен патч, иначе sshd демон будет закрывать все соединения со следующим сообщением:
Jul 5 22:29:21 se1 sshd[4881]: fatal: Connection from D*\v\312\230\177 with IP options: 86 0b 00 00 00 01 01 05 00 04 04 00
Клиент будет обламываться как:
# ssh 192.168.55.1 ssh: ssh_exchange_identification: Connection closed by remote host
Для этого нужно приложить патч: openssh-5.2p1-allow-ip-opts.patch.
ALT Linux
В ALT Linux решено, отключить маркировку трафика s0.
Но, в тоже самое время маркировать трафик, например, s0:c1.
Это достигнуто изменением:
- netlabel_tools. В команду netlabelctl добавлен переключатель: s0 on|off. С помощью этого переключателя можно указать ядру, следует ли маркировать трафик s0.
- Пропатчено ядро. git.alt. Данный патч должен быть в ядре std-def.
Создатель защищенного дистрибутива должен иметь файл конфигурации для netlabel следующего содержания:
# cat /etc/netlabel.rules cipsov4 add pass doi:1 tags:1 map del default map add default protocol:cipsov4,1 map s0 off
И должен быть настроен systemd, чтобы правила для netlabel применялись при загрузке ОС:
# systemctl enable netlabel
CUPS
- CUPS должен быть собран с cups-1.6.1-rh-lspp.patch
Патч позволяет при печати документов локально через сокет: /var/run/cups/cups.sock передавать контекст отправителя.
- Файл настройки /etc/cups/cupsd.conf должен быть отредактирован:
- Закоментировать строку Listen *:631 (при этом отключится WEB-интерфейс). К сожалению патч выше не умеет доставать SeLinux контекст из сетевых пакетов. Думаю этому можно его научить (stanv@).
- Добавить строку ClassifyOverride No -- что запретит пользователю передавать опцию -o job-sheets=none (запретит пользователю вручную отключать печать сумирующей страницы для задания).
- Добавить строку Classification selinux -- или Classification te или Classification mls. После чего в CUPS будет создаваться переменная: security-context которую можно потом прочитать: cupsGetOption("security-context", noptions, options). Эта опция указывает что для каждого задания печатать дополнительно две страницы (вначале и в конце).
- При указании опции Classification <banner> должна присутствовать страница-банер по пути: "/usr/share/cups/banners/<banner>
Вот тут начинается самое интересное.
- До недавного времени страница-баннер могла быть в формате PostScript. В PostScript передаются содержимое всех переменных (security-context) и потом можно запрограммировать на PostScript как красиво создать стреницу баннер с имеющимися переменными. В RHEL (в *) можно "украсть" красивые баннеры в формате PostScript, которые умеет печатать содержимое переменной security-context. Проблема кроется в том что переменные в CUPS будут содержать UTF8 текст. И в PS документе они будут искажены.
- Мы создали патч для фильтра bannertopdf который позволяет заполнять готовые PDF-формы.
В багзиле мантейнера заведена ошибка, где можно получить дополнительную информацию: openprinting bugzilla Порядок работы:
- В OpenOffice создается документ.
- Документ должен состоять не более одной страницы.
- Документ заполняется согласно требованиям.
- В места где должна выводится информация из окружения CUPS нужно вставить поле текст.
- Назначить полю нужное имя.
- Доступные имена полей можно посмотреть в файле cups-filters/filter/bannertopdf.c, функция get_known_opts()
- Документ сохранятся, потом экпортируется в PDF.
- Полученный PDF-файл сохраняем в /usr/share/cups/data
- Пишем новый banner для фильтра bannertopdf и кладем его в /usr/share/cups/banners. Примером может служить файл form
- В cups используем опцию: -o job-sheets=secret или правим конфигурационные файлы соответственно для использования этой опции.
В refpolicy для домена cupsd_t определены следующие свойства:
mls_fd_use_all_levels(cupsd_t) mls_file_downgrade(cupsd_t) mls_file_write_all_levels(cupsd_t) mls_file_read_all_levels(cupsd_t) mls_rangetrans_target(cupsd_t) mls_socket_write_all_levels(cupsd_t)
Сборка RPM пакета userspace утилит
Разработчики ведут работу над следующими пакетами в одном git-репозитории:
- libsepol
- libselinux
- checkpolicy
- libsemanage
- policycoreutils
- sepolgen
git-репозиторий доступен по адресу:
$ git remote add upstream http://oss.tresys.com/git/selinux.git
Информация об этом репозитории находится в :
http://userspace.selinuxproject.org/trac/wiki/Contributing
Для каждого релиза приложения приложения они ставят сами тег вида (например): sepolgen-1.2.1
Но такой тег не аннотирован, и он не проскочит в git.alt. Но нам и не нужно чтобы он туда проскакивал.
Из этого репозитория можно независимо собрать любой из пакетов. Поэтому на сборку каждый пакет прийдется отправлять по отдельности.
Также имеет значение в какой последовательности собирать пакеты. Пакеты следует обновлять в вышеприведенной последовательности.
Совместимые версии пакетов можно посмотреть в: http://userspace.selinuxproject.org/releases/
Пример, как обновить policycoreutils
Выкачать у stanv@ или кого еще базу:
> git clone git.alt:/people/stanv/packages/selinux.git
Удалить ветку policycoreutils. Так как мы не уверены что именно stanv@ собрал последний пакет policycoreutils в Сизиф.
> git branch -D policycoreutils
Добавить git-репозиторий, чтобы заполучить последний собраный пакет в Sisyphus (так делать придется для 1-6):
> git remote add gears-policycoreutils git://git.altlinux.org/gears/p/policycoreutils.git > git fetch gears-policycoreutils
Ветка будет содержать последний пакет в Сизифе:
> git checkout -B policycoreutils gears-policycoreutils/sisyphus
Узнаем что этот пакет собирается еще с другой веткой «alt»
> cat .gear/tags/list d36fdac4fc382ec705f93beea05a59801a3faa27 alt …
Ветка «alt» временная и ее не существует в репозитории, она все время удаляется и создается. Она содержит дорабоки для «ALT Linux»:
> git branch -D alt > git checkout -b alt d36fdac4fc382ec705f93beea05a59801a3faa27 Switched to a new branch ‘alt' > git merge policycoreutils-2.2.5
Сейчас мы имеем исходный код для policycoreutils с учетом изменений для «ALT Linux»
> git checkout policycoreutils Switched to branch ‘policycoreutils'
> git merge -s ours alt Merge made by the 'ours' strategy.
Поднимем версию пакета:
> vim policycoreutils.spec > add_changelog policycoreutils.spec > gear-update-tag -a > cat .gear/tags/list 0be22df81fe651c3233b8ab7417849aef0112fff alt 582c2d019926e5a34a637be6ff6eedd93e05f4ca policycoreutils-2.2.5 — поэтому этот тег от разработчиков можно не пушить на git.alt
> git add policycoreutils.spec > gear-commit
> gear-create-tag -n policycoreutils-2.2.5-alt1
> git push alt policycoreutils-2.2.5-alt1 > git push alt policycoreutils
Запустить задание на сборку пакета
> ssh git.alt build selinux.git policycoreutils-2.2.5-alt1
Перейти на сборку следующего пакета.