Lyhyesti: Kieltääksenne PHP:n suorituksen uploadeissa selvitätte ensin kaikki kansiot, joihin PHP saa kirjoittaa, ja estätte sitten jokaisessa niistä skriptien suorituksen palvelinasetuksissa, ette .htaccess-tiedostolla. Nginxissä eston on tehottava ennen yleistä PHP-lohkoa, Apachessa se kuuluu VirtualHostiin asetuksella AllowOverride None. security.limit_extensions = .php FPM-poolissa ja testi harmittomalla tiedostolla viimeistelevät työn.
Miksi juuri nyt upload-kansiot ratkaisevat
Kriittisen aukon kuten PHP2Shellin jälkeen hyökkääjät eivät harvoin halua suorittaa koodia vain kerran. He haluavat palata, vaikka palvelin päivitettäisiin myöhemmin. Helpoin tie siihen on web shell: pieni PHP-tiedosto, tallennettuna kirjoitettavaan kansioon ja kutsuttuna myöhemmin selaimen kautta.
Päivitys ei poista tällaista tiedostoa. Joka oli päivittämättömänä verkossa 20. lokakuuta 2026 alkaen, ei siksi saisi vain päivittää vaan myös tarkistaa, onko missään uusia PHP-tiedostoja, ja jatkossa estää niiden suorittaminen. Miten löydöt tulkitaan, kuvaa PHP-tiedostot upload-kansiossa: löytöjen oikea tulkinta.
Suorituksen esto kohdistuu toiseen ehtoon. Se ei estä tiedoston tallentamista, mutta estää palvelinta käsittelemästä sitä ohjelmana.
Ensin inventaario: missä PHP saa kirjoittaa?
Useimmat ohjeet mainitsevat vain upload-kansion. Käytännössä PHP-sovellus kirjoittaa paljon useampaan paikkaan. Jokainen niistä, joka on saavutettavissa verkkopalvelimen kautta, tarvitsee eston.
| Kansiotyyppi | Tyypillinen sisältö | Miksi kirjoitettava |
|---|---|---|
| Uploadit, media | kuvat, PDF:t, liitteet | käyttäjät ja toimitus lataavat tiedostoja |
| Välimuisti | luodut sivut, esikatselukuvat | sovellus nopeuttaa tarjoilua |
| Temp, tuonti, vienti | CSV-tiedostot, välitilat | rajapinnat ja tiedonsiirto |
| Varmuuskopiot verkkojuuressa | .zip, .sql |
laajennukset varmuuskopioivat ”paikan päällä” |
| Lokit verkkojuuressa | virhe- ja debug-lokit | väärin määritetyt sovellukset |
Mitkä kansiot ne ovat palvelimellanne, näyttää haku ajoympäristön käyttäjän oikeuksilla. Se ei muuta mitään:
# Kaikki hakemiston /var/www alla olevat kansiot, joihin PHP-käyttäjä saa kirjoittaa
# (mukauta käyttäjä: www-data, nginx, apache tai oma pool-käyttäjä)
sudo -u www-data find /var/www -type d -writable 2>/dev/null | sort
# Onko näissä kansioissa jo PHP-tiedostoja?
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
Jos ensimmäinen haku palauttaa koko verkkojuuren, ohjelmakoodi kuuluu ajoympäristön käyttäjälle. Se kannattaa muuttaa etukäteen, kuten opas Tiedosto-oikeudet verkkopalvelimella kuvaa. Muuten ei ole kansiota, jota ei pitäisi estää.
PHP:n suorituksen kielto uploadeissa: Nginx
Nginxissä järjestys ratkaisee. Nginxin dokumentaation mukaan säännölliset lausekkeet tarkistetaan asetustiedoston järjestyksessä, ja ensimmäinen osuma voittaa. Jos yleinen lohko location ~ \.php$ on ennen estoanne, tiedosto suoritetaan. Yksinkertainen etuliite-location ilman ^~ ei samasta syystä suojaa.
Turvallinen on säännöllinen lauseke kaikille estetyille kansioille, joka on ennen PHP-lohkoa. Se kattaa myös harvoin käytetyt päätteet:
server {
# ... peruskonfiguraatio ...
# 1. Esto kirjoitettaville kansioille, TÄYTYY olla ennen PHP-lohkoa
location ~* ^/(uploads|media|cache|tmp|export)/.*\.(php\d?|phtml|phar|pht|phps)$ {
deny all;
}
# 2. Yleinen PHP-lohko: välitä vain olemassa olevat tiedostot
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;
}
}
Mukauttakaa kansionimet inventaarioonne. Sovelluksissa, joissa on yksi ainoa sisääntulopiste, sallittujen lista on vielä vahvempi tie; mallin näyttää Nginxin turvallinen asetus PHP:lle.
Apache ja PHP-FPM: esto oikeassa kohdassa
Apachessa esto kuuluu palvelinasetuksiin tai VirtualHostiin. Upload-kansion .htaccess ei sovellu, koska kuka tahansa, joka saa kirjoittaa sinne, voi muuttaa sitä. Koko verkkojuurelle on siksi voimassa AllowOverride None. Apachen dokumentaation mukaan AllowOverride on sallittu vain <Directory>-lohkoissa ilman säännöllisiä lausekkeita, joten asetatte sen verkkojuurelle ja eston <DirectoryMatch>-lohkolla sen alle:
<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>
Jos mod_php pyörii vielä, lisäätte samaan lohkoon php_admin_flag engine off. PHP-FPM:n kanssa toinen este vaikuttaa poolissa: security.limit_extensions määrää, mitkä päätteet FPM ylipäätään suorittaa. PHP-käsikirjan mukaan oletus on .php .phar; suositus on rajata arvoon .php.
; poolissa, esim. /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
Testaus harmittomalla tiedostolla
Toimiiko esto, näyttää vain testi. Asettakaa jokaiseen estettyyn kansioon hetkeksi tiedosto, joka vain tulostaa tekstin, kutsukaa sitä verkkotunnuksen kautta ja poistakaa se sen jälkeen.
- Tarkistakaa asetukset:
nginx -ttaiapachectl configtest, ladatkaa sitten uudelleen. - Luokaa testitiedosto, esimerkiksi
uploads/sperrtest.phpsisällöllä<?php echo 'ausgefuehrt';. - Kutsukaa komennolla
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/uploads/sperrtest.php. Odotettu tulos on403. - Jos näkyy sen sijaan
200ja teksti ”ausgefuehrt”, esto ei toimi. Tarkistakaa asetukset ja järjestys. - Poistakaa testitiedosto ja toistakaa testi jokaiselle kansiolle ja jokaiselle verkkosivustolle.
Jos löydätte inventaarion yhteydessä jo tuntemattomia PHP-tiedostoja kirjoitettavista kansioista, älkää poistako mitään hätiköiden. Varmistakaa ensin tila ja lokit, sillä nämä tiedostot ovat todistusaineistoa. Miten toimitte sen jälkeen, kuvaa Web shellien tunnistaminen ja poisto.
Miten upload-toiminnot rakennetaan koodissa turvallisesti, tyyppitarkistuksella ja tallennuksella verkkojuuren ulkopuolelle, kerrotaan oppaassa Tiedostolatausten turvallinen toteutus PHP:ssä.
Yhteenveto: kirjoittaa saa, suorittaa ei
Suorituksen esto kirjoitettavissa kansioissa on yksi tehokkaimmista yksittäisistä toimenpiteistä pysyviä takaovia vastaan. Se maksaa muutaman rivin asetuksia eikä riko mitään siististi rakennetuissa sovelluksissa. Ratkaisevia ovat kolme asiaa: täydellinen inventaario ilmeisen upload-kansion sijaan, oikea järjestys Nginxissä tai oikea taso Apachessa ja todellinen testi harmittomalla tiedostolla.
Täydennettynä erillisillä omistajilla ohjelmakoodille, security.limit_extensions-asetuksella poolissa ja uusien PHP-tiedostojen säännöllisellä haulla syntyy tila, jossa tallennettu tiedosto on harmillinen mutta tuskin enää käyttökelpoinen. Se ei korvaa päivitystä eikä jälkien etsintää, mutta vie hyökkääjiltä yhden heidän tärkeimmistä työkaluistaan.
Miten PHP SOS auttaa konkreettisesti?
- Inventaario: Selvitämme kaikki kirjoitettavat kansiot sivustoa kohden ja tarkistamme ne olemassa olevien PHP-tiedostojen varalta.
- Estojen asettaminen: Kirjaamme suorituksen estot Nginxiin, Apacheen ja PHP-FPM:ään oikeassa järjestyksessä ja ilman
.htaccess-riippuvuutta. - Testaus: Tarkistamme jokaisen eston harmittomalla tiedostolla ja dokumentoimme tuloksen.
- Siivous: Löytöjen kohdalla hoidamme jälkien varmistuksen ja haittaohjelmien poiston.
Usein kysytyt kysymykset
Riittääkö upload-kansion .htaccess PHP:n kieltämiseen?
Ei luotettavasti. Joka voi kirjoittaa kansioon, voi myös muuttaa tai korvata .htaccess-tiedoston. Esto kuuluu palvelinasetuksiin tai VirtualHostiin, ja verkkojuurelle pitäisi olla voimassa AllowOverride None.
Mitkä kansiot minun pitää estää?
Kaikki kansiot, joihin PHP-käyttäjä saa kirjoittaa ja jotka ovat saavutettavissa verkkopalvelimen kautta. Upload-kansioiden lisäksi niitä ovat usein välimuisti-, temp-, tuonti-, vienti- ja varmuuskopiohakemistot. Selvittäkää ne haulla ajoympäristön käyttäjänä.
Rikkooko esto verkkosivustoni?
Yleensä ei, sillä siististi rakennetuissa sovelluksissa upload- ja välimuistikansioissa ei ole skriptejä, joita kutsuttaisiin suoraan. Yksittäiset laajennukset kuitenkin tallentavat sinne PHP-tiedostoja. Testatkaa siksi tärkeimmät toiminnot muutoksen jälkeen.
Suojaako esto PHP2Shelliltä?
Ei. PHP2Shell on aukko PHP-tulkissa, joka suljetaan vain päivityksellä ja kaikkien workerien uudelleenkäynnistyksellä. Esto estää kuitenkin sen, että tallennettua tiedostoa kutsutaan myöhemmin selaimen kautta ja käytetään pysyvänä takaovena.