LFI (Local File Inclusion)
| Po angielsku | local file inclusion (LFI) |
|---|---|
| Którą formą pisać | bez tłumaczenia Skrót, nazwa własna albo nazwa standardu — nie tłumaczymy w ogóle. |
| Inne formy | dołączenie pliku lokalnego |
| Kategoria | Podatności i klasy błędów |
LFI (Local File Inclusion) to podatność, w której aplikacja dołącza plik już obecny na serwerze, a jego wybór zależy od danych kontrolowanych przez atakującego [1]. OWASP opisuje LFI jako dołączanie plików lokalnych przez podatne procedury dołączania, gdy dane użytkownika trafiają do instrukcji include bez odpowiedniego oczyszczenia [1]. W PHP błąd ten mieści się w kategorii CWE-98, która obejmuje niekontrolowane nazwy plików w include, require i podobnych instrukcjach [2]. Skutkiem bywa ujawnienie konfiguracji, a często wykonanie kodu.
Jak działa
Instrukcja include w PHP dołącza i przetwarza wskazany plik; jeżeli zawiera on kod PHP, kod zostaje wykonany [3]. Ścieżka zaczynająca się od /, . albo .. jest traktowana jako jawna i pomija ustawienie include_path [3]. Jeżeli nazwa pliku pochodzi z parametru żądania, atakujący może więc podać ścieżkę z sekwencją ../ i wyjść poza katalog przewidziany przez programistę. Ten element ataku to path traversal [1].
Schemat poniżej pokazuje, jak parametr adresu zamienia się w wykonanie pliku.
Różnicę między kodem podatnym i bezpiecznym widać na przykładzie. Pierwsza wersja skleja ścieżkę z parametru, druga wybiera plik z zamkniętej listy.
include __DIR__ . '/szablony/' . $_GET['widok'] . '.php'; // podatne
$widoki = array( 'lista' => 'lista.php', 'siatka' => 'siatka.php' );
$klucz = isset( $_GET['widok'] ) ? sanitize_key( $_GET['widok'] ) : 'lista';
include __DIR__ . '/szablony/' . ( $widoki[ $klucz ] ?? 'lista.php' );
LFI a RFI
MITRE rozróżnia dwa warianty tego samego błędu [2]. W RFI (Remote File Inclusion) atakujący wskazuje adres zdalny z własnym kodem. Gdy pobieranie zdalnych plików jest wyłączone, pozostaje LFI: atakujący używa ścieżek względnych, by dołączyć plik lokalny, na przykład log serwera, do którego wcześniej wpisał kod PHP [2].
| Cecha | LFI | RFI (Remote File Inclusion) |
|---|---|---|
| skąd pochodzi plik | z dysku serwera [1] | z adresu zdalnego [2] |
| warunek w PHP | brak listy dozwolonych plików [1] | włączone allow_url_include [3] |
| typowa droga do kodu | log lub wgrany plik [2] | plik atakującego [2] |
| ograniczenie | open_basedir [4] | allow_url_fopen wyłączone [2] |
Zagrożenia i skutki
OWASP wymienia jako skutki LFI wykonanie kodu na serwerze, wykonanie kodu JavaScript po stronie klienta prowadzące do XSS (Cross-Site Scripting), odmowę usługi oraz ujawnienie informacji wrażliwych [1]. MITRE podkreśla, że głównym skutkiem jest wykonanie nieautoryzowanego kodu, co narusza integralność, poufność i dostępność [2].
- Ujawnienie informacji wrażliwych: odczyt plików konfiguracyjnych, w tym takich, które zawierają dane dostępu do bazy.
- Zdalne wykonanie kodu: dołączenie pliku, w którym atakujący wcześniej umieścił kod PHP [2].
- Połączenie z wgraniem dowolnego pliku: nawet obrazek z kodem PHP zostanie wykonany, jeśli trafi do
include[3]. - Instalacja webshella jako trwałego dostępu po udanym wykonaniu kodu.
W WordPressie
LFI w ekosystemie WordPress dotyczy głównie wtyczek i motywów, które ładują szablony PHP według nazwy przekazanej w shortcodzie, parametrze adresu albo żądaniu AJAX. To typowa podatność we wtyczce.
Przykładem jest wtyczka WP Dark Mode: według WPScan nie oczyszczała parametru style w shortcodach, zanim użyła go do wczytania szablonu PHP [7]. Błąd CVE-2023-0467 wymagał konta co najmniej na poziomie subskrybenta i został poprawiony w wersji 4.0.8 [7]. Groźniejszy był błąd CVE-2025-2636 we wtyczce InstaWP Connect: parametr instawp-database-manager pozwalał dołączać i wykonywać pliki na serwerze bez logowania [6]. Dotyczył wersji do 0.1.0.85 włącznie, poprawkę zawiera wersja 0.1.0.86, a WPScan opublikował go 10 kwietnia 2025 roku [6]. To przykład podatności wykorzystywanej bez uwierzytelnienia.
Rdzeń WordPressa udostępnia funkcję validate_file(), która sprawdza nazwę i ścieżkę pliku [5]. Zwraca 0, gdy wszystko jest w porządku, 1 przy sekwencji przejścia do katalogu nadrzędnego, 2 przy ścieżce z literą dysku Windows i 3, gdy pliku nie ma na przekazanej liście dozwolonych [5].
Jak się bronić
OWASP wskazuje jako najskuteczniejszą obronę niewysyłanie danych od użytkownika do żadnego API systemu plików [1]. Gdy nie da się tego uniknąć, zaleca listę dozwolonych plików z identyfikatorami zamiast nazw i odrzucanie każdego żądania z nieprawidłowym identyfikatorem [1]. MITRE dodaje walidację według listy dozwolonych wartości, ograniczenie znaków i rozszerzeń w nazwach plików oraz trzymanie plików dołączanych poza katalogiem publicznym [2].
Druga warstwa to konfiguracja PHP. Dyrektywa open_basedir ogranicza pliki dostępne dla PHP, także przez include, do wskazanego drzewa katalogów [4]. Dokumentacja zaznacza jednak, że jest to tylko dodatkowa siatka bezpieczeństwa i nie powinna być jedyną ochroną [4]. Instrukcja include z danymi od użytkownika nie powinna się pojawiać bez walidacji [3].
- Sanityzacja i walidacja nazw szablonów, najlepiej przez zamkniętą listę.
- Szybkie wgrywanie łatek wtyczek i motywów.
- Utwardzanie pliku wp-config.php, bo to pierwszy cel odczytu.
- WAF jako warstwa pomocnicza, blokująca typowe sekwencje przejścia katalogów.
Historia i przykłady
MITRE wymienia jako obserwowane przykłady CWE-98 między innymi CVE-2004-0285, CVE-2005-1864 i CVE-2005-3335 [2]. LFI występuje także poza PHP. Sekurak opisał 20 października 2024 roku błąd CVE-2024-9264 w Grafanie serii 11, który umożliwiał zdalne wykonanie kodu i LFI [8]. Według tego opisu podatne były tylko instalacje z plikiem wykonywalnym DuckDB dostępnym w zmiennej PATH Grafany, którego domyślnie nie ma [8].
Przypisy
8- [1] Testing for Local File Inclusion — Web Security Testing Guide v4.2 · OWASP
- [2] CWE-98: Improper Control of Filename for Include/Require Statement in PHP Program ('PHP Remote File Inclusion') · MITRE
- [3] include — PHP Manual · The PHP Group
- [4] Description of core php.ini directives — open_basedir · The PHP Group
- [5] validate_file() — Function Reference · WordPress.org
- [6] InstaWP Connect < 0.1.0.86 – Unauthenticated Local PHP File Inclusion (CVE-2025-2636) · WPScan
- [7] WP Dark Mode < 4.0.8 – Subscriber+ Local File Inclusion (CVE-2023-0467) · WPScan
- [8] Grafana łata poważną podatność umożliwiającą RCE i LFI · Sekurak
Hasła w tym artykule
16- podatność
- CWE
- path traversal
- RFI (Remote File Inclusion)
- XSS (Cross-Site Scripting)
- atak odmowy usługi
- ujawnienie informacji wrażliwych
- zdalne wykonanie kodu (RCE)
- wgranie dowolnego pliku (arbitrary file upload)
- webshell
- podatność we wtyczce
- podatność wykorzystywana bez uwierzytelnienia
- sanityzacja danych wejściowych
- łatka (patch)
- utwardzanie pliku wp-config.php
- WAF