Ukratko: Da biste zabranili izvršavanje PHP-a u prijenosima, najprije utvrdite sve mape u koje PHP smije pisati, a zatim u svakoj od njih blokirajte izvršavanje skripti u konfiguraciji poslužitelja, a ne putem .htaccess. U Nginxu blokada mora djelovati prije općeg PHP bloka, u Apacheu pripada u VirtualHost s AllowOverride None. security.limit_extensions = .php u FPM poolu i test bezazlenom datotekom zaokružuju posao.
Zašto upravo sada mape za prijenose računaju
Nakon kritične ranjivosti poput PHP2Shella napadači rijetko žele izvršiti kod samo jednom. Žele se vratiti, čak i kad se poslužitelj kasnije zakrpa. Najjednostavniji put za to je web shell: mala PHP datoteka odložena u zapisivu mapu i kasnije pozvana preko preglednika.
Zakrpa takvu datoteku ne uklanja. Tko je od 20. listopada 2026. bio na mreži nezakrpan, trebao bi stoga ne samo ažurirati nego i provjeriti leži li negdje nova PHP datoteka te ubuduće spriječiti njezino izvršavanje. Kako tumačiti nalaze, opisuje članak PHP datoteke u mapi za prijenose: ispravno tumačiti nalaze.
Blokada izvršavanja djeluje na drugom uvjetu. Ne sprječava odlaganje datoteke, ali sprječava da je poslužitelj tretira kao program.
Najprije inventura: gdje PHP smije pisati?
Većina uputa spominje samo mapu za prijenose. U praksi PHP aplikacija piše na mnogo više mjesta. Svako od njih koje je dostupno preko web-poslužitelja treba blokadu.
| Vrsta mape | Tipičan sadržaj | Zašto je zapisiva |
|---|---|---|
| Prijenosi, mediji | slike, PDF-ovi, privici | korisnici i redakcija učitavaju datoteke |
| Predmemorija | generirane stranice, sličice | aplikacija ubrzava isporuku |
| Privremene, uvoz, izvoz | CSV datoteke, međustanja | sučelja i razmjena podataka |
| Sigurnosne kopije u web-korijenu | .zip, .sql |
proširenja spremaju „na licu mjesta“ |
| Zapisnici u web-korijenu | zapisnici pogrešaka i debugiranja | pogrešno konfigurirane aplikacije |
Koje su to mape na Vašem poslužitelju, pokazuje pretraga s pravima korisnika pod kojim aplikacija radi. Ništa ne mijenja:
# Sve mape pod /var/www u koje PHP korisnik smije pisati
# (prilagoditi korisnika: www-data, nginx, apache ili vlastiti korisnik poola)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Leže li u tim mapama već PHP datoteke?
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
Ako prva pretraga vrati cijeli web-korijen, programski kod pripada korisniku pod kojim aplikacija radi. To biste trebali prethodno promijeniti, kako opisuje vodič Prava datoteka na web-poslužitelju. Inače ne postoji mapa koju ne bi trebalo blokirati.
Zabraniti izvršavanje PHP-a u prijenosima: Nginx
Kod Nginxa odlučuje redoslijed. Prema dokumentaciji Nginxa regularni izrazi provjeravaju se redoslijedom iz konfiguracijske datoteke i prvi pogodak pobjeđuje. Ako opći blok location ~ \.php$ stoji prije Vaše blokade, datoteka se izvršava. Jednostavna prefiksna lokacija bez ^~ iz istog razloga ne štiti.
Sigurno je regularni izraz za sve blokirane mape koji stoji ispred PHP bloka. Pokriva i rijetko korištene ekstenzije:
server {
# ... osnovna konfiguracija ...
# 1. Blokada za zapisive mape, MORA stajati prije PHP bloka
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Opći PHP blok: predavati samo postojeće datoteke
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;
}
}
Nazive mapa prilagodite svojoj inventuri. Kod aplikacija s jednom jedinom ulaznom točkom put preko popisa dopuštenih još je jači; obrazac pokazuje članak Sigurno konfigurirati Nginx za PHP.
Apache i PHP-FPM: blokada na pravom mjestu
U Apacheu blokada pripada u konfiguraciju poslužitelja ili VirtualHost. .htaccess u mapi za prijenose je neprikladan jer ga može promijeniti svatko tko tamo smije pisati. Za cijeli web-korijen stoga vrijedi AllowOverride None. Prema dokumentaciji Apachea AllowOverride je dopušten samo u blokovima <Directory> bez regularnih izraza, pa ga postavite na web-korijen, a blokadu pomoću <DirectoryMatch> ispod njega:
<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>
Ako još radi mod_php, u istom bloku dodajte php_admin_flag engine off. Kod PHP-FPM-a druga prepreka djeluje u poolu: security.limit_extensions određuje koje ekstenzije FPM uopće izvršava. Prema PHP priručniku zadano je .php .phar; preporučuje se ograničenje na .php.
; u poolu, npr. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Testirati bezazlenom datotekom
Djeluje li blokada, pokazuje samo test. U svaku blokiranu mapu nakratko odložite datoteku koja samo ispisuje tekst, pozovite je preko domene i zatim je izbrišite.
- Provjeriti konfiguraciju:
nginx -todnosnoapachectl configtest, zatim ponovno učitati. - Izraditi testnu datoteku, primjerice
uploads/sperrtest.phpsa sadržajem<?php echo 'ausgefuehrt';. - Pozvati je naredbom
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Očekuje se403. - Ako se umjesto toga pojavi
200i tekst „ausgefuehrt“, blokada ne djeluje. Provjeriti konfiguraciju i redoslijed. - Izbrisati testnu datoteku i test ponoviti za svaku mapu i svaku web-stranicu.
Ako pri inventuri već pronađete nepoznate PHP datoteke u zapisivim mapama, ne brišite ništa prenagljeno. Najprije osigurajte stanje i zapisnike, jer su te datoteke dokazni predmeti. Kako zatim postupiti, opisuje članak Prepoznati i ukloniti web shellove.
Kako se funkcije prijenosa u kodu grade sigurno, uz provjeru tipa i pohranu izvan web-korijena, piše u vodiču Sigurno implementirati prijenose datoteka u PHP-u.
Zaključak: pisati da, izvršavati ne
Blokada izvršavanja u zapisivim mapama jedna je od najdjelotvornijih pojedinačnih mjera protiv trajnih stražnjih vrata. Košta nekoliko redaka konfiguracije i kod uredno izgrađenih aplikacija ništa ne kvari. Odlučujuće su tri stvari: potpuna inventura umjesto samo očite mape za prijenose, ispravan redoslijed u Nginxu odnosno ispravna razina u Apacheu i pravi test bezazlenom datotekom.
Dopunjeno odvojenim vlasnicima programskog koda, security.limit_extensions u poolu i redovitom potragom za novim PHP datotekama, nastaje stanje u kojem je odložena datoteka doduše neugodna, ali jedva upotrebljiva. To ne zamjenjuje ni ažuriranje ni potragu za tragovima, ali napadačima oduzima jedan od njihovih najvažnijih alata.
Kako PHP SOS konkretno pomaže?
- Inventura: utvrđujemo sve zapisive mape po web-stranici i provjeravamo postoje li u njima PHP datoteke.
- Postaviti blokade: upisujemo blokade izvršavanja u Nginx, Apache i PHP-FPM, pravilnim redoslijedom i bez ovisnosti o
.htaccess. - Testirati: svaku blokadu provjeravamo bezazlenom datotekom i dokumentiramo rezultat.
- Očistiti: kod nalaza preuzimamo osiguranje tragova i uklanjanje zlonamjernog softvera.
Česta pitanja
Je li .htaccess u mapi za prijenose dovoljna da se zabrani PHP?
Nije pouzdano. Tko može pisati u mapu, može promijeniti ili zamijeniti i .htaccess. Blokada pripada u konfiguraciju poslužitelja ili VirtualHost, a za web-korijen treba vrijediti AllowOverride None.
Koje mape moram blokirati?
Sve mape u koje PHP korisnik smije pisati i koje su dostupne preko web-poslužitelja. Osim mapa za prijenose to su često direktoriji za predmemoriju, privremene datoteke, uvoz, izvoz i sigurnosne kopije. Pronađite ih pretragom kao korisnik pod kojim aplikacija radi.
Hoće li blokada pokvariti moju web-stranicu?
U pravilu neće, jer se u mapama za prijenose i predmemoriju kod čistih aplikacija ne nalaze skripte koje se izravno pozivaju. Pojedina proširenja ipak tamo odlažu PHP datoteke. Zato nakon prelaska testirajte najvažnije funkcije.
Štiti li blokada od PHP2Shella?
Ne. PHP2Shell je ranjivost u PHP interpreteru koja se zatvara samo ažuriranjem i ponovnim pokretanjem svih workera. Blokada ipak sprječava da se odložena datoteka kasnije pozove preko preglednika i iskoristi kao trajna stražnja vrata.