Aktuális helyzet: PHP2Shell. Két kritikus PHP-rés (CVSS 9,2) lehetővé teszi kártékony kód futtatását bejelentkezés nélkül. Javítások 2026. 10. 21. óta.Mi a teendő most →

Local File Inclusion megelőzése PHP-ban: LFI és RFI

Ha az include vagy a require a kérésből veszi át az útvonalakat, a támadók idegen fájlokat tölthetnek be. Így építse fel biztonságosan az oldalválasztást és a sablonokat, és védje meg ezen felül a szervert.

Állapot 5 perc olvasási időÚtmutatók

Röviden: A Local File Inclusion PHP-ban akkor keletkezik, ha az include, a require vagy a fájlfüggvények olyan útvonalat használnak, amelyet a látogató befolyásolhat. A biztonságos megoldás egy rögzített engedélylista: a paraméter csak ismert értékek közül választ, maga az útvonal soha nem a kérésből származik. Szerveroldalon az allow_url_include=Off, az open_basedir és a szigorú fájljogosultságok egészítik ki a védelmet.

Mi az a Local File Inclusion PHP-ban?

Sok régebbi PHP-alkalmazás egy egyszerű minta szerint tölt be oldalakat: a címben lévő paraméter határozza meg, melyik fájlt építik be. Ha ezt a paramétert ellenőrzés nélkül adják át az include-nak, a támadó más fájlokat kérhet a szerverről. Ártalmatlanabb esetben hozzáférési adatokat tartalmazó konfigurációs fájlokat olvas. Súlyosabb esetben rávesz a PHP-t arra, hogy olyan tartalmakat hajtson végre, amelyeket előtte máshol helyezett el, például egy feltöltésben vagy egy naplófájlban.

A vezetőség számára fontos: ez a rés ritkán a CMS magjában van, hanem többnyire saját fejlesztésekben, régi bővítményekben vagy gyorsan épített kiegészítő oldalakban. A mindennapokban nem tűnik fel, mert a weboldal normálisan működik.

A Remote File Inclusion esetén a PHP idegen címről tölt be kódot. Ennek feltétele, hogy az allow_url_include be legyen kapcsolva. Az aktuális PHP-verziókban ez a beállítás alapértelmezetten ki van kapcsolva, régi vagy hibásan beállított szervereken azonban még megtalálható.

Tipikus sebezhető minták a kódban

Veszélyeztetettek azok a helyek, ahol a kérésből, a cookie-kból vagy az adatbázisból származó érték egy fájlútvonal részévé válik. Gyakori példák a nyelvváltók, amelyek egy paraméter szerint töltenek be nyelvi fájlt, a címben lévő paraméterrel történő oldalválasztás, a sablon- vagy témaválasztás és a dokumentumok letöltési szkriptjei. Az útvonal végére fűzött .php ezt nem védi megbízhatóan, mert a támadók kitérhetnek meglévő PHP-fájlokra.

Egy első áttekintést úgy kaphat, ha olyan beépítéseket keres, amelyek változókat tartalmaznak. Ez ártalmatlan találatokat is hoz, de megmutatja, hol kell alaposabban megnézni:

grep -rnE --include='*.php' '(include|require)(_once)?\s*\(?\s*\$' /var/www/projekt \
  | grep -v '/vendor/'

Minden találatot ellenőrizzen arra, honnan származik a változó, és befolyásolhatja-e egy látogató.

A biztonságos minta: engedélylista a kérésből származó útvonal helyett

A legmegbízhatóbb védelem az, hogy a látogató csak egy kulcsot választ, és az alkalmazás maga dönti el, melyik fájl tartozik hozzá. Az útvonalat soha nem állítják össze bemenetekből.

<?php
declare(strict_types=1);

$seiten = [
    'start'      => __DIR__ . '/../vorlagen/start.php',
    'leistungen' => __DIR__ . '/../vorlagen/leistungen.php',
    'kontakt'    => __DIR__ . '/../vorlagen/kontakt.php',
];

$wahl = is_string($_GET['seite'] ?? null) ? $_GET['seite'] : 'start';

if (!array_key_exists($wahl, $seiten)) {
    http_response_code(404);
    $wahl = 'start';
}

require $seiten[$wahl];

Ez a minta rövid, könnyen ellenőrizhető, és nem hagy mozgásteret. A modern keretrendszerekben az útválasztó (router) veszi át ezt a feladatot; ott a vezérlőket és a sablonokat sem szabad szabad paraméterekből meghatározni.

Ha a fájlneveknek dinamikusnak kell lenniük: realpath és alapkönyvtár

Néha egy rögzített lista nem praktikus, például egy dokumentummappából való letöltéseknél. Ekkor a feloldott útvonalat ellenőrizze egy rögzített alapkönyvtárral szemben, és csak egyszerű fájlneveket engedjen meg.

<?php
declare(strict_types=1);

const BASIS = '/var/www/daten/dokumente';

function sichererPfad(string $name): string
{
    if (!preg_match('/^[a-z0-9_-]{1,64}\.pdf$/', $name)) {
        throw new InvalidArgumentException('Ungültiger Dateiname.');
    }

    $basis = realpath(BASIS);
    $pfad  = realpath($basis . DIRECTORY_SEPARATOR . $name);

    if ($basis === false || $pfad === false
        || !str_starts_with($pfad, $basis . DIRECTORY_SEPARATOR)) {
        throw new RuntimeException('Datei nicht gefunden.');
    }

    return $pfad;
}

// Kiszolgálás beépítés helyett: a readfile() nem hajt végre kódot.
$datei = sichererPfad((string) ($_GET['datei'] ?? ''));
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($datei) . '"');
readfile($datei);

Két pont döntő. A reguláris kifejezés nem enged könyvtárelválasztókat és speciális karaktereket. A csak kiszolgálandó fájlokat pedig readfile()-lal olvassák, nem include-dal, hogy a bennük lévő kód soha ne kerüljön végrehajtásra. Az str_starts_with() a PHP 8.0-tól érhető el.

Szerveroldali védelem: php.ini, open_basedir és jogok

A biztonságos kód az első védvonal. A szerverkonfiguráció gondoskodik arról, hogy egy átnézett hiba kevesebb kárt okozzon.

; php.ini vagy FPM-pool (php_admin_value / php_admin_flag)
allow_url_include = Off
allow_url_fopen   = Off   ; csak ha az alkalmazás nem tölt be külső URL-eket
open_basedir      = /var/www/kunde-a/:/tmp/kunde-a/
display_errors    = Off
log_errors        = On

Az allow_url_fopen-re egyes alkalmazásoknak frissítésekhez vagy interfészekhez szükségük van. A kikapcsolást először egy tesztkörnyezetben próbálja ki. Az open_basedir a PHP-t a weboldal saját könyvtáraira korlátozza, ami különösen fontos több ügyfelet kiszolgáló szervereken. A részleteket az open_basedir és weboldalankénti elkülönítés és a A php.ini biztonságos beállítása útmutatók tartalmazzák.

Kiegészítésként a feltöltési és gyorsítótár-könyvtárak ne legyenek futtathatók, a naplófájlok pedig ne a webgyökérben legyenek. Így a támadónak hiányoznak azok a helyek, ahol saját tartalmat helyezhetne el egy beépítéshez.

Miről ismeri fel a kihasználási kísérleteket a naplókban

A File Inclusion kihasználására tett kísérletek többnyire nyomot hagynak az access-naplóban. Feltűnőek a könyvtárváltásokat, abszolút rendszerútvonalakat, stream wrappereket vagy teljes idegen címeket tartalmazó paraméterek, különösen az olyan paramétereknél, mint a page, a file, a template vagy a lang. Egyetlen találat többnyire automatizált szkennelés. Fontos, hogy egy ilyen kérésre 200-as státuszkóddal és szokatlan válaszmérettel válaszoltak-e.

Hogyan járjon el ennél módszeresen, azt a Webszerver-naplók kiértékelése egy támadás után írja le. Ha sikeres hozzáférések nyomára bukkan, feltételezze, hogy konfigurációs fájlokat olvastak, és újítsa meg a bennük lévő hozzáférési adatokat.

Ide tartoznak mindenekelőtt az adatbázis-jelszavak, a fizetési és szállítási szolgáltatók kulcsai, az SMTP-hozzáférések és a CMS titkos kulcsai. Ellenőrizze emellett, hogy az első gyanús hozzáférés óta keletkeztek-e új fájlok. Aki fájlokat tudott olvasni, az esetleg saját fájlokat is megpróbált elhelyezni. Ebben az esetben már nem csak a kódban lévő résről van szó, hanem egy biztonsági incidensről, amelyet strukturáltan kell kezelni.

A javítások tartós biztosítása

Egy javítás után érdemes a védelmi funkciót automatizált tesztekkel biztosítani. Egy egyszerű teszt ismeretlen értékeket, könyvtárváltásokat és üres bemeneteket ad át az oldalválasztásnak, és minden esetben az alapértelmezett oldalt vagy egy 404-es hibát vár. Az ilyen tesztek megakadályozzák, hogy egy későbbi módosítás észrevétlenül ismét megnyissa a rést.

A vezetőség és a projektfelelősök számára hasznos egy kérdés az ügynökséghez: vannak-e az alkalmazásban olyan helyek, ahol fájlokat paraméterek alapján töltenek be, és hogyan vannak védve? Egy konkrét válasz lelőhelyekkel és tesztekkel jó jel.

Hogyan segít konkrétan a PHP SOS?

  • Célzottan keresünk a kódjában include, require és olyan fájlfüggvények után, amelyek a kérésből származó bemeneteket használnak, és minden leletet értékelünk.
  • Weboldalanként beállítjuk az allow_url_include, az open_basedir értékét és a megfelelő jogokat, és ellenőrizzük, hogy az alkalmazás ezután is működik.
  • Kiértékeljük a naplókat kihasználási kísérletek szempontjából, és tisztázzuk, hogy meg kell-e újítani a hozzáférési adatokat.
  • Független ellenőrzéshez PHP-alkalmazásokra biztonsági auditot penetrációs teszttel kínálunk.

Gyakori kérdések

Mi a különbség az LFI és az RFI között?

A Local File Inclusionnél az alkalmazás olyan fájlt tölt be, amely már a szerveren van, de nem kellene betöltenie. A Remote File Inclusionnél idegen címről töltenek be kódot. Az RFI nem biztonságos PHP-beállítást feltételez, az LFI nem.

Elég a ../ eltávolítása a paraméterből?

Nem. Az ilyen szűrők gyakran megkerülhetők kódolással vagy változatokkal, és elkerülik a figyelmüket az abszolút útvonalak. Biztonságos csak az engedélyezett értékek rögzített hozzárendelése fájlokhoz, vagy a feloldott útvonal ellenőrzése egy alapkönyvtárral szemben.

Teljesen véd az open_basedir a file inclusion ellen?

Nem, csak azokat a könyvtárakat korlátozza, amelyekhez a PHP hozzáférhet. Ezeken a határokon belül a rés kihasználható marad. Az open_basedir további védelmi réteg, és nem pótol biztonságos kódot.

Érintettek az olyan CMS-ek, mint a WordPress az LFI-ben?

Az elterjedt CMS-ek magja ebből a szempontból jól ellenőrzöttnek számít. Rések inkább a bővítményekben, témákban és saját fejlesztésekben bukkannak fel. A bővítmények frissítései és biztonsági közleményeik áttekintése ezért fontos.

Források

Azonnali kapcsolat

Minden óra számít. Írjon nekünk most.

Ismertesse röviden a rendszert, a PHP-verziót és a megfigyelését. Jelentkezünk, tisztázzuk a helyzetet, és távolról dolgozunk, amíg az incidens le nem zárul és dokumentálva nem lesz.

Azonnali segítség