Trenutno stanje: PHP2Shell. Dve kritični ranljivosti PHP (CVSS 9,2) omogočata izvedbo škodljive kode brez prijave. Popravki od 21. 10. 2026.Kaj je zdaj treba storiti →

Prepoved izvajanja PHP v mapah za nalaganje

Webshell potrebuje dve stvari: mapo, v katero je mogoče pisati, in strežnik, ki jo izvede. Tako ji vzamete drugo, in sicer v vsaki zapisljivi mapi, ne samo v uploads.

Stanje 5 min branjaUtrjevanje in konfiguracija

Na kratko: Za prepoved izvajanja PHP v nalaganjih najprej ugotovite vse mape, v katere sme PHP pisati, nato v vsaki od njih zaprite izvajanje skriptov v konfiguraciji strežnika, ne prek .htaccess. V Nginx mora zapora delovati pred splošnim blokom PHP, v Apache sodi v VirtualHost z AllowOverride None. security.limit_extensions = .php v poolu FPM in preizkus z neškodljivo datoteko delo zaključita.

Zakaj prav zdaj štejejo mape za nalaganje

Po kritični ranljivosti, kot je PHP2Shell, napadalci le redko želijo kodo izvesti samo enkrat. Želijo se vrniti, tudi ko je strežnik pozneje popravljen. Najpreprostejša pot za to je webshell: majhna datoteka PHP, odložena v zapisljivi mapi in pozneje poklicana prek brskalnika.

Popravek take datoteke ne odstrani. Kdor je bil od 20. oktobra 2026 brez popravka na spletu, naj zato ne samo posodobi, ampak tudi preveri, ali kje ležijo nove datoteke PHP, in v prihodnje prepreči njihovo izvajanje. Kako razlagate najdbe, opisuje Datoteke PHP v mapi za nalaganje: pravilna razlaga najdb.

Zapora izvajanja se loti drugega pogoja. Ne prepreči, da bi bila datoteka odložena, prepreči pa, da bi jo strežnik obravnaval kot program.

Najprej popis: kje sme PHP pisati?

Večina navodil navaja samo mapo za nalaganje. V praksi aplikacija PHP piše na veliko več mest. Vsako od njih, ki je dosegljivo prek spletnega strežnika, potrebuje zaporo.

Vrsta mape Tipična vsebina Zakaj zapisljiva
Nalaganja, mediji slike, PDF-ji, priponke uporabniki in uredništvo nalagajo datoteke
Predpomnilnik ustvarjene strani, sličice aplikacija pospešuje dostavo
Začasne datoteke, uvoz, izvoz datoteke CSV, vmesna stanja vmesniki in izmenjava podatkov
Varnostne kopije v spletnem korenu .zip, .sql razširitve varnostno kopirajo »na kraju samem«
Dnevniki v spletnem korenu dnevniki napak in odpravljanja napak napačno konfigurirane aplikacije

Katere mape so to na vašem strežniku, pokaže iskanje s pravicami izvajalnega uporabnika. Ničesar ne spremeni:

# Vse mape pod /var/www, v katere sme uporabnik PHP pisati
# (prilagodite uporabnika: www-data, nginx, apache ali lasten uporabnik poola)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Ali v teh mapah že ležijo datoteke 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

Če prvo iskanje vrne celoten spletni koren, programska koda pripada izvajalnemu uporabniku. To pred tem spremenite, kot opisuje vodnik Pravice do datotek na spletnem strežniku. Sicer ni mape, ki je ne bi bilo treba zapreti.

Prepoved izvajanja PHP v nalaganjih: Nginx

Pri Nginx odloča vrstni red. Po dokumentaciji Nginx se regularni izrazi preverjajo v vrstnem redu konfiguracijske datoteke in prvi zadetek zmaga. Če splošni blok location ~ \.php$ stoji pred vašo zaporo, se datoteka izvede. Preprosta predponska lokacija brez ^~ iz istega razloga ne ščiti.

Varen je regularni izraz za vse zaprte mape, ki stoji pred blokom PHP. Pokrije tudi redko uporabljane končnice:

server {
    # ... osnovna konfiguracija ...

    # 1. Zapora za zapisljive mape, MORA stati pred blokom PHP
    location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
        deny all;
    }

    # 2. Splošni blok PHP: predaj samo obstoječ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;
    }
}

Imena map prilagodite svojemu popisu. Pri aplikacijah z eno samo vstopno točko je pot prek seznama dovoljenih še močnejša; vzorec prikazuje Varna konfiguracija Nginx za PHP.

Apache in PHP-FPM: zapora na pravem mestu

V Apache zapora sodi v konfiguracijo strežnika ali VirtualHost. .htaccess v mapi za nalaganje je neprimeren, ker ga lahko spremeni vsak, ki tam sme pisati. Za celoten spletni koren zato velja AllowOverride None. Po dokumentaciji Apache je AllowOverride dovoljen samo v blokih <Directory> brez regularnih izrazov, zato ga nastavite na spletnem korenu, zaporo pa prek <DirectoryMatch> pod njim:

<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>

Če še teče mod_php, v istem bloku dodajte php_admin_flag engine off. Pri PHP-FPM druga pregrada deluje v poolu: security.limit_extensions določa, katere končnice FPM sploh izvede. Po priročniku PHP je privzeto .php .phar; priporočena je omejitev na .php.

; v poolu, npr. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php

Preizkus z neškodljivo datoteko

Ali zapora deluje, pokaže samo preizkus. V vsako zaprto mapo za kratek čas položite datoteko, ki izpiše le besedilo, jo pokličite prek domene in jo nato izbrišite.

  1. Preverite konfiguracijo: nginx -t oziroma apachectl configtest, nato znova naložite.
  2. Ustvarite preizkusno datoteko, na primer uploads/sperrtest.php z vsebino <?php echo 'ausgefuehrt';.
  3. Pokličite jo z curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Pričakovan je 403.
  4. Če se namesto tega pojavi 200 in besedilo »ausgefuehrt«, zapora ne deluje. Preverite konfiguracijo in vrstni red.
  5. Preizkusno datoteko izbrišite in preizkus ponovite za vsako mapo in vsako spletno stran.
Pomembno

Če pri popisu že najdete neznane datoteke PHP v zapisljivih mapah, ničesar ne brišite prenagljeno. Najprej zavarujte stanje in dnevnike, ker so te datoteke dokazno gradivo. Kako nato postopate, opisuje Prepoznavanje in odstranjevanje webshellov.

Kako se funkcije nalaganja v kodi varno zgradijo, s preverjanjem tipa in hrambo zunaj spletnega korena, piše v vodniku Varna izvedba nalaganja datotek v PHP.

Sklep: pisanje da, izvajanje ne

Zapora izvajanja v zapisljivih mapah je eden najučinkovitejših posameznih ukrepov proti trajnim stranskim vratom. Stane nekaj vrstic konfiguracije in pri čisto grajenih aplikacijah ničesar ne pokvari. Odločilne so tri stvari: popoln popis namesto samo očitne mape za nalaganje, pravilen vrstni red v Nginx oziroma prava raven v Apache in pravi preizkus z neškodljivo datoteko.

Z ločenimi lastniki za programsko kodo, security.limit_extensions v poolu in rednim iskanjem novih datotek PHP nastane stanje, v katerem je odložena datoteka sicer nadležna, a komaj še uporabna. To ne nadomešča posodobitve ne iskanja sledi, napadalcem pa vzame eno njihovih najpomembnejših orodij.

Kako PHP SOS pomaga konkretno?

  • Popis: ugotovimo vse zapisljive mape za vsako spletno stran in jih preverimo za obstoječe datoteke PHP.
  • Nastavitev zapor: zapore izvajanja vnesemo v Nginx, Apache in PHP-FPM, v pravem vrstnem redu in brez odvisnosti od .htaccess.
  • Preizkus: vsako zaporo preverimo z neškodljivo datoteko in rezultat dokumentiramo.
  • Čiščenje: pri najdbah prevzamemo zavarovanje sledi in odstranjevanje zlonamerne kode.

Pogosta vprašanja

Ali za prepoved PHP zadošča .htaccess v mapi za nalaganje?

Ne zanesljivo. Kdor lahko piše v mapo, lahko spremeni ali zamenja tudi .htaccess. Zapora sodi v konfiguracijo strežnika ali VirtualHost, za spletni koren pa naj velja AllowOverride None.

Katere mape moram zapreti?

Vse mape, v katere sme pisati uporabnik PHP in so dosegljive prek spletnega strežnika. Poleg map za nalaganje so to pogosto imeniki za predpomnilnik, začasne datoteke, uvoz, izvoz in varnostne kopije. Ugotovite jih z iskanjem kot izvajalni uporabnik.

Ali zapora pokvari mojo spletno stran?

Praviloma ne, ker v mapah za nalaganje in predpomnilnik pri čistih aplikacijah ni skriptov, ki bi se klicali neposredno. Posamezne razširitve tam vendarle odlagajo datoteke PHP. Zato po prehodu preizkusite najpomembnejše funkcije.

Ali zapora ščiti pred PHP2Shell?

Ne. PHP2Shell je ranljivost v interpreterju PHP, ki se zapre samo s posodobitvijo in ponovnim zagonom vseh delavcev. Zapora pa prepreči, da bi se odložena datoteka pozneje poklicala prek brskalnika in uporabila kot trajna stranska vrata.

Viri

Takojšnji stik

Vsaka ura šteje. Pišite nam zdaj.

Na kratko opišite sistem, različico PHP in opažanje. Odzovemo se, razjasnimo stanje in delamo na daljavo, dokler incident ni zaključen in dokumentiran.

Takojšnja pomoč