Eigenes Profil erstellen Beispiel ncat
Zur Navigation springen
Zur Suche springen
Installation
- Wenn noch nicht geschehen
Vorbereitungen
Das Programm nc soll über systemd eingeschränkt auf einen Port ausgeführt werden.
Kopieren der Netzkatze
- cp /usr/bin/ncat /usr/local/bin/netzkatze
Wir erstellen einen Arbeitsordner
- mkdir netzkatze
- cd netzkatze
Benutzerdefiniert Richtlinie für das Programm “netzkatze” generieren
- --init bestimmt dass das Program von systemd aufgerufen wird.
- --application für normale Programme
- sepolicy generate --init /usr/local/bin/netzkatze
Failed to retrieve rpm info for selinux-policy Created the following files: /root/selinux/modules/netzkatze/netzkatze.te # Typ-Enforcement-Datei (Hierstehen die Regeln drin) /root/selinux/modules/netzkatze/netzkatze.if # Schnittstellendatei () /root/selinux/modules/netzkatze/netzkatze.fc # Dateikontext-Datei (Dateien die vom Programm aufgerufen werden, werden gelabled) /root/selinux/modules/netzkatze/netzkatze_selinux.spec # Spezifikationsdatei () /root/selinux/modules/netzkatze/netzkatze.sh # Einrichtungsskript (Kompilieren und Installieren)
netzkatze.sh anpassen
- vim netzkatze.sh
... echo "Unloading Policy if present" set -x semanage port -l | grep 8888 && semanage port -d -p tcp 8888 semodule -l | grep netzkatze && semodule -r netzkatze echo "Building and Loading Policy" make -f /usr/share/selinux/devel/Makefile netzkatze.pp || exit /usr/sbin/semodule -i netzkatze.pp # Generate a man page off the installed module sepolicy manpage -p . -d netzkatze_t # Fixing the file context on /usr/local/bin/netzkatze and label port /sbin/restorecon -F -R -v /usr/local/bin/netzkatze semanage port -a -t netzkatze_port_t -p tcp 8888 ...
Modul konfigurieren
- Die Grundeinstellung der .te Datei erlaubt lediglich den Start des Dienstes über systemd.
- Es muss noch ein Porttyp für das Programm definiert werden.
- Ein Port muss über semanage port mit den benutzerdefinierten Porttype gelabelt werden
- Ein User muss zu den nötigen Prozess Typen transitieren dürfen.
Permissive für das Modul ausschalten
- Standardmäßig ist das Modul auf permissive gestellt, d.h. SELinux schränkt das Programm nicht ein.
- Um das zu ändern muss diese Zeile auskommentiert werden:
# permissive netzkatze_t;
Attribute und Klassen laden
- Um die Standardregeln von SELinux benutzen zu dürfen, müssen diese mit require im Skript geladen werden
- Die Listen der Standardobjekte und -assoziationen kann man sich mit seinfo -x … anzeigen
- Für unseren Fall benötigen wir folgendes:
require { attribute port_type; class tcp_socket { name_bind }; }
- Liste der Attribute (erforderlich, um später die Dateilabels zuweisen zu können):
- seinfo -a | grep your_attribute
- Liste der Klassen und deren Permissions (erforderlich, um Permissions zuweisen zu können):
- seinfo -x -a | grep your_class
- Liste der Commons und deren Permissions (Klassen erben Permissions von diesen):
- seinfo --commmon
- seinfo -x common your_common
Porttyp deklarieren und Typentransition erlauben
Vollständige Konfiguration zum freischalten eines Ports:
policy_module(netzkatze, 1.0.0) require { attribute port_type; class tcp_socket { name_bind }; } ######################################## # # Declarations # type netzkatze_t; type netzkatze_port_t; type netzkatze_exec_t; init_daemon_domain(netzkatze_t, netzkatze_exec_t) typeattribute netzkatze_port_t port_type; #permissive netzkatze_t; ######################################## # # netzkatze local policy # allow netzkatze_t self:fifo_file rw_fifo_file_perms; allow netzkatze_t self:unix_stream_socket create_stream_socket_perms; # Erlaube eine named_bind an den netzkatze_port_t. # Die zuordnung für welchen Port es gilt, erfolgt später. allow netzkatze_t netzkatze_port_t:tcp_socket { name_bind }; # Erlaube generell ein node bind. allow netzkatze_t node_t:tcp_socket { node_bind }; # Erlaube netzkatze das Akzeptieren und Hören von Datenströmen allow netzkatze_t self:tcp_socket { listen accept }; domain_use_interactive_fds(netzkatze_t) files_read_etc_files(netzkatze_t) miscfiles_read_localization(netzkatze_t) sysnet_dns_name_resolve(netzkatze_t)
Einrichten des neuen Richtlinienmoduls mithilfe des erzeugten Setup-Skripts
- Es wird kompliert, installiert und relabled
- ./netzkatze.sh
Building and Loading Policy + make -f /usr/share/selinux/devel/Makefile netzkatze.pp Compiling default netzkatze module Creating default netzkatze.pp policy package rm tmp/netzkatze.mod tmp/netzkatze.mod.fc + /usr/sbin/semodule -i netzkatze.pp libsemanage.add_user: user sddm not in password file + sepolicy manpage -p . -d netzkatze_t ./netzkatze_selinux.8 + /sbin/restorecon -F -R -v /usr/local/sbin/netzkatze Relabeled /usr/local/sbin/netzkatze from unconfined_u:object_r:bin_t:s0 to system_u:object_r:netzkatze_exec_t:s0 + pwd + pwd=/root/selinux/modules/netzkatze + rpmbuild --define _sourcedir /root/selinux/modules/netzkatze --define _specdir /root/selinux/modules/netzkatze --define _builddir /root/selinux/modules/netzkatze --define _srcrpmdir /root/selinux/modules/netzkatze --define _rpmdir /root/selinux/modules/netzkatze --define _buildrootdir /root/selinux/modules/netzkatze/.build -ba netzkatze_selinux.spec ...
den erlaubten Port labeln
- Nachdem das Modul kompiliert und geladen ist, sollte SELinux den neuen Porttyp kennen
- Um ihn mit den Port 8888 zu assozieren, verwendet man semanage port:
- semanage port -a -t netzkatze_port_t -p tcp 8888
Check
- semanage port -l | grep netzkatze
netzkatze_port_t tcp 8888
Systemd-Dienst erstellen
- Für die erste Version soll netzkatze nach der ersten Nachricht stoppen und noch keine Logdatei schreiben.
- Die erhaltene Nachricht soll einzusehen sein über:
- systemctl status netzkatze
- cat /etc/systemd/system/netzkatze.service
[Unit] Description=Simple Enforcement test [Service] Type=simple ExecStart=/usr/local/bin/netzkatze -lp 8888 #StandardOutput=append:/netzkatze/netzkatze.log #Restart=always [Install] WantedBy=default.target
Permanente Änderung des Kontexts
Service starten
- systemctl start netzkatze
- systemctl status netzkatze
Einschränkung überprüfen
Man sieht an anhand von netzkatze_t das von init_t richtig tranistiert wurde.
- ps -eZ | grep netzkatze
system_u:system_r:netzkatze_t:s0 3598 ? 00:00:00 netzkatze
- ss -Znlt | grep netzkatze
LISTEN 0 1 0.0.0.0:8888 0.0.0.0:* users:(("netzkatze",pid=3598,proc_ctx=system_u:system_r:netzkatze_t:s0,fd=3))
Einschränkungen testen
- echo -e "Hello, World!" | nc localhost 8888
- systemctl status netzkatze
● netzkatze.service - Netzkatze-Kontext Test Loaded: loaded (/lib/systemd/system/netzkatze.service; enabled; vendor preset: enabled) Active: inactive (dead) since Fri 2022-11-25 09:57:07 CET; 3s ago Process: 8878 ExecStart=/usr/local/sbin/netzkatze -l -p 8888 (code=exited, status=0/SUCCESS) Main PID: 8878 (code=exited, status=0/SUCCESS) CPU: 4ms Nov 25 09:56:50 se-debian systemd[1]: Started Netzkatze-Kontext Test. Nov 25 09:57:06 se-debian netzkatze[8878]: Hello, World! Nov 25 09:57:07 se-debian systemd[1]: netzkatze.service: Succeeded.
Systemd darf keinen nicht gelabelten Port benutzen
- vim /usr/lib/systemd/system/netzkatze.service
[Unit] Description=Netzkatze-Kontext Test [Service] Type=simple ExecStart=/usr/local/sbin/netzkatze -l -p 9998 #StandardOutput=append:/netzkatze/netzkatze.log [Install] WantedBy=default.target
- systemctl daemon-reload
- systemctl start netzkatze
- systemctl status netzkatze
● netzkatze.service - Netzkatze-Kontext Test Loaded: loaded (/lib/systemd/system/netzkatze.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Fri 2022-11-25 10:15:23 CET; 2s ago Process: 8964 ExecStart=/usr/local/sbin/netzkatze -l -p 9998 (code=exited, status=1/FAILURE) Main PID: 8964 (code=exited, status=1/FAILURE) CPU: 4ms Nov 25 10:15:23 se-debian systemd[1]: Started Netzkatze-Kontext Test. Nov 25 10:15:23 se-debian netzkatze[8964]: Can't grab 0.0.0.0:9998 with bind : Permission denied Nov 25 10:15:23 se-debian systemd[1]: netzkatze.service: Main process exited, code=exited, status=1/FAILURE Nov 25 10:15:23 se-debian systemd[1]: netzkatze.service: Failed with result 'exit-code'.
Verstöße anzeigen
- ausearch -m AVC -ts recent
---- time->Fri Nov 25 10:15:23 2022 type=AVC msg=audit(1669367723.907:425): avc: denied { name_bind } for pid=8964 comm="netzkatze" src=9998 scontext=system_u:system_r:netzkatze_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket permissive=0
von audit2allow Vorgeschlagene Änderungen (nicht übernehmen!)
Mit audit2allow kann man sich Vorschläge machen lassen um Einstellungen zu ändern. In diesem Fall wäre es eine Erlaubnis unreserved_ports zu nutzen. Wir wollen dies aber nicht. Wir wollen den jeweiligen Port dediziert zuordnen.
- ausearch -m AVC -ts recent | audit2allow -R
require { type netzkatze_t; type unreserved_port_t; class tcp_socket name_bind; } #============= netzkatze_t ============== allow netzkatze_t unreserved_port_t:tcp_socket name_bind;
netzkatze loggen
- systemd soll nun alles, was netzkatze erhält in die Logdatei /netzkatze/netzkatze.log schreiben.
- mkdir /netzkatze
- Dies sieht man auch, wenn wir die .service Datei verändern:
- cat /usr/lib/systemd/system/netzkatze.service
[Unit] Description=Simple Enforcement test [Service] Type=simple ExecStart=/usr/local/bin/netzkatze -lp 8888 StandardOutput=append:/netzkatze/netzkatze.log Restart=always [Install] WantedBy=default.target
- systemctl daemon-reload
- systemctl start netzkatze
- systemctl status netzkatze
- echo -e "Hello, World" | nc localhost 8888
- ausearch -m AVC -ts recent
---- time->Fri Nov 25 12:45:56 2022 type=AVC msg=audit(1669376756.023:446): avc: denied { append } for pid=9347 comm="netzkatze" path="/tmp/netzkatze.log" dev="sda1" ino=655791 scontext=system_u:system_r:netzkatze_t:s0 tcontext=system_u:object_r:tmp_t:s0 tclass=file permissive=0
Modul modifizieren
- cat netzkatze.te
policy_module(netzkatze, 1.0.0) require { type init_t; attribute port_type; attribute file_type; class tcp_socket { name_bind }; class file { append open }; class dir { write create }; } ######################################## # # Declarations # type netzkatze_t; type netzkatze_port_t; type netzkatze_exec_t; type netzkatze_log_t; init_daemon_domain(netzkatze_t, netzkatze_exec_t) typeattribute netzkatze_port_t port_type; typeattribute netzkatze_log_t file_type; #permissive netzkatze_t; ######################################## # # netzkatze local policy # allow netzkatze_t self:fifo_file rw_fifo_file_perms; allow netzkatze_t self:unix_stream_socket create_stream_socket_perms; # Erlaube Typentransition zum gelabelten Port für name bind. allow netzkatze_t netzkatze_port_t:tcp_socket { name_bind }; # Erlaube generell ein node bind. allow netzkatze_t node_t:tcp_socket { node_bind }; # Erlaube netzkatze das Akzeptieren und Hören von Datenströmen allow netzkatze_t self:tcp_socket { listen accept }; # Erlaube netzkatze das Anhängen in netzkatze_log_t markierte Dateien allow netzkatze_t netzkatze_log_t:file { append }; allow init_t netzkatze_log_t:file { append open}; allow init_t netzkatze_log_t:dir { create write }; domain_use_interactive_fds(netzkatze_t) files_manage_default_files(init_t) files_read_etc_files(netzkatze_t) miscfiles_read_localization(netzkatze_t) sysnet_dns_name_resolve(netzkatze_t)
Modul neuinstallieren und Logdatei labeln
- ./netzkatze.sh
- touch /netzkatze/netzkatze.log
- semanage fcontext -a -t netzkatze_log_t "/netzkatze(/.*)?"
- restorecon -R /netzkatze
Relabeled /tmp/netzkatze.log from system_u:object_r:tmp_t:s0 to system_u:object_r:netzkatze_log_t:s0
- systemctl daemon-reload
- systemctl stop netzkatze
- systemctl start netzkatze
Berechtigung testen
- echo -e “Hello, World” | nc localhost 8888
- cat /netzkatze/netzkatze.log
Hello, World
netzkatze-Logging über einen Boolean an-/ausschalten
- cat netzkatze.te
policy_module(netzkatze, 1.0.0) require { type init_t; attribute port_type; attribute file_type; class tcp_socket { name_bind }; class file { append open }; class dir { write create }; } ######################################## # # Declarations # type netzkatze_t; type netzkatze_port_t; type netzkatze_exec_t; type netzkatze_log_t; init_daemon_domain(netzkatze_t, netzkatze_exec_t) typeattribute netzkatze_port_t port_type; typeattribute netzkatze_log_t file_type; bool allow_netzkatze_log true; #permissive netzkatze_t; ######################################## # # netzkatze local policy # allow netzkatze_t self:fifo_file rw_fifo_file_perms; allow netzkatze_t self:unix_stream_socket create_stream_socket_perms; # Erlaube Typentransition zum gelabelten Port für name bind. allow netzkatze_t netzkatze_port_t:tcp_socket { name_bind }; # Erlaube generell ein node bind. allow netzkatze_t node_t:tcp_socket { node_bind }; # Erlaube netzkatze das Akzeptieren und Hören von Datenströmen allow netzkatze_t self:tcp_socket { listen accept }; # Erlaube netzkatze das Anhängen in netzkatze_log_t markierte Dateien if (allow_netzkatze_log) { allow netzkatze_t netzkatze_log_t:file { append }; allow init_t netzkatze_log_t:file { append open}; allow init_t netzkatze_log_t:dir { create write }; } domain_use_interactive_fds(netzkatze_t) files_manage_default_files(init_t) files_read_etc_files(netzkatze_t) miscfiles_read_localization(netzkatze_t) sysnet_dns_name_resolve(netzkatze_t)
Schauen ob der Boolean gesetzt ist
- getsebool allow_netzkatze_log
allow_netzkatze_log --> on
- setsebool allow_netzkatze_log 0
- echo “Wird nicht geloggt” | nc localhost 8888
- cat /tmp/netzkatze.log
- setsebool allow_netzkatze_log 1
- systemctl restart netzkatze
- echo “Wird geloggt” | nc localhost 8888
- cat /netzkatze/netzkatze.log
Wird geloggt