Stručne: Ak chcete zakázať vykonávanie PHP v uploadoch, najprv zistite všetky priečinky, do ktorých smie PHP zapisovať, a potom v každom z nich zablokujte vykonávanie skriptov v konfigurácii servera, nie cez .htaccess. V Nginx musí blokovanie zaberať pred všeobecným blokom PHP, v Apache patrí do VirtualHost s AllowOverride None. security.limit_extensions = .php v poole FPM a test neškodným súborom prácu uzavrú.
Prečo práve teraz záleží na priečinkoch s uploadmi
Po kritickej zraniteľnosti ako PHP2Shell útočníci zriedka chcú vykonať kód len raz. Chcú sa vrátiť, aj keď sa server neskôr zaplátuje. Najjednoduchšou cestou je webshell: malý súbor PHP uložený v zapisovateľnom priečinku a neskôr otvorený cez prehliadač.
Záplata takýto súbor neodstráni. Kto bol od 20. októbra 2026 online nezáplatovaný, nemal by preto len aktualizovať, ale aj skontrolovať, či niekde neležia nové súbory PHP, a do budúcna zabrániť ich vykonaniu. Ako nálezy správne vyhodnotiť, opisuje Súbory PHP v priečinku s uploadmi: správne vyhodnotenie nálezov.
Blokovanie vykonávania nadväzuje na druhú podmienku. Nebráni tomu, aby sa súbor uložil, ale tomu, aby ho server považoval za program.
Najprv inventúra: kam smie PHP zapisovať?
Väčšina návodov uvádza len priečinok s uploadmi. V praxi aplikácia PHP zapisuje na oveľa viac miest. Každé z nich, ktoré je dostupné cez webový server, potrebuje blokovanie.
| Typ priečinka | Typický obsah | Prečo zapisovateľný |
|---|---|---|
| Uploady, médiá | obrázky, PDF, prílohy | používatelia a redakcia nahrávajú súbory |
| Cache | vytvorené stránky, náhľady obrázkov | aplikácia zrýchľuje doručovanie |
| Temp, import, export | súbory CSV, medzistavy | rozhrania a výmena údajov |
| Zálohy vo webovom koreni | .zip, .sql |
rozšírenia zálohujú „na mieste“ |
| Protokoly vo webovom koreni | chybové a ladiace protokoly | nesprávne nakonfigurované aplikácie |
Ktoré priečinky to na vašom serveri sú, ukáže hľadanie s právami používateľa behu. Nič nemení:
# Všetky priečinky pod /var/www, do ktorých smie zapisovať používateľ PHP
# (upraviť používateľa: www-data, nginx, apache alebo vlastný používateľ poolu)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Ležia v týchto priečinkoch už súbory PHP?
sudo -u www-data find /var/www -type d -writable -print0 2>/dev/null \
| xargs -0 -I{} find {} -maxdepth 1 -type f -iname "*.ph*" 2>/dev/null
Ak prvé hľadanie vráti celý webový koreň, programový kód patrí používateľovi behu. To by ste mali vopred zmeniť, ako opisuje sprievodca Práva k súborom na webovom serveri. Inak neexistuje priečinok, ktorý by sa nemusel blokovať.
Zákaz vykonávania PHP v uploadoch: Nginx
V Nginx rozhoduje poradie. Podľa dokumentácie Nginx sa regulárne výrazy kontrolujú v poradí konfiguračného súboru a vyhráva prvá zhoda. Ak všeobecný blok location ~ \.php$ stojí pred vaším blokovaním, súbor sa vykoná. Jednoduchá lokácia s predponou bez ^~ z rovnakého dôvodu nechráni.
Bezpečný je jeden regulárny výraz pre všetky blokované priečinky, ktorý stojí pred blokom PHP. Pokrýva aj zriedka používané prípony:
server {
# ... základná konfigurácia ...
# 1. Blokovanie zapisovateľných priečinkov, MUSÍ stáť pred blokom PHP
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Všeobecný blok PHP: odovzdávať len existujúce súbory
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/seite1.sock;
}
}
Názvy priečinkov prispôsobte svojej inventúre. Pri aplikáciách s jediným vstupným bodom je cesta cez zoznam povolených ešte silnejšia; vzor ukazuje Bezpečná konfigurácia Nginx pre PHP.
Apache a PHP-FPM: blokovanie na správnom mieste
V Apache patrí blokovanie do konfigurácie servera alebo do VirtualHost. Súbor .htaccess v priečinku s uploadmi je nevhodný, pretože ho môže zmeniť každý, kto tam smie zapisovať. Pre celý webový koreň preto platí AllowOverride None. Podľa dokumentácie Apache je AllowOverride povolené len v blokoch <Directory> bez regulárnych výrazov, nastavte ho teda na webovom koreni a blokovanie cez <DirectoryMatch> pod ním:
<Directory /var/www/seite1/public>
AllowOverride None
Require all granted
</Directory>
<DirectoryMatch "^/var/www/seite1/public/(uploads|media|cache|tmp|export)/">
<FilesMatch "\.(php\d?|phtml|phar|pht|phps)$">
Require all denied
</FilesMatch>
</DirectoryMatch>
Ak ešte beží mod_php, doplňte v tom istom bloku php_admin_flag engine off. Pri PHP-FPM pôsobí druhá zábrana v poole: security.limit_extensions určuje, ktoré prípony FPM vôbec vykoná. Podľa príručky PHP je štandard .php .phar; odporúča sa obmedzenie na .php.
; v poole, napr. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Test neškodným súborom
Či blokovanie zaberá, ukáže len test. Do každého blokovaného priečinka nakrátko uložte súbor, ktorý iba vypíše text, otvorte ho cez doménu a potom ho zmažte.
- Skontrolovať konfiguráciu:
nginx -tresp.apachectl configtest, potom znova načítať. - Vytvoriť testovací súbor, napríklad
uploads/sperrtest.phps obsahom<?php echo 'ausgefuehrt';. - Otvoriť pomocou
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Očakáva sa403. - Ak sa namiesto toho objaví
200a text „ausgefuehrt“, blokovanie nezaberá. Skontrolovať konfiguráciu a poradie. - Testovací súbor zmazať a test zopakovať pre každý priečinok a každý web.
Ak pri inventúre nájdete v zapisovateľných priečinkoch už neznáme súbory PHP, nemažte nič unáhlene. Najprv zabezpečte stav a protokoly, pretože tieto súbory sú dôkazmi. Ako potom postupovať, opisuje Rozpoznanie a odstránenie webshellov.
Ako sa funkcie uploadu v kóde stavajú bezpečne, s kontrolou typu a uložením mimo webového koreňa, uvádza sprievodca Bezpečná implementácia nahrávania súborov v PHP.
Záver: zapisovať áno, vykonávať nie
Blokovanie vykonávania v zapisovateľných priečinkoch je jedno z najúčinnejších jednotlivých opatrení proti trvalým zadným vrátkam. Stojí niekoľko riadkov konfigurácie a pri čisto postavených aplikáciách nič nepokazí. Rozhodujúce sú tri veci: úplná inventúra namiesto len zjavného priečinka s uploadmi, správne poradie v Nginx resp. správna úroveň v Apache a skutočný test neškodným súborom.
Doplnené o oddelených vlastníkov pre programový kód, security.limit_extensions v poole a pravidelné hľadanie nových súborov PHP vznikne stav, v ktorom je uložený súbor síce nepríjemný, ale takmer nepoužiteľný. To nenahrádza ani aktualizáciu, ani hľadanie stôp, útočníkom však berie jeden z ich najdôležitejších nástrojov.
Ako konkrétne pomáha PHP SOS?
- Inventúra: zistíme všetky zapisovateľné priečinky pre každý web a skontrolujeme ich na existujúce súbory PHP.
- Nastaviť blokovanie: zákazy vykonávania zapíšeme do Nginx, Apache a PHP-FPM, v správnom poradí a bez závislosti od
.htaccess. - Testovať: každé blokovanie preveríme neškodným súborom a výsledok zdokumentujeme.
- Vyčistiť: pri nálezoch preberáme zabezpečenie stôp a odstránenie malvéru.
Časté otázky
Stačí na zákaz PHP súbor .htaccess v priečinku s uploadmi?
Nie spoľahlivo. Kto môže zapisovať do priečinka, môže zmeniť alebo nahradiť aj .htaccess. Blokovanie patrí do konfigurácie servera alebo do VirtualHost a pre webový koreň by mal platiť AllowOverride None.
Ktoré priečinky musím zablokovať?
Všetky priečinky, do ktorých smie zapisovať používateľ PHP a ktoré sú dostupné cez webový server. Okrem priečinkov s uploadmi sú to často cache, temp, import, export a záložné adresáre. Zistíte ich hľadaním pod používateľom behu.
Pokazí blokovanie môj web?
Spravidla nie, pretože v priečinkoch s uploadmi a cache u čisto postavených aplikácií neležia skripty, ktoré sa otvárajú priamo. Jednotlivé rozšírenia tam však predsa len ukladajú súbory PHP. Po prechode preto otestujte najdôležitejšie funkcie.
Chráni blokovanie pred PHP2Shell?
Nie. PHP2Shell je zraniteľnosť v interpreteri PHP, ktorá sa uzavrie len aktualizáciou a reštartom všetkých workerov. Blokovanie však bráni tomu, aby sa uložený súbor neskôr otvoril cez prehliadač a využil ako trvalé zadné vrátko.