PHP: Bezpečnostní tipy

15. 1. 2020

Bezpečnost začíná již na začátku projektu. Je důležité se vzdělávat v tomto směru, využívat nejnovější možnosti zabezpečení a zároveň nezapomínat na základní bezpečnostní pravidla. Příspěvek je přehled základních bodů pro začínající vývojáře, ale může zároveň sloužit jako “checklist” pro zkušené vývojáře.

PHP 7.4 je zde

Udržujte verzi PHP v kondici jeho včasnou aktualizací. Získáte nejen výkonnostní a bezpečnostní aktualizace, ale vyhnete se do budoucna problému nákladného refaktorování kódu se změnou standardů a zastaralých funkcí.

Aktuální verzi PHP získáte příkazem

$ php -v

Roadmapu PHP naleznete na: https://www.php.net/supported-versions.php

Kompletní nastavení PHP vypíšete příkazem

$ php info

PHP moduly

Udělejte pořádek v modulech. Moduly mohou obsahovat blackdoory a nebo jiné bezpečnostní hrozby. Odeberte z konfigurace nepoužité moduly a zkontrolujte si, zda používáte aktuální dostupné verze.

Aktuální moduly v konfiguraci získáte příkazem

$ php -m

Výpis chyb

V produkčním (ostrém) prostředí zakažte výpis chyb, upozornění a informací běhu scriptu v konfiguraci a naopak nastavte jejich zápis do logovacího souboru. Vypsané informace mohou v některých případech obsahovat důležité fragmenty kódů (nebo autentifikační údaje), které může zneužít útočník a nebo pomůžou ke zmapování struktury aplikace.

Logovací soubor není odpadkový koš!

Pravidelně kontrolujte logy aplikací a přístupové logy. Získáte informace o chybách, které test při buildu nemusel prověřit a zároveň můžete včas rozpoznat podezřelé chování.

Tip: Automatizujte to.

Nebezpečné funkce PHP

Zakažte nativně používat potenciálně nebezpečné funkce v scriptech.

php.ini

disable_functions = apache_child_terminate,apache_get_modules,apache_note,apache_setenv,define_syslog_variables,disk_free_space,disk_total_space,diskfreespace,dl,escapeshellarg,escapeshellcmd,exec,extract,get_cfg_var,get_current_user,getcwd,getenv,getlastmo,getmygid,getmyinode,getmypid,getmyuid,ini_restore,ini_set,passthru,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_get_last_error,pcntl_getpriority,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_strerrorp,pcntl_wait,pcntl_waitpid,pcntl_wexitstatus,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,php_uname,phpinfo,popen,posix_getlogin,posix_getpwuid,posix_kill,posix_mkfifo,posix_setpgid,posix_setsid,posix_setuid,posix_ttyname,posix_uname,posixc,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,ps_aux,putenv,readlink,runkit_function_rename,shell_exec,show_source,symlink,syslog,system

Používejte limity

Dlouhý čas běhu v kombinaci s několikanásobným spuštění z volného zdroje může odstavit server. Určete proto maximální čas běhu scriptu.

php.ini

max_execution_time

Nastavte limit pro maximální upload souborů přes rozhraní aplikace.

php.ini

upload_max_filesize
post_max_size

Zakažte ošklivé a zlé “<?”

V konfiguraci php.ini zakažte zkrácený zápis začátku scriptu a tím ošetříte možnost podsunutí cizího fragmentu v XML datech.

php.ini

short_open_tag = Off

XSS (Cross-Site Scripting)

Ošetřete proměnné před vložením cizího kódu obsahující fragmenty užívající ve sriptu interpretátoru PHP.

Základní zabezpečení můžete provést funkcí

htmlspecialchars($string, ENT_QUOTES, 'UTF-8');

Tip: Používejte framework, který řeší tento problém za Vás.

CSRF/XSRF (Cross-Site Request)

Zranitelnost v předávání či rozšiřování požadavku nejčastěji pomocí metody GET/POST a replikaci požadavku bez ověření. Zabezpečte aplikaci tokenem, který bude obsahovat unikátní sezení uživatele, invalidaci, rozsah obsahu a bude předávám společně s daty. Při každém přijatém požadavku validujte platnost tokenu.

Detailnější informace na: https://cs.wikipedia.org/wiki/Cross-site_request_forgery

Tip: Používejte framework, který řeší tento problém za Vás.

Session Hijacking

Bezpečností problém, který může nastat odcizením unikátního session ID sezení uživatele. Odcizení vznikne napadením počítače návštěvníka škodlivým softwarem anebo únikem dat uložených v session files na serveru nedostatečným či špatným zabezpečením. Svažte v aplikaci session ID s dalším parametrem jako je IP adresa, user agent a jiné možné vlastnosti identifikace unikátnosti návštěvníka včetně jejich kombinace. 

Tip. Další úroveň může být behaviorální zabezpečení.

Session lifetime

Provádějte invalidaci session souborů. Můžete tím zachránit uživatele, který se zapomene odhlásit na cizím zařízení. Nastavení naopak může způsobit nevhodné chování aplikace. Doporučuji si přečíst následující vlákno: https://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes

SQL Injection

Parametry předávané v SQL dotazu ošetřete před vložení cizího fragmentu obsahující znaky využívající se v samotném zápisu SQL dotazu. Nejčastěji jsou to uvozovky nebo pomlčky. Používejte PDO driver a Prepared statements pro bezpečné vkládání hodnot.

Phpinfo()

Nenechávejte na serveru volně dostupný soubor s phpinfo(). Výpis informací obsahuje podrobné informace o sestavení a lze je využít k nalezení nezabezpečeného rozšíření či konfigurace pro získání přístupu minimálně do aplikace v horším případě do serveru.

SSL (Secure Sockets Layer)

Komunikace mezi klientem a serverem na protokolu HTTP není šifrována a proto ji lze snadno odposlouchávat. Zabezpečte komunikaci SSL technologií, která probíhá na protokolu HTTPS a je šifrovaná.

SSL technologie vyžaduje vytvoření certifikátu od důvěrné autority pro šifrování spojení. Jako bezplatnou rozšířenou autoritu můžete použít Let’s Encrypt: https://letsencrypt.org/.

Pro snadnou správu (vytvoření, smazání, automatické aktualizování) můžete využít na Linuxové platformě nástroj Certbot: https://certbot.eff.org/.

SQL safe mode

Mód přístupu ke zdroji dat. Ve verzi PHP 7.2 je možnost nastavení již zrušena, ale pro starší verze je nutné nastavit:

sql.safe_mode=On
magic_quotes_gpc=Off

Testujte nejen funkčnost, ale i bezpečnost

Psaní aplikace bez testování je jako jezdit na kole bez přilby. Programátoři píšou testy na různé komponenty a součásti, ale nezapomínejte na testování bezpečnosti, která není pouze přihlašovací stránka!

Skryjte důvěrné soubory a adresáře

Zkontrolujte, zda není možné zobrazit soubory s konfigurací přes požadavek prohlížeče (napište si test) anebo zdrojové části aplikace. Vhodné řešení je vytvoření veřejného adresáře (public) obsahující index aplikace a ostatní data umístit mimo tento adresář.

Na Apache serveru to může provést pomocí souboru .htaccess a na Nginx serveru pomoci NGINX Directives.

Možnosti v .htaccess: https://www.jakpsatweb.cz/server/htaccess.html

Zakažte traverzování adresářů v .htaccess

Options -Indexes

Zakažte procházení celé struktury

Order allow,deny
Deny from all

NGINX Directives: http://nginx.org/en/docs/dirindex.html

Zdroje

https://www.php.net/manual/en/security.php

https://httpd.apache.org/docs/current/misc/security_tips.html

Nejnovější příspěvky