PHP: Bezpečnostní tipy
15. 1. 2020Bezpeč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