Eigenes Profil erstellen Beispiel ncat: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Zeile 297: Zeile 297:
 
* systemctl start netzkatze
 
* systemctl start netzkatze
 
* systemctl status netzkatze
 
* systemctl status netzkatze
 +
* echo -e "Hello, World" | nc localhost 8888
 
* ausearch -m AVC -ts recent
 
* ausearch -m AVC -ts recent
  

Version vom 13. Januar 2023, 11:53 Uhr

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)

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 /usr/lib/systemd/system/netzkatze.service

Normal sollte man dies unter /etc/systemd/system schreiben können. Dies führt unter Fedora zu einer Fehlermeldung.

[Unit]
Description=Simple Enforcement test

[Service]
Type=simple
ExecStart=/usr/local/bin/netzkatze -lp 8888
#StandardOutput=append:/tmp/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:/tmp/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/netzkatze.log
  • restorecon -Fv /netzkatze/netzkatze.log
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 /tmp/netzkatze.log
Hello, World

netzkatze-Logging über einen Boolean an-/ausschalten

  • cat netzkatze.te
policy_module(netzkatze, 1.0.0)

require {
    attribute port_type;
    attribute file_type;
    class tcp_socket { name_bind };
    class file { append };
}
########################################
#
# 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;

# allow port to receive things

allow netzkatze_t netzkatze_port_t:tcp_socket { name_bind };
allow netzkatze_t node_t:tcp_socket { node_bind };
allow netzkatze_t self:tcp_socket { listen accept };

# allow netzkatze to write a log file

if (allow_netzkatze_log) {
    allow netzkatze_t netzkatze_log_t:file { append };
}

domain_use_interactive_fds(netzkatze_t)

files_read_etc_files(netzkatze_t)

miscfiles_read_localization(netzkatze_t)

sysnet_dns_name_resolve(netzkatze_t)
  • 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 /tmp/netzkatze.log
Wird geloggt