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 →

Kako PHP obdela nalaganje datotek

Med klikom na Naloži in vašo kodo je v PHP cela veriga obdelave. Ta stran razlaga multipart/form-data, začasne datoteke, $_FILES, omejitve in povezavo s PHP2Shell.

Stanje 5 min branjaZnanje o PHP

Na kratko: Ko brskalnik naloži datoteko, pošlje zahtevo POST v obliki multipart/form-data, v kateri so polja obrazca in vsebine datotek kot posamezni deli zapisani drug za drugim. PHP to zahtevo razčleni sam, vsak del z datoteko zapiše v začasno datoteko v upload_tmp_dir, podatke vpiše v $_FILES in šele nato zažene vašo skripto. Skripta datoteko premakne z move_uploaded_file(); vse, kar ni premaknjeno, PHP ob koncu zahteve izbriše.

Pot datoteke od brskalnika do skripte

Za odločevalce je predvsem pomembno eno: nalaganje ni opravilo same aplikacije. Velik del dela se opravi v interpreterju PHP, še preden je koda sistema CMS ali spletne trgovine sploh vpletena. Zato napake v tem delu PHP zadevajo vsako spletno stran, ne glede na to, ali ima obrazec za nalaganje ali ne.

Potek na kratko:

  1. Odda se obrazec z method="POST" in enctype="multipart/form-data".
  2. Spletni strežnik zahtevo sprejme in jo preda PHP, odvisno od načina delovanja prek PHP-FPM, mod_php ali drugega vmesnika.
  3. PHP preveri omejitve, kot je post_max_size, in vsebino razdeli na podlagi ločilnega niza, tako imenovane meje (boundary).
  4. Navadna polja pristanejo v $_POST, deli z datotekami se zapišejo v začasne datoteke in opišejo v $_FILES.
  5. Šele zdaj se zažene skripta, preveri datoteko in jo premakne na ciljno mesto.
  6. Ob koncu zahteve PHP izbriše vse začasne datoteke, ki niso bile premaknjene.

multipart/form-data: zgradba zahteve za nalaganje

Zahteva za nalaganje je čisto besedilo z vdelanimi podatki datoteke. Glava Content-Type navaja mejo (boundary), v vsebini pa ta niz loči posamezne dele. Vsak del ima lastne glave z imenom polja in po potrebi imenom datoteke. Močno skrajšan, neškodljiv primer:

POST /bewerbung HTTP/1.1
Content-Type: multipart/form-data; boundary=----trenner42

------trenner42
Content-Disposition: form-data; name="vorname"

Erika
------trenner42
Content-Disposition: form-data; name="lebenslauf"; filename="lebenslauf.pdf"
Content-Type: application/pdf

%PDF-1.7 ... Dateiinhalt ...
------trenner42--

Vsi podatki v tem besedilu izvirajo od pošiljatelja, tudi ime datoteke in Content-Type dela. PHP jih prevzame v $_FILES, vendar ne preverja njihove verodostojnosti.

Polje $_FILES

Za polje z imenom lebenslauf $_FILES['lebenslauf'] po priročniku PHP vsebuje te ključe:

Ključ Vsebina Ali mu je mogoče zaupati?
name prvotno ime datoteke pri pošiljatelju ne
full_path pot, ki jo sporoči brskalnik, od PHP 8.1.0 ne
type tip MIME po navedbi brskalnika, PHP ga ne preverja ne
size velikost v bajtih ugotovi PHP
tmp_name pot začasne datoteke na strežniku dodeli PHP
error koda napake pri obdelavi nalaganja nastavi PHP

Pri poljih z oglatimi oklepaji v imenu, na primer bilder[], vsak ključ vsebuje polje z enim vnosom na datoteko. Aplikacija nato na primer prehodi $_FILES['bilder']['error'] in prek istega indeksa dostopa do tmp_name in name.

Obrazec lahko pred poljem za datoteko dodatno pošlje skrito polje MAX_FILE_SIZE. Po priročniku je to samo namig brskalniku, ki ga je mogoče zlahka obiti. Zanesete se lahko izključno na meje, ki jih uveljavlja strežnik: v PHP, v spletnem strežniku in v sami aplikaciji.

Omejitve: direktive php.ini za nalaganje

Te direktive nadzorujejo obdelavo nalaganja. Privzete vrednosti izhajajo iz priročnika PHP in veljajo, kadar jih php.ini ne prepiše.

Direktiva Privzeto Mogoče spremeniti v
file_uploads 1 samo sistemska konfiguracija
upload_tmp_dir prazno (sistemski temp) samo sistemska konfiguracija
upload_max_filesize 2M php.ini, pool, konfiguracija imenika
post_max_size 8M php.ini, pool, konfiguracija imenika
max_file_uploads 20 php.ini, pool, konfiguracija imenika
enable_post_data_reading 1 php.ini, pool, konfiguracija imenika

post_max_size mora biti večji od upload_max_filesize, memory_limit pa mora biti po priročniku praviloma večji od post_max_size. Če v upload_tmp_dir ni mogoče pisati, PHP preide na temp imenik sistema. Pri open_basedir mora biti temp imenik dovoljen, sicer nalaganje ne uspe. Praktične vrednosti in njihove posledice opisuje prispevek Smiselna omejitev post_max_size in upload_max_filesize.

Pravilno ovrednotenje kod napak

Polje error pove, kaj se je zgodilo pri obdelavi. Konstante segajo od UPLOAD_ERR_OK (0) prek UPLOAD_ERR_INI_SIZE (1), UPLOAD_ERR_FORM_SIZE (2), UPLOAD_ERR_PARTIAL (3) in UPLOAD_ERR_NO_FILE (4) do UPLOAD_ERR_NO_TMP_DIR (6), UPLOAD_ERR_CANT_WRITE (7) in UPLOAD_ERR_EXTENSION (8).

<?php
declare(strict_types=1);

$datei = $_FILES['lebenslauf'] ?? null;
if ($datei === null) {
    exit('Keine Upload-Daten, eventuell wurde post_max_size überschritten.');
}

$meldung = match ($datei['error']) {
    UPLOAD_ERR_OK => null,
    UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE => 'Datei zu groß.',
    UPLOAD_ERR_NO_FILE => 'Keine Datei gewählt.',
    default => 'Upload fehlgeschlagen.',
};

if ($meldung === null && is_uploaded_file($datei['tmp_name'])) {
    $ziel = '/srv/app/uploads/' . bin2hex(random_bytes(16)) . '.pdf';
    move_uploaded_file($datei['tmp_name'], $ziel);
}

Primer kaže samo mehaniko. Preverjanje tipa datoteke, shranjevanje zunaj korena spleta (webroot) in onemogočanje izvajanja skript opisuje vodnik Varno nalaganje datotek v PHP.

Nalaganje in PHP2Shell: kaj pomenijo prehodni ukrepi

Ranljivosti PHP2Shell CVE-2026-109618 in CVE-2026-109619 zadevata obdelavo okoli zahteve v interpreterju PHP. Zato php.net kot prehodne ukrepe med drugim navaja post_max_size = 8M (brez nalaganja) ali 32M (z nalaganjem), upload_max_filesize pod tem, pa tudi session.upload_progress.enabled=0. Te vrednosti sodijo v php.ini, pool FPM ali konfiguracijo strežnika, nato pa je treba znova zagnati vse workerje.

Strokovni avtorji dodatno predlagajo, da se zahteve multipart/form-data zunaj pravih poti za nalaganje blokirajo na proxyju ali v WAF. To je neuradni ukrep s tveganjem, da se obrazci pokvarijo; tehtanje opisuje prispevek Filtriranje zahtev za nalaganje na robu. Noben od teh ukrepov ne nadomesti posodobitve na PHP 8.5.12, 8.4.27, 8.3.36 ali 8.2.35.

Kako PHP SOS pomaga konkretno?

  • Ugotovimo, katere vaše spletne strani dejansko potrebujejo nalaganje in na katerih poteh.
  • Omejitve in prehodne ukrepe nastavimo po poolih, znova zaženemo vse workerje in preizkusimo obrazce.
  • Imenike za nalaganje preverimo glede izvršljivih datotek in onemogočimo izvajanje skript v okviru utrjevanja strežnika.
  • Namestimo posodobitev PHP in dokumentiramo stanje popravkov po posameznih spletnih straneh.

Pogosta vprašanja

Kam PHP najprej shrani naložene datoteke?

V začasen imenik. Privzeto je to začasni imenik sistema; z upload_tmp_dir ga je mogoče spremeniti. Če skripta datoteke ne premakne, jo PHP izbriše ob koncu zahteve.

Ali lahko zaupam polju type v $_FILES?

Ne. Tip MIME sporoči brskalnik, PHP ga po priročniku ne preverja. Tudi name in full_path izvirata od pošiljatelja. Dejanski tip datoteke ugotovite na strežniku na podlagi vsebine.

Zakaj je $_FILES prazen, čeprav je bila datoteka poslana?

Najpogosteje je bila celotna zahteva večja od post_max_size. Takrat PHP popolnoma izprazni $_POST in $_FILES, brez kode napake v polju. Drugi vzroki so manjkajoč enctype v obrazcu ali izklopljen file_uploads.

Ali proti PHP2Shell pomaga, če v aplikaciji prepovem nalaganje?

Ne. Obdelava podatkov zahteve poteka v PHP, še preden se izvede koda aplikacije. Učinkovita sta posodobitev PHP in ponovni zagon vseh workerjev; ožje omejitve so samo prehodni ukrep.

Kakšna je razlika med upload_max_filesize in post_max_size?

upload_max_filesize omejuje vsako posamezno datoteko, post_max_size pa celotno vsebino zahteve, vključno z vsemi datotekami in polji. post_max_size mora zato biti večji od upload_max_filesize.

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č