[MEGOLDVA] Portszűrés process szinten SELinux-szal

Fórumok

szerk.: sikerült megoldanom a problémát, az elkészült policy csomagot megtalálhatjátok ebben a kommentemben.

Szokatlan ötletem támadt: azt találtam ki, hogy lekorlátozom a desktop gépemen futó firefox-ot (de csak ezt az egy processt), hogy csak egy adott portra tudjon kapcsolódni. Mivel CentOS-t használok (6.4-es release), kézenfekvőnek tűnt az SELinux-on keresztül megoldani a korlátozást (esetleg iptables-szel kombinálva), de sajnos hosszas kísérletezgetések után sem boldogultam a feladattal.A cél:

* a firefox process csak egy adott portra (SOCKS proxy) tudjon kapcsolódni (esetleg korlátozva azt is, hogy csak localhost-ra mehessen a kapcsolat, bár a portszintű korlátozás is elegendő lenne)
* a névfeloldás is tiltva legyen (SOCKS-on keresztül kell a neveket feloldani)
* minden egyéb hálózati forgalom tiltva legyen (pl. ICMP, kapcsolódás bármilyen egyéb portra, bármilyen protokollon)

Ami eddig felmerült lehetséges megoldásként:

* egyedi kontextus létrehozása a firefox folyamatnak, amiben limitálom a hálózati hozzáféréseket
* iptables-szel vizsgálni a csomag címkéjét, és az OUTPUT láncon beállítani a korlátozást

A saját policy készítéséhez a meglévő "mozilla" policy-t klónoztam le - kiiktattam belőle minden hálózatra vonatkozó részt, és csak a szükséges portra engedélyeztem a kapcsolódást, de ez sajnos nem segített, továbbra is korlátlanul ki tudtam menni az internetre.

Az iptables-hez találtam egy modult (xt_selinux), ami tudja vizsgálni a csomagok címkéjét, de ez gyárilag nincs telepítve és azt írja a fejlesztő, hogy nem garantált a kompatibilitása, mivel olyan belső SELinux adatstruktúrákra épít, amelyek bármikor megváltozhatnak. Saját otthoni rendszerről lévén szó, ez annyira nem riaszt el, de jobban szeretném, ha a lehető legegyszerűbben, beépített eszközökkel tudnám a feladatot megoldani.

A probélma szerintem oda vezethető vissza, hogy hiába állítom be a megfelelő fájlkontextust a firefox binárisának, a process mégis unconfined domain-ben fut:


chcon user_u:object_r:mozillastrict_exec_t:s0 ~/firefox-strict/firefox

A folyamatot elindítva az alábbi látszik a ps wauxZ kimenetében:


LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 nb 7076 6.7  6.0 971740 238376 ? Sl 08:52   3:45 /home/nb/firefox-strict/firefox

Könnyen lehet, hogy félreértelmezek valamit az SELinux koncepciójában, de nem tudom, hogy mit. Más processek a nekik kijelölt domainben futnak, sejtésem szerint a firefox-nál is ezt kellene megoldani valahogy a korlátozások működéséhez:


system_u:system_r:rpcbind_t:s0  rpc       1957  0.0  0.0  18972   916 ?        Ss   07:26   0:00 rpcbind
system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 dbus 1972 0.0  0.0 98156 2232 ? Ssl 07:26   0:01 dbus-daemon --system
system_u:system_r:NetworkManager_t:s0 root 1983 0.0  0.1  90376  4504 ?        Ssl  07:26   0:00 NetworkManager --pid-file=/var/run/NetworkManager/NetworkManager.pid
system_u:system_r:modemmanager_t:s0-s0:c0.c1023 root 1989 0.0  0.0 55832 2436 ? S   07:26   0:00 /usr/sbin/modem-manager
system_u:system_r:rpcd_t:s0     rpcuser   2004  0.0  0.0  23344  1328 ?        Ss   07:26   0:00 rpc.statd

Van valami ötletetek? Mit csinálhatok rosszul?

Hozzászólások

"unconfined_u:unconfined_r:unconfined_t"
Nem ez a gond?
(csak belekontárkodtam pár napja, nem ismerem mélyebben)

Már bánom, hogy legyalultam a SELinuxos rendszeremet.
A binárisod tuti, hogy bináris? Nem egy script, ami valami hasonló nevű binárist indít? Firefox régen script volt és volt neki külön, más könyvtárban egy valódi binárisa - hacsak nem keverem valamivel.

Egyébként támadt egy szörnyű gyanúm: amit a chcon beállít, az nem csak azt szabályozza, hogy kik férhetnek hozzá a fájlodhoz? Van köze ahhoz is, hogy az azt indító usertől függetlenül, milyen jogai vannak?

A "firefox" fájl, amire a kontextust állítom, egész biztosan bináris fájl:


[nb@nb firefox-strict]$ file ~/firefox-strict/firefox
/home/nb/firefox-strict/firefox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped

Könnyen lehet, hogy igazad van a chcon-nal kapcsolatban. Tovább kísérletezek, jelentkezem a fejleményekkel.

Sikerült megoldani, most már a megfelelő domain alatt fut a firefox folyamat.

A trükk annyi, hogy kell egy ilyen kiegészítés a policy fájlba:


optional_policy(`
        gen_require(`
                type unconfined_t;
                role unconfined_r;
        ')

        mozillastrict_run(unconfined_t, unconfined_r)
')

Ezen kívül még az alábbiakat is be kell illeszteni egy mozillastrict.if nevű fájlba:


interface(`mozillastrict_domtrans',`
	gen_require(`
		type mozillastrict_t, mozillastrict_exec_t;
	')

	corecmd_search_bin($1)
	domtrans_pattern($1, mozillastrict_exec_t, mozillastrict_t)
')

interface(`mozillastrict_run',`
	gen_require(`
		type mozillastrict_t;
	')

	mozillastrict_domtrans($1)
	role $2 types mozillastrict_t;
')

interface(`mozillastrict_role',`
	gen_require(`
		type mozillastrict_t;
	')

	role $1 types mozillastrict_t;

	mozillastrict_domtrans($2)

	ps_process_pattern($2, mozillastrict_t)
	allow $2 mozillastrict_t:process signal;
')

Fordítás és az új modul installálása után ezt látom a ps wauxZ kimenetben:


LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
unconfined_u:unconfined_r:mozillastrict_t:s0-s0:c0.c1023 nb 8461 12.0  2.5 783524 98336 pts/0 Sl+ 19:25   0:01 /home/nb/firefox-strict/firefox

A policy-ben megadott korlátozások működni is látszanak, már csak annyi probléma van, hogy az AVC alert-ek alapján készített engedélyező szabályok felvétele ellenére enforce módban az alábbi hibát kapom, még mielőtt a Firefox elindulhatna:


Couldn't find the application directory.

Nyomozok tovább...

Egy debian7-esen én is "beizzítottam" a SELinuxot, majd nulla ismerettel, google-ről összevadászott infók alapján valamelyest működőképessé tettem.
Miután az audit2why -b már nem talált semmi hibát, beraktam magam a user_u SELinux ... mi is ez? Context? User? Szóval valami ilyesmibe. Na ettől kezdve se a sudo, se a su nem működött. :)
Nagyon örültem, hogy van snapshot a virtualbox-ban. :)

Az SELinuxot gyakran kritizálják a policy-k bonyolultsága és a dokumentáció hiánya miatt...most már testközelből látom, hogy mindkét kritika megállja a helyét. :(

Napok óta szenvedek már ezzel, de mivel mostanra elég közel kerültem a megoldáshoz (szerintem már csak egy olyan policy kell, ami engedi, hogy megkeresse a firefox a saját könyvtárát/binárisát), nem fogom feladni. :)

Én apparmorral próbáltam kicsit kordában tartani a firefoxot pár éve, de már az is sok(k) volt. ;)
Viszont akkor még nem volt olyan lehetőség, mint a SELinux audit2allow toolja, vagy én nem tudtam róla.
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_L…
Ezt ismered?

Köszi a linket, ezt a doksit nem olvastam még, de hasznos olvasmánynak tűnik, ha lesz egy kis időm, átolvasom majd.

Viszont időközben meglett a megoldás: csak ki kellett kapcsolni az audit üzenetek elrejtését (semodule -DB), és máris megjelentek a Firefox indítását megakadályozó avc üzenetek a logban, amiket innentől kezdve a jól ismert audit2allow paranccsal ki tudtam iktatni.

Az eredmény: egy hozzáférések szintjén limitált, tökéletesen működőképes böngésző, ami csak proxyn keresztül képes kimenni a netre. Ha esetleg véletlen kikapcsolom a proxyt (vagy egy "gonosz" weboldal kikapcsolja egy ismert sebezhetőséget kihasználva), akkor az így keletkező request-ek (DNS, HTTP, FTP...) az SELinux ráhatásával timeout-olnak, így el sem jutnak odáig, hogy csomag generálódjon belőlük.

Ha esetleg szüksége lenne valakinek ilyen megoldásra, publikáltam a policy csomagot itt:

http://www.martoncomp.hu/dl/mozillastrict.zip

CentOS 6.4-en garantáltan működik, de gyaníthatóan a legtöbb SELinux-képes, Red Hat Enterprise Linux-ra épülő disztribúción is használható.

A használatához csak egy standalone Firefox-ot kell letölteni (ESR és legfrissebb release egyaránt megfelel), és betenni a ~/firefox-strict könyvtárba. A policy fordításának és telepítésének menete (root-ként):


# cd (kitomoritett_fajlok_helye)
# make -f /usr/share/selinux/devel/Makefile mozillastrict.pp
# semodule -i mozillastrict.pp
# restorecon -R -F -v (user_home_konyvtara)/firefox-strict

Ha minden stimmel, akkor a ~/firefox-strict alól indított firefox process csak és kizárólag a 9050-s portra tud kapcsolódni (tor socks proxy), minden más hálózati forgalom tiltott (DNS, proxy nélküli HTTP, FTP stb), ez természetesen a ZIP-ben lévő .te fájl szerkesztésével tetszőlegesen továbbfejleszthető.

En az egyszeru megoldasok hive vagyok, ezert az SElinux helyett, kulon usereim vannak ffx/p2p/stb celokra.

Az iptables owner moduljaval szabalyozom a net elerest, unix groupokkal a fs jogokat, xauth-tal az X elerest, etc. Par evtizeddel kiforrottabb mint az SElinux, es par (tiz?)ezer sorral kevesebb koban lehet lyuk.

Sajnos debian centrikus vagyok minimum tíz éve, rpm alapú rendszereket csak alig-alig használtam eddig.
(de ha ehhez most hozzáteszem, hogy a tegnap felrakott SuSE szerver mit produkált... és még yum sincs rajta, de feltenni is problémás, mert óbégat, hogy valami más csomagokat el kéne távolítani, amit viszont nem mertem, mert nem tudtam, mit ver agyon... :D)