# Fájlfeltöltések biztonságos megvalósítása PHP-ban: PHP-feltöltés biztonsága

> PHP-feltöltés biztonsága a gyakorlatban: fájltípus szerveroldali ellenőrzése, átnevezés, tárolás a webgyökéren kívül, a PHP-végrehajtás tiltása.

Forrás: https://phpsos.de/hu/ratgeber/datei-upload-sicher/  
Állapot: 2026. 10. 25.  
Szolgáltató: PHP SOS, PHP-vészhelyzeti segítség és szerverbiztonság. Azonnali segítség WhatsAppon: https://wa.me/491736494914?text=%C3%9Cdv%C3%B6zl%C3%B6m%2C%20PHP%20SOS%21%20Seg%C3%ADts%C3%A9gre%20van%20sz%C3%BCks%C3%A9g%C3%BCnk%20a%20PHP-szerver%C3%BCnkkel.%20C%C3%A9g%3A%20%E2%80%A6%20Weboldal%3A%20%E2%80%A6

**Röviden:** A PHP-feltöltés biztonságánál nem egyetlen ellenőrzés dönt, hanem a kombináció: a fájltípus szerveroldali ellenőrzése, a fájlok átnevezése, tárolásuk a webgyökéren kívül, és a szkriptek végrehajtásának tiltása a feltöltési mappában. Egy ellenőrizetlen feltöltési űrlap az egyik klasszikus út, amelyen a támadók hátsó ajtót juttatnak egy webszerverre.

## Miért kedvelt belépési pont a feltöltési űrlap

Minden fájlokat fogadó űrlap idegen adatokat ír a szerverére. Ide tartoznak a jelentkezési űrlapok, az ügyfélportálok, a képgalériák, a támogatási területek és a CMS-ek és webshopok sok bővítménye. Ha egy támadónak sikerül ott olyan fájlt elhelyeznie, amelyet a webszerver ezután PHP-ként hajt végre, tartós hátsó ajtója van.

A vezetőség számára ez azt jelenti: egy ártalmatlannak tűnő önéletrajz-feltöltés a legrosszabb esetben a teljes webszerver átvételéhez vezethet. Emellett a feltöltési mappákban gyakran személyes adatok vannak, amelyek hibás konfiguráció esetén nyilvánosan lekérhetők.

Az adminok és fejlesztők számára ez azt jelenti: az alkalmazáskódnak és a szerverkonfigurációnak egymáshoz kell illeniük. Az egyik szint gyengeségét gyakran a másik fogja fel, ha mindkettő szabályosan van megvalósítva. Hogyan találhatja meg a már bejuttatott fájlokat, azt a [Webshellek felismerése és eltávolítása](https://phpsos.de/hu/ratgeber/webshell-erkennen/) útmutató írja le.

## A PHP-feltöltés biztonságának alapszabályai

A következő szabályok megfelelnek az OWASP Cheat Sheetek ajánlásainak, és az üzemben bevált:

- **Engedélylista tiltólista helyett:** Csak kifejezetten engedélyezett fájltípusokat fogadjon el, például PDF-et, JPG-t és PNG-t. Az egyes kiterjesztések tiltólistái változatokkal és dupla kiterjesztésekkel megkerülhetők.
- **A tartalmat ellenőrizze, ne csak a kiterjesztést:** A tényleges típust szerveroldalon állapítsa meg a `finfo`-val. A `$_FILES`-ban lévő MIME-típus a feladó adata, és nem megbízható.
- **Új fájlnév:** Az eredeti nevet soha ne használja fájlnévként. Hozzon létre véletlenszerű nevet, és fűzze hozzá az engedélylistából származó kiterjesztést.
- **Tárolás a webgyökéren kívül:** A fájlokat úgy mentse, hogy URL-en keresztül közvetlenül ne legyenek elérhetők. A kiszolgálás jogosultság-ellenőrzéssel ellátott szkripten keresztül történik.
- **A méret korlátozása:** Az alkalmazásban, a PHP-ban és a webszerveren.
- **Nincs végrehajtás:** Ha a feltöltéseknek mégis a webgyökérben kell lenniük, kapcsolja ki a szkriptek végrehajtását ebben a könyvtárban.
- **Ellenőrzés csak a szerveren:** A böngészőben végzett JavaScript-ellenőrzések javítják a kezelhetőséget, de nem védenek.

## Egy biztonságos példa finfo-val és véletlenszerű névvel

A következő példa a biztonságos feldolgozás magját mutatja. Szándékosan rövid, és be kell ágyazni az alkalmazásába, vagyis bejelentkezéssel, jogosultság-ellenőrzéssel, CSRF-védelemmel és naplózással együtt.

```php
<?php
declare(strict_types=1);

const MAX_BYTES  = 5 * 1024 * 1024; // 5 MB
const ERLAUBT    = [
    'application/pdf' => 'pdf',
    'image/jpeg'      => 'jpg',
    'image/png'       => 'png',
];
const ZIELORDNER = '/var/www/daten/uploads'; // a webgyökéren kívül

$datei = $_FILES['dokument'] ?? null;

if (!is_array($datei) || $datei['error'] !== UPLOAD_ERR_OK) {
    http_response_code(400);
    exit('Upload fehlgeschlagen.');
}

if ($datei['size'] > MAX_BYTES || !is_uploaded_file($datei['tmp_name'])) {
    http_response_code(400);
    exit('Datei ungültig.');
}

$finfo = new finfo(FILEINFO_MIME_TYPE);
$typ   = $finfo->file($datei['tmp_name']);

if (!isset(ERLAUBT[$typ])) {
    http_response_code(415);
    exit('Dateityp nicht erlaubt.');
}

$name = bin2hex(random_bytes(16)) . '.' . ERLAUBT[$typ];
$ziel = ZIELORDNER . '/' . $name;

if (!move_uploaded_file($datei['tmp_name'], $ziel)) {
    http_response_code(500);
    exit('Speichern fehlgeschlagen.');
}

chmod($ziel, 0640);
// Az eredeti nevet csak szövegként tárolja az adatbázisban,
// és minden kiadásnál escape-elje a htmlspecialchars()-szal.
```

Képeknél érdemes egy további lépés: a képet GD-vel vagy Imagickkel újra kell kódolni, és közben a metaadatokat el kell dobni. Ez nem pótolja a többi ellenőrzést, de csökkenti a beágyazott idegen adatokból eredő maradék kockázatot.

Ismeretlen forrásból származó dokumentumoknál, például jelentkezéseknél vagy reklamációs fotóknál ezen felül célszerű egy vírusellenőrzés a továbbadás előtt. Ez kevésbé a webszervert védi, inkább a munkatársakat, akik a fájlokat később a munkaállomásukon megnyitják. Naplózzon emellett minden feltöltést idővel, fiókkal, fájlmérettel és felismert típussal, hogy a szokatlan minták később visszakövethetők legyenek.

A CMS-eknél és webshopoknál a beépített médiakönyvtárak többnyire saját ellenőrzéseket hoznak magukkal. Kockázatosabbak az űrlap-bővítmények, az importfunkciók és az önállóan programozott kiegészítő oldalak, amelyek a könyvtárat megkerülve mentik a fájlokat. Egy ellenőrzésnél éppen ezeket a helyeket nézze meg elsőként.

> **Tipp:**
> A fájlokat a védett mappából `Content-Disposition: attachment` és `X-Content-Type-Options: nosniff` fejléccel szolgálja ki. Ekkor a böngésző a problémás tartalmakat nem jeleníti meg közvetlenül, hanem letöltésként kínálja fel.

## A PHP-végrehajtás kikapcsolása a feltöltési mappában

Még ha egy hibás tartalmú fájl át is csúszik, a webszervernek nem szabad szkriptként végrehajtania. Ez a második védelmi réteg minden olyan szerveren kell, amely feltöltéseket a webgyökérben tárol.

Nginx PHP-FPM-mel:

```nginx
location ^~ /uploads/ {
    location ~* \.(php|phtml|phar)$ {
        deny all;
    }
}
```

Apache esetén, a legjobb közvetlenül a VirtualHostban, nem egy `.htaccess`-ben, hogy a szabályt az alkalmazás ne tudja felülírni:

```apache
<Directory "/var/www/html/uploads">
    AllowOverride None
    <FilesMatch "\.(php|phtml|phar)$">
        Require all denied
    </FilesMatch>
</Directory>
```

Ha a PHP Apache-modulként (mod_php) fut, ugyanabban a blokkban emellett beállíthatja a `php_admin_flag engine off` értéket. A módosítás után egy ártalmatlan teszt fájllal, amely csak egy szöveget ad ki, ellenőrizze, hogy a szerver 403-mal válaszol a rá irányuló kérésre.

## Méretkorlátok és a kapcsolat a PHP2Shellel

A feltöltések szorosan összefüggnek a `post_max_size` és az `upload_max_filesize` PHP-beállításokkal. A PHP2Shell kapcsán a php.net átmeneti intézkedésként azt ajánlja, hogy a `post_max_size` értékét állítsa 8M-ra, ha nincs szükség feltöltésekre, vagy 32M-ra feltöltésekkel, és az `upload_max_filesize` ennél kisebb maradjon. Ez nem teljes védelem, és nem pótolja a javított PHP-verzióra való frissítést.

```ini
; php.ini vagy FPM-pool (php_admin_value), utána indítsa újra az összes workert
file_uploads        = On
post_max_size       = 32M
upload_max_filesize = 20M
max_file_uploads    = 5
```

Ha egy weboldalnak egyáltalán nincs szüksége feltöltésekre, a `file_uploads = Off` a legtisztább megoldás. Hogy a javításig mely beállítások célszerűek, azt az [Azonnali intézkedések javítás nélkül](https://phpsos.de/hu/php2shell/sofortmassnahmen-ohne-patch/) oldalon találja. A feltöltési könyvtárak megfelelő jogait a [Fájljogosultságok a webszerveren](https://phpsos.de/hu/ratgeber/dateirechte-webserver/) írja le.

## Tipikus hibák a feltöltési funkciókban

A meglévő alkalmazások átnézésekor újra és újra ugyanazok a minták bukkannak fel. Ellenőrizze az űrlapjait célzottan ezekre a pontokra:

- A kiterjesztést csak részben ellenőrzik, így a több kiterjesztéssel rendelkező fájlnevek átcsúsznak.
- Az űrlapból származó eredeti név a tárolási útvonalba kerül. Ez utat nyit az útvonal-manipulációnak és a meglévő fájlok felülírásának.
- A feltöltések nyilvánosan, kiszámítható nevekkel vannak. Jelentkezéseknél vagy szerződéseknél ez adatvédelmi probléma is.
- A feltöltési mappa a webszerver számára írható és egyben futtatható.
- A régi feltöltési bővítményeket vagy űrlap-plugineket nem frissítik, noha a gyártó biztonsági frissítéseket adott ki.
- A hibákat nem naplózzák. Az elutasított feltöltések azonban korai jelzések a célzott kísérletekről.

## Hogyan segít konkrétan a PHP SOS?

- Ellenőrizzük a feltöltési funkcióit a kódban és a szerverkonfigurációban, és prioritással megnevezzük a konkrét gyengeségeket.
- A [szerver-keményítés](https://phpsos.de/hu/leistungen/server-haertung/) keretében beállítjuk a végrehajtási tiltást a feltöltési mappában, a megfelelő jogokat és a méretkorlátokat.
- Gyanú esetén átvizsgáljuk a feltöltési könyvtárakat bejuttatott szkriptek után, és megtisztítjuk őket a [kártevő-eltávolítással](https://phpsos.de/hu/leistungen/malware-entfernung/).
- Kívánságra a megvalósítást egy [penetrációs teszttel](https://phpsos.de/hu/leistungen/sicherheitsaudit-penetrationstest/) függetlenül ellenőriztetjük.


## Gyakori kérdések

**Elég a fájl kiterjesztését ellenőrizni feltöltéskor?**  
Nem. A kiterjesztés és a böngésző által jelentett MIME-típus a feladótól származik, és szabadon megválasztható. Ellenőrizze a tartalmat szerveroldalon, adjon új fájlnevet, és tiltsa le a szkriptek végrehajtását a feltöltési könyvtárban.

**Hol érdemes tárolni a feltöltött fájlokat?**  
A legjobb a nyilvános webkönyvtáron kívül. A kiszolgálást ekkor egy szkript végzi, amely előtte ellenőrzi, hogy a felhasználó láthatja-e a fájlt. Így a fájlok sem közvetlenül nem hívhatók meg, sem nem futtathatók.

**Ártalmatlanok az SVG-fájlok képként?**  
Nem automatikusan. Az SVG XML, és aktív tartalmat tartalmazhat. Csak akkor engedélyezze az SVG-t, ha megtisztítja a fájlokat, vagy kizárólag letöltésként, megfelelő Content-Disposition fejléccel szolgálja ki őket.

**Van köze a feltöltési méretnek a PHP2Shellhez?**  
Igen, közvetve. A php.net átmeneti intézkedésként alacsonyabb értékeket ajánl a post_max_size és az upload_max_filesize számára. Ez csökkenti a kockázatot, de nem pótolja a javított PHP-verzióra való frissítést és az összes worker újraindítását.

## Források

- [OWASP Cheat Sheet Series (File Upload)](https://cheatsheetseries.owasp.org/)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [php.net: biztonsági közlemények a PHP2Shellről](https://www.php.net/)
