Oddělení uživatelů na sdíleném hostingu

Školení, která pořádám

Méně náročné webové aplikace nevytíží celý server, proto je ekonomické jich na jednom stroji provozovat více. S virtuálními servery je spojena nemalá režie (v každém musí běžet všechny společné komponenty zvlášť), takže se často používá stejné prostředí pro více aplikací. Tyto aplikace je potom od sebe nutné z bezpečnostních důvodů odstínit.

PHP k tomuto odstínění používá jednak konfigurační direktivu safe_mode, která porovnává vlastníka skriptu s vlastníkem manipulovaného souboru nebo jeho adresáře. Problém s touto direktivou je ten, že když si PHP skriptem vytvoříme soubor (třeba cache nebo soubor nahraný uživatelem), tak s tímto souborem může manipulovat skript jiného uživatele vytvořený jeho skriptem. A naopak když si skriptem vytvoříme adresář (třeba strukturu cache), tak nadále nemáme přístup k souborům uloženým v tomto adresáři. Oba problémy jsou způsobené tím, že vlastníkem souboru vytvořeného skriptem je uživatel, pod kterým běží webový server. Z toho důvodu bude direktiva safe_mode v PHP 6 odstraněna a už dnes se na ni nevyplatí spoléhat.

Druhou direktivou, kterou PHP za účelem odstínění uživatelů sdíleného hostingu nabízí, je open_basedir. Ta se sice o něco pracněji konfiguruje (každému uživateli je potřeba nastavit jeho vlastní adresář), nemá ale koncepční problém jako safe_mode.

Obě direktivy se za určitých okolností dají obejít.

  1. Za prvé se nevztahují na programy spouštěné z příkazového řádku (ty je tedy vhodné zakázat nebo omezit).
  2. Za druhé se čas od času objeví místo v PHP, které tyto direktivy nerespektuje. To platí i pro nestandardní extenze.
  3. A za třetí je možné některými útoky tyto direktivy přenastavit.

Vedle ochrany, kterou nabízí PHP (tu je samozřejmě vhodné nechat zapnutou), je užitečné uživatele oddělit i jiným způsobem. Sám používám a doporučuji jednoduchý systém, který uživatele oddělí už na úrovni souborového systému. Vychází z této struktury adresářů:

weby --x
  vrana.cz_gr7a1e r-x
    private r-x
    public r-x
      data rwx
    temp rwx

Práva jsou uvedena z pohledu uživatele, pod kterým běží webový server. Nad společným adresářem weby chybí právo pro čtení, což znamená, že v něm nelze získat seznam souborů. K názvu každého podadresáře je připojen náhodný řetězec (v ukázce gr7a1e), který v kombinaci s předchozím faktem způsobí, že útočník nemá jak zjistit název adresáře jiného uživatele. Aby se ho nedozvěděl, tak je samozřejmě vhodné v konfiguraci vypnout zobrazování chyb a náhodný řetězec volit co nejdelší a skutečně náhodný (neměl by to být např. hash názvu domény).

Alternativou je použít modul mod_chroot, který uživatele oddělí tak, že každému zpřístupní jen jeho adresář. Je potřeba ale dát pozor na několik věcí.

Přijďte si o tomto tématu popovídat na školení Bezpečnost PHP aplikací.

Jakub Vrána, Seznámení s oblastí, 4.9.2009, diskuse: 45 (nové: 0)

Diskuse

Martin:

Security by obscurity.To jsem si mohl myslet. Klasický přístup laika k bezpečnosti.

Aplikace uživatele si je "zaheslované" cesty vědoma a pokud je v ní sebemenší chybka, tak ji útočníkovi ráda sdělí. Ten má pak volnou cestu. Opravdu Vás pane Vráno prosím, tohle neškolte! Uživatelé tato hloupá řešení rádi přebírají a ještě si začnou myslet, že začali rozumět bezpečnosti a administraci serveru.

Místo toho raději školte těchto pár trivialit, které se ale masově nedodržují (přitom je to jen základ bez kterého to nejde):
- PHP nikdy nesmí běžet jako modul
- nikdy nedávat souborům práva 777. Zápis musí být povolen je pro speciálně vybrané části (uživatelé netuší která bije a když něco nejde, šup 777 je zachrání)
- přístup do adresářů musí být zajištěn NA ÚROVNI OS!!! (nikdy jen safe_mode, open_basedir) - správně chroot, pouhá práva (klíčové slovo suexec), selinux apod.
- security by obscurity NEBRAT!

fos4:

ze by Emkei ? :-)

Martin:

Ne to fakt ne :)

Marek Šudák:

Jistě, vaše zásady jsou základ, ale celkové vyznění vašeho příspěvku nechápu.

1) Aplikace jde nastavit tak, aby nikdy cestu nesdělovala.
2) Cokoliv, co útočníkovi ztíží jeho práci a nezpůsobí příliš mnoho námahy nebo komplikací, se vyplatí použít.
3) Ačkoliv se nedá spoléhat jen na ni, na zásadě "security by obscurity" není v principu nic špatného a nelze ji paušálně odsuzovat. Např. použití nestandardního portu pro SSH přístup je nejefektivnější způsob, jak se vyhnout útokům.

Martin:

To vidím, že tomu nerozumíte. Bezpečnostní zásady nejsou totiž žádné "moje zásady", které si prosazuji kvůli nějaké duševní nemoci. Bezpečnostní zásady jsou principy, bez kterých žádná bezpečnost není.

1) To jistě lze. Ale když uživatel sdíleného hostingu svoji aplikaci blbě naprogramuje, bude tam mít díru a někdo mu to kvůli ní hackne, je to jeho chyba nebo chyba hostingu? Jednoznačně chyba hostingu!
2) To jistě ano. Blbá opatření se ale jako "ztížení" nepočítají!
3) "security by obscurity" se MUSÍ paušálně odsuzovat. Jinak laici získají falešný pocit bezpečnosti i tam, kde žádná není. Prezentovat laikům na školení (!) nesmyslnou metodu a nazývat ji "alternativa k chroot", to je opravdu silné kafe.

Marek Šudák:

Vidím, že jste v ráži..

Špatně jsem to formuloval, myslel jsem "vámi popsané zásady".

1) Když uživateli někdo hackne špatně napsanou aplikaci, je to chyba hostingu? To myslíte vážně?

2) Opatření popsané v článku není ideální, ale útočníkovi může ztížit jeho práci. Čili i když se vám může zdát blbé, přidává další kousek bezpečnosti navíc.

3) "Security by obscurity" se nemůže paušálně odsuzovat. Jen je potřeba nespoléhat jen na ni, to je snad jasné.

4) Já popsané opatření jako alternativu k chroot nikdy neoznačil, nechápu tedy, co dělá ve vaší reakci na můj příspěvek.

ikona Jakub Vrána OpenID:

1. Martin myslel asi to, že když má jiný uživatel sdíleného hostingu děravou aplikaci a mě kvůli tomu hacknou, tak je to samozřejmě chyba hostingu. Ten "jiný uživatel" totiž může být rovnou útočník.

ikona Jakub Vrána OpenID:

Zdá se, že jsi článek nečetl příliš důkladně:

1. V článku je jasně uvedeno, že je vhodné vypnout zobrazování chyb. Cesta může uniknout i jinak (např. veřejným phpinfo()), ale to by byla chyba návrhu aplikace.

2. Doporučené nastavení práv je v článku také uvedeno.

3. Modul mod_chroot je také zmíněn.

V ideálním světě by PHP jako modul neběželo, ideálně by měl každý svůj vlastní virtuální server. Ale v reálném světě jako modul obvykle běží a článek se k této situaci staví pragmaticky.

O Security by obscurity se nejedná, protože systém se nesnaží zatajit žádnou svou vlastnost. Pracuje samozřejmě s nějakým tajemstvím, ale totéž platí pro jakékoliv přihlašování heslem nebo i certifikátem. Podle stejné logiky by třeba HTTPS a přihlašování SSH spadalo také do Security by obscurity.

Martin:

Děkuji za upozornění! Nyní jsem si přečetl článek znovu, tentokrát opravdu důkladně, a již je mi vše jasné.

To mi prve nedošlo, že ten hash je vlastně takové heslo, anebo certifikát. Chytré!

ikona Jakub Vrána OpenID:

V článku je jasně uvedeno, že by to neměl být hash, ale náhodný řetězec. Trochu větší pozornost při čtení a přesnost při vyjadřování by neškodila.

cvičební úbor:

Milý Martine, pokud jste při výkonu práce stejně těkavý a nepozorný jako tady, tak bych si od vás nenechal zabezpečit ani zámek od tříkolky.

Prdlořeznictví Krkovička, n. p.:

ad security by obscurity) tvoje věta "systém se nesnaží zatajit žádnou svou vlastnost" asi nebude úplně přesná. Principem security by obscurity je zatajit to, jak je dané řešení navržené nebo implementované. Podle mě, např. pojmenováním adresáře vrana.cz_gr7a1e je jedna z vlastností návrhu a implementace, která je samozřejmě zatajovaná (útočníkovi není znám ani onen koncový náhodný řetězec ve jménu adresáře (security by design) ale ani to, zda-li je tento typ pojmenovávání vůbec použit (security by obscurity)). Ale souhlasím, že tím, že's nám řekl, jaký způsob zabezpečení používáš ty, se efekt security by obscurity úplně vytratil. :-)

ikona Jakub Vrána OpenID:

U sdíleného hostingu se dá předpokládat, že útočník má na stejném serveru účet také. Název svého adresáře si zjistit dovede a z něj může dovodit, že to je asi něco, co bude pro každého jiné (obzvlášť když to zkusí). Pokud by to přidané smetí bylo z něčeho odvozené (např. hash domény), tak by to pochopitelně bylo security by obscurity (tajili bychom, jak jsme ho vygenerovali a kdyby se to proláklo, tak je náš systém napaden). Ale když je vygenerováno skutečně náhodně, tak to tajit nepotřebujeme.

Mírná odbočka: Popisy Security by obscurity se zaměřují převážně na kód. Jak je to ale s daty? Když by útočník aplikaci napadl díky tomu, že se dostal k datům, se kterými aplikace pracuje, jednalo by se také o Security by obscurity? Má někdo odkaz na důvěryhodný zdroj?

Yaplik:

Základní problém tohodle řešení je v tom, že sice používá připojenej řetězec jako heslo, nicméně s ním jako s heslem nepracuje - dá se zjistit jak z konfiguráku apache, tak třeba z errorlogu (File does not exists: ...) nebo ještě jednodušeji z /proc/self/fd/*.

ikona v6ak:

To jo, ale na druhou stranu: jak se k tomu dostaneš z pozice útočníka?

ikona Jakub Vrána OpenID:

Děkuji za připomínku. Konfigurák Apache i errorlog musí být pro uživatele apache nepřístupný pro čtení.

Schválně jsem si nechal vypsat /proc/self/fd/* z PHP skriptu a byly tam jenom logy Apache. Momentálně zpracovávaný skript ani soubor otevřený přes fopen() z PHP tam nebyl.

Dundee:

Pokud už člověk konfiguruje sdílený hosting, tak by měl přemoci svojí lenost a mírný úbytek zdrojů, a zprovoznit PHP jako FastCGI se Suexecem. PHP pak běží přímo pod právy uživatele hostingu (třeba vrana-cz) a většina bezpečnostních problémů tak mizí. Mimito pokud i FTP server je schopný kopírovat soubory se správným vlastníkem, odpadá potřeba měnit práva souborů (na 777), do kterých potřebují PHP skripty něco zapisovat.

Díky tomu všemu pak open_basedir ani není potřeba, stačí nastavit správně práva čtení (chmod o-r) na filesystému.

Současné nastavení většiny sdílených hostingů, kdy skripty všech uživatelů běží pod právy Apache, považuji za pěknou prasárnu.

Messa:

Já vím, že už jsem tady asi třetí, ale proč se uživatelé neoddělují tak, že by každý měl vlastní instanci PHP? Na českém hostingu jsem to zatím neviděl, ale v zahraničí to některé lepší hostingy používají a já osobně také. Je to systémové řešení všech těchto problémů i prevence před bugy v PHP. Navíc to je obecné řešení pro jakoukoliv platformu, ne jen pro PHP. Dá se to udělat pomocí FastCGI, nebo každému uživateli spouštět jeho vlastní Apache nebo jiný webserver (proxovaný; zde vidím problém typu falešného $_SERVER['REMOTE_ADDR']). Paměť je dnes celkem levná, i hodně desítek takových uživatelů na jednom stroji bych si dokázal představit. Co si o tom myslíte? Nebo každý, kdo tohle chápe, má už dávno vlastní stroj a webhostingům se jen zdálky směje? :)

ikona Jakub Vrána OpenID:

Důvody jsou hlavně ekonomické. Webhosterům jde o to na jeden server nacpat co nejvíc uživatelů, což jde nejlépe právě s modulem. FastCGI je sice srovnatelně rychlé, ale zase se jim asi špatně spravuje.

Dundee:

Také bych za tím viděl tu ekonomiku. FastCGI a zvlášť se Suexecem žere o dost víc paměti než mod_php. Divím se ale, že české hostingy nenabízejí i nějaké vyšší tarify, kde by toto bylo. Pravděpodobně je to kvůli poptávce. Mezi uživateli sdílených hostingů asi pramálo lidí o FastCGI vůbec slyšelo. A kdo už o něm slyšel, ten odstěhuje weby do zahraničí nebo připlatí o stovku víc a pronajme si celé VPSko.

Michal Prynych:

Presne tak, myslim si, ze ta spotreba + prace administratoru navic by cenu na uroven virtualu

Dundee:

Práce navíc je dost zanedbatelná. Jakmile je FastCGI jednou nastaveno, nepotřebuje žádnou extra péči.

pojízdná kočka:

A jak je to při přechodu na jinou verzi? Nemusí se všechno dělat zvlášť pro každého uživatele?

Messa:

Při řešení pomocí FastCGI se právě naskytuje možnost dát každému uživateli si vybrat, jakou verzi PHP chce používat, popř. používat vždy tu nejaktuálnější.

Všechno zvlášť pro každého uživatele musí dělat jen administrátor, který si na to nedokáže naprogramovat skript; a takový podle mě nemá u webhostingu co dělat :-)

Jakub Mach:

Na Českém hostingu používáme FastCGI už několik let...

Dundee:

Mohu se zeptat, proč nepoužíváte suexec?

Jakub Mach:

Suexec používáme. Ještě k té správě - oproti mod_php je správa určitě lepší. Například hned vidíte, komu patří příslušný PHP proces...

Dundee:

Pak je tedy škoda, že to nemáte nikde uvedené.

Jakub Mach:

To je pravda. Ale důvod je právě ten, že to málokomu něco řekne...

Dundee:

Na stránce nastavení PHP (http://www.cesky-hosting.cz/pro-zakazniky/napoveda/nastaveni-php.html) jsou samé technické informace, tam by to být klidně mohlo.

Jakub Mach:

OK, je to tam :-)

Dundee:

Supr. Přeji mnoho nových spokojených zákazníků :)

Jakub Mach:

Díky :-) Jsem zvědav, kolik nám jich zrovna tahle informace přinese ;-)

Jakub Mach:

Omlouvám se, to měla být reakce na to, že u nás FastCGI nikdo nepoužívá. Ale je pravda, že uživatelé o tom nic nevědí. Nebo je jim to jedno.

cvičební úbor:

Btw. jak můžu (jako běžný uživatel na sdíleném hostingu) vůbec "vypnout" nějakou funkci (viz. zmiňované phpinfo())?

Juan:

Pěkné řešení. Jen se zeptám, neměly by se ty náhodně generované klíče pravidelně měnit? Tzn. nemá to stejnou náchylnost na útok hrubou silou jako jakékoliv heslo?

ikona Jakub Vrána OpenID:

Bylo by to vhodné. Ještě lepší by bylo kontrolovat, jestli se někdo ten útok hrubou silou nesnaží provádět, ale popravdě řečeno nevím jak.

Michal Prynych:

nejak prochazet chybove logy a hledat velky vyskyt chyby: soubor nenalezen(s patricnou cestou)? ale nevim jestli je to z pohledu webhostera legalni prochazet cizi logy

ikona v6ak:

Zajisté existují různé postupy zachycení pokusů o přístup k souborům...

pojízdná kočka:

Přes .htaccess s použitím modifikátoru -F (neexistující adresář)?

DocX:

pokud útok pochází z PHP skriptu jiného uživatele hostingu, tak to .htaccess nijak neovlivňuje.

A nenapadá mě jak to zjistit bez zásahu do serveru. Pokud skript budou pouze kontrolovat jestli adresář existuje, žádnou chybu to nevyvolá.

Jedině snad nějaký log na úrovni OS.

Martin 2:

Jako rychle reseni jak nedat seznam zakazniku a jejich data  dobre, ale pokud je chyba v open_basedir, pak si muze utocnik cist kupu veci ze systemu, coz je zasadne nezadouci, pri vychozim zabezpeceni vetsiny distribuci pak zjisti i cesty k www-home.
Zabezpeceni PHP je kombinace vice prvku, chroot/prava na urovni PHP i Apache i system, SELinux apod. Jen se divim, ze bezpecnost php je v ofic dokumentaci tak strucne odbyta, mnoho hostingu je pro zkuseneho utocnika deravy.

Klobouk dolu Jakube, ze jsi s touhle kuzi sel na trh. Ale tipuji, nejen dle reakci, ze Tvoje reseni jako temer Linux/Unix laika je lepsi nez zadne reseni vetsiny administratoru.

Ales:

Reseni s nahodnym retezcem tu je uz dlouho. Presny zdroj nevim, ale kolega ho pouzil uz na serveru, ktery se instaloval odhadem pred 4 lety. vim jen, ze to reseni nekde vygooglil.

ikona Jakub Vrána OpenID:

Ano, já jsem to vymyslel v roce 2003 při práci na serveru mysms.cz. Neříkám, že jsem byl první nebo jediný, kdo to vymyslel, ale nikde jsem o tom nečetl. Od roku 2006 to říkám na svém školení.

Miloš Brecher:

PHP mám instalované jako modul Apache - z věrohodných návodů na internetu jsem se dočetl, že je to technicky nejlepší a nejmodernější řešení. A zde Martin píše, že PHP nesmí nikdy běžet jako modul. Je to tak velká bezpečnostní díra? Zatím jsem s tím problémy neměl.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.