Aktuālā situācija: PHP2Shell. Divas kritiskas PHP ievainojamības (CVSS 9.2) ļauj izpildīt ļaunprātīgu kodu bez pieteikšanās. Ielāpi kopš 21.10.2026.Kas jādara tagad →

Kā PHP apstrādā failu augšupielādes

Starp klikšķi uz augšupielādes pogas un jūsu kodu PHP atrodas vesela apstrādes ķēde. Šī lapa izskaidro multipart/form-data, pagaidu failus, $_FILES, robežvērtības un saistību ar PHP2Shell.

Aktuāls uz 4 min lasīšanas laiksPHP zināšanas

Īsi: kad pārlūkprogramma augšupielādē failu, tā sūta POST pieprasījumu formātā multipart/form-data, kurā veidlapas lauki un faila saturs ir secīgas atsevišķas daļas. PHP pats sadala šo pieprasījumu, ieraksta katru faila daļu pagaidu failā direktorijā upload_tmp_dir, ievada datus masīvā $_FILES un tikai tad startē jūsu skriptu. Skripts failu pārvieto ar move_uploaded_file(); visu, kas netiek pārvietots, PHP izdzēš pieprasījuma beigās.

Faila ceļš no pārlūkprogrammas līdz skriptam

Lēmumu pieņēmējiem svarīgākais ir tas, ka augšupielāde nav tikai lietojumprogrammas darbība. Liela daļa darba notiek PHP interpretatorā, pirms CMS vai veikala kods vispār tiek iesaistīts. Tāpēc kļūdas šajā PHP daļā skar katru vietni neatkarīgi no tā, vai tai ir augšupielādes veidlapa.

Norises kopskats:

  1. Tiek nosūtīta veidlapa ar method="POST" un enctype="multipart/form-data".
  2. Tīmekļa serveris pieņem pieprasījumu un nodod to PHP, atkarībā no darbības režīma ar PHP-FPM, mod_php vai citu saskarni.
  3. PHP pārbauda robežvērtības, piemēram, post_max_size, un sadala saturu pēc atdalītāja rindas, tā sauktā Boundary.
  4. Parastie lauki nonāk $_POST, faila daļas tiek ierakstītas pagaidu failos un aprakstītas $_FILES.
  5. Tikai tagad startē skripts, pārbauda failu un pārvieto to uz mērķa vietu.
  6. Pieprasījuma beigās PHP izdzēš visus pagaidu failus, kas nav pārvietoti.

multipart/form-data: augšupielādes pieprasījuma uzbūve

Augšupielādes pieprasījums ir tīrs teksts ar iegultiem faila datiem. Galvene Content-Type nosauc Boundary, un saturā šī rinda atdala atsevišķās daļas. Katrai daļai ir savas galvenes rindas ar lauka nosaukumu un, ja nepieciešams, faila nosaukumu. Ļoti saīsināts, nekaitīgs piemērs:

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--

Visas šī teksta ziņas nāk no sūtītāja, arī faila nosaukums un daļas Content-Type. PHP tās pārņem $_FILES, bet nepārbauda, vai tās ir ticamas.

Masīvs $_FILES

Laukam ar nosaukumu lebenslauf masīvs $_FILES['lebenslauf'] saskaņā ar PHP rokasgrāmatu satur šādas atslēgas:

Atslēga Saturs Vai uzticams?
name sākotnējais faila nosaukums pie sūtītāja nē
full_path pārlūkprogrammas paziņotais ceļš, kopš PHP 8.1.0 nē
type MIME tips pēc pārlūkprogrammas, PHP to nepārbauda nē
size izmērs baitos to nosaka PHP
tmp_name pagaidu faila ceļš serverī to piešķir PHP
error augšupielādes apstrādes kļūdas kods to iestata PHP

Laukiem ar kvadrātiekavām nosaukumā, piemēram, bilder[], katra atslēga satur masīvu ar vienu ierakstu katram failam. Lietojumprogramma tad iet cauri, piemēram, $_FILES['bilder']['error'], un ar to pašu indeksu piekļūst tmp_name un name.

Veidlapa var papildus pirms faila lauka nosūtīt slēptu lauku MAX_FILE_SIZE. Saskaņā ar rokasgrāmatu tā ir tikai norāde pārlūkprogrammai, ko viegli apiet. Uzticēties var tikai robežām, ko īsteno serveris: PHP, tīmekļa serverī un pašā lietojumprogrammā.

Robežvērtības: php.ini direktīvas augšupielādēm

Šīs direktīvas vada augšupielādes apstrādi. Noklusējuma vērtības ņemtas no PHP rokasgrāmatas un ir spēkā, ja php.ini tās nepārraksta.

Direktīva Noklusējums Maināms kur
file_uploads 1 tikai sistēmas konfigurācijā
upload_tmp_dir tukšs (sistēmas pagaidu direktorijs) tikai sistēmas konfigurācijā
upload_max_filesize 2M php.ini, pūls, direktorija konfigurācija
post_max_size 8M php.ini, pūls, direktorija konfigurācija
max_file_uploads 20 php.ini, pūls, direktorija konfigurācija
enable_post_data_reading 1 php.ini, pūls, direktorija konfigurācija

post_max_size jābūt lielākam par upload_max_filesize, un memory_limit saskaņā ar rokasgrāmatu parasti jābūt lielākam par post_max_size. Ja upload_tmp_dir nav rakstāms, PHP pāriet uz sistēmas pagaidu direktoriju. Ar open_basedir pagaidu direktorijam jābūt atļautam, citādi augšupielādes neizdodas. Praktiskās vērtības un to sekas apraksta raksts post_max_size un upload_max_filesize saprātīga ierobežošana.

Kļūdu kodu pareiza izvērtēšana

Lauks error norāda, kas apstrādes laikā noticis. Konstantes iet no UPLOAD_ERR_OK (0) cauri UPLOAD_ERR_INI_SIZE (1), UPLOAD_ERR_FORM_SIZE (2), UPLOAD_ERR_PARTIAL (3) un UPLOAD_ERR_NO_FILE (4) līdz UPLOAD_ERR_NO_TMP_DIR (6), UPLOAD_ERR_CANT_WRITE (7) un 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);
}

Piemērs rāda tikai mehāniku. Faila tipa pārbaudi, glabāšanu ārpus webroot un skriptu izpildes bloķēšanu apraksta ceļvedis Failu augšupielādes PHP drošā īstenošana.

Augšupielādes un PHP2Shell: ko nozīmē pagaidu pasākumi

PHP2Shell ievainojamības CVE-2026-109618 un CVE-2026-109619 skar pieprasījuma apstrādi PHP interpretatorā. Tāpēc php.net kā pagaidu pasākumus min, cita starpā, post_max_size = 8M (bez augšupielādēm) vai 32M (ar augšupielādēm), zemāku upload_max_filesize un session.upload_progress.enabled=0. Šīm vērtībām jābūt php.ini, FPM pūlā vai servera konfigurācijā, pēc tam jāpārstartē visi darbprocesi.

Speciālisti papildus iesaka bloķēt multipart/form-data pieprasījumus ārpus īstajiem augšupielādes ceļiem starpniekserverī vai WAF. Tas ir neoficiāls pasākums ar risku, ka veidlapas pārstās darboties; izvērtējumu apraksta raksts Augšupielādes pieprasījumu filtrēšana tīkla malā. Neviens no šiem pasākumiem neaizstāj atjauninājumu uz PHP 8.5.12, 8.4.27, 8.3.36 vai 8.2.35.

Kā PHP SOS palīdz konkrēti?

  • Mēs noskaidrojam, kurām jūsu vietnēm augšupielādes patiešām vajadzīgas un kādos ceļos.
  • Mēs iestatām robežvērtības un pagaidu pasākumus katram pūlam, pārstartējam visus darbprocesus un testējam veidlapas.
  • Mēs pārbaudām augšupielāžu direktorijus uz izpildāmiem failiem un bloķējam skriptu izpildi servera nostiprināšanas ietvaros.
  • Mēs ieviešam PHP atjauninājumu un dokumentējam ielāpu stāvokli katrai vietnei.

Biežāk uzdotie jautājumi

Kur PHP vispirms saglabā augšupielādētos failus?

Pagaidu direktorijā. Pēc noklusējuma tas ir sistēmas pagaidu direktorijs; to var mainīt ar upload_tmp_dir. Ja skriptā fails netiek pārvietots, PHP to izdzēš pieprasījuma beigās.

Vai laukam type masīvā $_FILES var uzticēties?

Nē. MIME tipu paziņo pārlūkprogramma, un saskaņā ar rokasgrāmatu PHP to nepārbauda. Arī name un full_path nāk no sūtītāja. Faktisko faila tipu nosakiet servera pusē pēc satura.

Kāpēc $_FILES ir tukšs, kaut gan fails tika nosūtīts?

Visbiežāk viss pieprasījums bija lielāks par post_max_size. Tad PHP pilnībā iztukšo $_POST un $_FILES, un masīvā nav kļūdas koda. Citi iemesli ir trūkstošs enctype veidlapā vai izslēgts file_uploads.

Vai pret PHP2Shell palīdz augšupielāžu aizliegšana lietojumprogrammā?

Nē. Pieprasījuma datu apstrāde notiek PHP, pirms darbojas lietojumprogrammas kods. Efektīvi ir PHP atjauninājums un visu darbprocesu pārstartēšana; šaurākas robežvērtības ir tikai pagaidu pasākums.

Kāda ir atšķirība starp upload_max_filesize un post_max_size?

upload_max_filesize ierobežo katru atsevišķo failu, post_max_size visu pieprasījuma saturu, ieskaitot visus failus un laukus. Tāpēc post_max_size jābūt lielākam par upload_max_filesize.

Avoti

Tūlītējs kontakts

Katra stunda ir svarīga. Rakstiet mums tūlīt.

Īsi aprakstiet sistēmu, PHP versiju un novēroto. Mēs sazināsimies, noskaidrosim situāciju un strādāsim attālināti, līdz incidents ir slēgts un dokumentēts.

Tūlītēja palīdzība