SELinux 101
|
14-12-2014, 04:50
|
|||
|
|||
SELinux 101
Under SELinux, køres systemet med MAC, Mandatory Access Control, hvor man uden SELinux kører Discresionary Acces Control.
Kort fortalt er DAC, de typiske Read, Write og Execute permissions, man kan sætte for root, brugere og "other". Der er selvfølgelig untagelse, hvis man f.eks. kører med ACLs, som man også kan i Linux. MAC tilbyder et miljø, der default har Deny på alt, og alt der skal kunne tilgå noget, skal have en Allow policy. Der findes følgende fire forskellige måder at køre SELinux på: Citer:Selinux 4 access control forms:MCS er en Multi Category System og er en overbygning på MLS. Denne intro til SELinux dækker kun TE, selv om kommandoerne sådan set, er de samme. SELinux er bygget op omkring Labels. Alt får en label, og denne fortæller, hvad der tillades. Hvis man vil undersøge, hvilken label en fil har, kan man ikke bruge ls -l, som ellers sidder i fingrene hos de fleste: Citer:root@selinux:~# ls -l Man kan dog se, der er kommet et punktun efter "-rw-r--r--", altså "-rw-r--r--.", og dette viser, filerne på dette system, har fået labels. Det er her, man ville se et +, hvis systemet kørte med Access Lists. Vi er så heldige, at tegnet Z, ikke bruges i så forfærdelig mange kommandoer på linux, og derfor bliver dette brugt til at vise labels med i SELinux. Citer:root@selinux:~# ls -Z Får du ikke dette output, kan du kontrollere at SELinux kører med: root@selinux:~# check-selinux-installation /etc/pam.d/login is not SELinux enabled Citer:root@selinux:~# sestatus Hvis du ikke har behov for al informationen, som ovenstående kommando giver, kan man nøjes med at bruge "getenforce": Citer:root@selinux:~# getenforce Denne viser dog ikke, om SELinux vil køre, efter en reboot. Alt har labels, når man har aktiveret SELinux. Både filer, sockets, processes, brugere osv. Her er et eksempel på hvordan root ser ud lige nu: Citer:root@selinux:~# id -Z Her er den kørende Apache2 process: Citer:root@selinux:~# ps -efZ |grep apache Brugere i SELinux er dog ikke det samme som, den bruger man logger ind med. Flere linux brugere, kan være under samme SELinux bruger. Lidt som en gruppe af brugere, deler nogle rettigheder. En Process kaldes i SELinux for et "subject", og filer, directories, FIFOs, sockets osv., er "objects". Så subjects arbejder på objects, når man benytter SELinux. En label er i "context", når de er assosieret med en fil, og i et "domain", hvis en label er assosieret med en process. Hvis vi ønsker at se, hvilke SELinux brugere og roller, der er configureret, kan vi gøre det med semanage: Citer:root@selinux:~# semanage user -l Hvis man ønsker at tildele en bruger, en bestemt rolle, kan det gøres således: Citer:root@selinux:~# semanage login -a -s staff_u mian Som vi kan se fra ovensstående eksempl med apache2, er en label delt op i flere dele: user:role:type:level. Hvis det ser lidt underligt ud, at apache2 både kører som root og www-data, er det fordi, Apache2 virker sådan. Apache2 starter som root, så det kan læse certifikater osv., når den starter, den degraderer så sine egne rettigheder til www-data brugeren, og kører med den. Apache2 har følgende label: system_u:system_r:httpd_t:s0. System_u = user, system_r = role, httpd_t = type og s0 er adgangsniveauet. Adgangsniveauet bruges ikke sønderligt i SELinux, når man kører Targeted Enforcement (TE), men er en form for adgangsniveau opdeling, f.eks. s0-s15 hvor S0 kunne svare til Public Information og S15 kunne være Top Secret. Nogle ses som C0-c1023. Her er et andet eksempel: Citer:root@selinux:~# ls -lZ /etc/resolv.conf Kører man Permissive eller Enforcing SELinux bør alt have en label, og det er ufarligt at skifte mellem disse to modes. Man skal dog passe på med at gå direkte fra at have SELinux Disabled, til Enforced, for så er det ikke sikkert, alle labels er på plads og korrekte. Der er flere måder at få sat labels på alt, på: Citer:#fixfiles relabel // Gør dette på et kørende system Hvis man vil ekskludere nogle filer fra at blive relabeled af fixfiles, kan disse angives i "/etc/selinux/fixfiles_exclude_dirs". Det er ikke sikkert, filen findes på forhånd. Brugerfiler og bruger processes, vil ofte være labeled unconfinded_u, hvor systemfiler og system processes, ofte vil have system_u i stedet. Det kan også være user_u. Hvis noget kører uden en targeted policy, vil det formegentlig køre unconfined_u. De fleste distributioner har haft SELinux i mange år, og nogle kommer faktisk i dag, med en Permissive SELinux. Det betyder også at når man installerer pakker, så får man, til lagt de fleste, færdiglavede policies med, og skal ikke tænke på at lave dem selv. Lige det, hjælper ikke udviklere, som laver deres egne programmer, compiler et program fra source, eller bruger en tar ball. Hvordan sætter vi så disse labels? Det er der flere svar på. Jeg vil starte med et typisk pitfall, før vi dykker ned i detaljerne. SELinux labels flytter på samme måde som DAC permissions gør. Når man opretter en ny fil, arver sin context fra det directory, den ligger i. Flytter man en fil, vil filens context flytte med. Så man skal være varsom, hvis man flytter filer fra en context til en anden. Hvis man kopierer en fil, og destinationsfilen allerede eksisterer, vil den nye fil, overtage den gamle fils label. Altså hvis man kopierer ovenpå den eksisterende. Kopierer man en fil, og den ikke allerede findes, der hvor den kopieres hen, svarer det til en ny fil, og filen vil arve sin context, fra det directory, filen kommer til at ligge i, efter kopieringen. Hvis man f.eks. selv har compilet nmap, som har brug for lidt flere rettigheder, end de andre filer man har i /usr/bin/, vil nmap arve sin context, eller få en label, ud fra, den context, /usr/bin mappen har. Det kan man formegntlig ikke få nmap til at køre med, og det kan vi ændre på flere forskellige måder. Vi kan bruge "chcon", som står for Change Context, eller vi kan bruge "semanage". Nedenstående to kommandoer gør det samme: Citer:#chcon --type traceroute_exec_t /usr/bin/nmap // Change Context type traceroute_exec_t for /usr/bin/nmap Bemærk at _t i traceroute_exec_t står for type, så derfor bruger vi -t for type, eller --type. Får man ændret noget, man ikke ville have ændret, kan man bruge "restorecon" til at restore den originale context for den fil, man har ændret: Citer:#restorecon /usr/bin/nmap Man kan selvfølgelig også bruge chcon og restorecon rekursivt, hvis det er nødvendigt. Det kan være brugbart, hvis man f.eks. har fået rodet for meget i /var/www. Så kan man rekursivt genskabe sin context med kommandoen: Citer:#restorecon -R /var/www Her er et eksempel på, hvordan en fil ændres fra type user_home_t til etc_t, og herefter tilbage: Citer:root@selinux:~# ls -lZ Hvis man har lavet en ny fil der hedder foo.html, kan man sætte dens context, ved at henvise til det directory, filen ligger i. Den er meget tilsvarende de andre metoder: Citer:#chcon --reference /var/www/html /var/www/html/foo.html OBS: chcon er i deb pakken coreutils og semanage er i policycoreutils. Man kan også kaste et blik på man eller info page for genhomedircon og setfiles kommandoerne. Hvis man ønsker at bruge sin home folder, til webindhold, som man ofte gør, hvis man bruger vhosts til hjemmesider, kan man sætte disse filer til typen httpd_sys_content_t. Citer:#semanage fcontext -a -t httpd_sys_content_t "/home/bob/html(/.*)?" // Bemærk at i en shell, vil udsagn i gåseøjne, bliver fortolket. Det kan også være man ønsker at have nogle CGIs tilgængelig, for at skabe noget dynamisk indhold: Citer:#semanage fcontext -a -t httpd_sys_script_exec_t "/home/bob/html/cgi-bin(/.*)?" En ting man støder på, hvis man f.eks. flytter sine html filer til sit home dir, er at webserveren vil blive nægtet adgang. Dette skyldes af apache2 kører i en anden context end din home folder: Citer:root@selinux:/var/www# ls -lZ En home folder har en helt anden label. typen er user_home_t, hvor den i /var/www/ er httpd_sys_content_t. For ikke at ødelægge det for meget for sig selv, kan man med fordel benytte sig af SELinux booleans. Det er en form for shortcuts, som enten kan være slået til eller fra. Eller det var engang, og det lader vi som om, det stadig er. For at give apache2 adgang til sit hjemmedrev, kan man sætte en boolean som hedder httpd_enable_homedirs. Dette kan, som det meste andet, gøres på flere måder. Nedenstående kommandoer gør det samme: Citer:#semanage boolean -m --on httpd_enable_homedirs Som man kan se her under, fortæller de ikke noget, når det går godt. Citer:root@selinux:~# setsebool -P httpd_enable_homedirs on Der er rigtig mange af disse booleans, og disse kan ses med semanage, eller getsebool kommandoerne. Hvis man f.eks. ønsker at tillade CGI, kan man tilføle en "grep" sammen med kommandoerne. Her er et par eksempler med de to kommandoer. Man kan se, de har forskelligt output: Citer:root@selinux:/var/www# getsebool -a |grep cgi For at få en idé om, hvilke booleans der er, er det bare at køre en af ovenstående kommandoer, uden at smide det i gennem grep. OBS: setsebool og getsebool er i pakken policycoreutils, lige som semanage. En anden ting man sikkert vil støde på, er at apache2 kun må lytte på port 80 og 443. Det er godt hvis det er en prod server, alle kan tilgå fra Inetnettet. Hvis det f.eks. lykkes en hacker at uploade netcat og er han nød til at sætte den til at lytte på en anden port end 80 eller 443, da apache bruger disse to. Så vil det ikke være muligt for Apache2s address space, at lytte på andre porte. Men det kan være, man ønsker at køre software som webmin eller lign., som normalt lytter på tcp port 10000. Så er man nød til at ændre http_port_t, så apache2 får lov til at lytte på den ønskede port. Dette kan også gøres med semanage, med følgende kommando: Citer:#semanage port -a -t http_port_t -p tcp 10000 Ønsker man at se, de porte der er registreret i SELinux, kan man gøre det med kommandoen semanage. Der er en hel del, da det svarer meget til /etc/hosts. Her kan vi se, hvilke porte der er tilknyttet ftp: Citer:root@selinux:~# semanage port -l |grep ftp Hvad gør man så, når det ikke virker? Hvis man har installeret auditd pakken, vil der komme meddelelser i /var/log/audit/audit.log, og det vil jeg bestemt anbefale. Ellers må man undersloge /var/log/messages for output. Outputtet er lidt finurligt, og tidsstemplingen er i et forunderligt format. For at få noget at se på, har jeg started exim op igen: Citer:root@selinux:/usr/bin# service exim4 start For at skille, hvad der er gået godt, og hvad der ikke er, kan man med fordel bruge grep. En ting man kan søge på, er "denied", en anden ting er AVC. Når der i SELinux opstår en access violation, altså når en policy ikke er blevet overholdt, kommer der en AVC (Access Vector Cache) besked. Denne kan man greppe efter: Citer:root@selinux:/usr/bin# tail /var/log/audit/audit.log |grep AVC En bedre måde at søge efter disse fejl på, er at bruge en af de gode linux audit værktøjer, der kommer prepacked fra distributøren. Et af dem er ausearch, som er bygget til at søge i daemon logs. OBS: ausearch er i pakken auditd, som også giver /var/log/audit/audit.log filen. Her kan vi se, hvordan de samme beskeder fra exim4 processen er opstillet gennem ausearch. Dette er en søgning på AVC beskeder som ikke er gået godt: Citer:root@selinux:/usr/bin# ausearch -i -m AVC,USER_AVC -sv no Bemærk at tidsstemplingen nu er til at læse. Nogle gange, kan man være nød til at rette eksisterende policies, men det anbefales at rapportere disse fejl til distributøren af pakken, så det kan blive rettet. Måske skal man lave en policy til et program, man selv har lavet, og dette kan gøres med audit2allow, som kommer i policycoreutils pakken. Man kan skrive sin policy i hånden, eller man kan vælge at tage de deny AVCs fra audit.log, og lade audit2allow lave en allow policy for dig. Reelt set, kan man pipe indholdet fra /var/log/audit/audit.log direkte ind i audit2allow, men der er en god chance for, den policy man får ud i den anden ende, tillader lidt for meget. Citer:#audit2allow < /var/log/audit/audit.log Ovenstående må anses som at være aller sidste udvej. Man kan f.eks. udstede følgende kommando, som laver en Type Enforcementrule, ud fra deny AVCs fra de sidste 5 minutter, der tillader denne handling: Citer:#ausearch -i -m AVC -sv no -ts recent | audit2allow Får man ikke hvad man forventer, skal man være opmærksom på, meddelelserne kan være mere end 5 minutter gamle. Se man eller info page for ausearch. De kan rigtig mange ting. Her er et par søgninger: Citer:root@selinux:~# ausearch -i -m AVC -sv no | grep exim4 | audit2allow Lad os prøve at lave en ny policy. Vær dog opmærksom på, du kan risikere at overskrive en eksisterende policy, hvis du vælger samme navn. Citer:root@selinux:~# ausearch -i -m AVC -sv no -se exim_t | audit2allow -m ny-exim > ny-exim.te Så har vi dannet en ny policy. Denne skal så "kompileres, linkes og loades", før den virker. Bemærk versionsnummeret i den. Denne er dannet med version 1.0, og det anbefales at ændre denne, hver gang, denne policy ændres. Det gør det i hvert fald nemmere at holde hånd i hanke med, hvilken policy, der er den nyeste og formegntlig, den der er loaded ind i linux kernen. Det næste trin er at danne en .mod fil og dette gøres med følgende kommando: Citer:root@selinux:~# checkmodule -M -m -o ny-exim.mod ny-exim.te Så skal vi have lavet en policy module package fra det binære policy modul. Der efter loades vores nye package ind i linux kernen, hvor SELinux lever: Citer:root@selinux:~# semodule_package -o ny-exim.pp -m ny-exim.mod Det tager lidt tid at loade modulet, men det er normalt. Jeg har ladet mig fortælle, der kan gå lidt tid, før modulet rent faktisk bliver aktivt. Lad os prøve at tømme audit.log og genstarte exim4. Hvis vi ikke får nogen AVCer, lader det til, vores nylavede policy virker: Citer:root@selinux:~# service exim4 stop Virker den policy man har lavet, ikke efter hensigten, kan den unloades med samme kommando, som den blev loaded med, bare med --remove i stedet for --install. Citer:root@selinux:~# semodule --remove ny-exim.pp Når man tester sin SELinux installation, og arbejdet med nogle problemer, har man den mulighed, at sætte hele sytemet i Permissive mode. Så kan man debugge, ved at se i /var/log/audit.log, men slippe for, at systemet ikke virker. Hvis man vælger at gøre dette, skal man selvfølgelig være opmærksom på, man har fravalgt SELinux beskyttelsen for hele systemet, og det kan potentielt, efterlade systemet åbent, mens du arbejder. En anden og måske bedre måde, er at sætte Permissive mode på den enkelte process, i stedet for hele systemet. Så har resten af systemet sikkerheden fra SELinux, mens man frit kan arbejde med den process, der giver problemer. Citer:#semanage permissive -a exim_t // Tillader at exim4 kører permissive, selv om resten af systemet kører enforced. Jeg skal dog sige, jeg ikke kan få ovenstående til at virke lige nu. For at få adgang til filer og andet, skal man selvfølgelig også have adgang via DACs RWX. Der er rigtig meget læsestof i man og info pages. SELinux er en god og nem måde at gøre en maskine lidt mere sikker på, og det brude faktisk ikke være opt-in, men opt-out, efter min mening. Jeg vil dog ikke anbefale, at installere det på din legeplads. Og vær opmærksom på, det reelt er en chance for, du får lukket dig selv ude. SELinux til Debian er efterhånden rimelig godt med. Der kan dog stadig være nogle udfordringer med nogle display managere, som skal have finpudset deres policies. En anden ting man skal være opmærksom på er, at kommandoer udføres langsomt. Der er en del overhead, når man gør noget, hvor adgangen skal kontrolleres. Det påvirker ikke daemons det store. De bliver et ekstra sekund på at starte, men når de først kører, burde man ikke mærke noget til det. https://github.com/TresysTechnology/refpolicy/wiki https://wiki.debian.org/SELinux/Setup?hi...etup%29%29
---
Writing a shellcode decoder stub in assembly is like talking gibberish in such a way that it is still perfectly intelligible. - iTick |
|||
|
User(s) browsing this thread: 1 Gæst(er)