Praegune olukord: PHP2Shell. Kaks kriitilist PHP turvaauku (CVSS 9,2) lubavad kahjulikku koodi ilma sisselogimata. Paigad alates 21.10.2026.Mida nüüd teha →

Failide üleslaadimine PHP-s turvaliselt: PHP üleslaadimise turvalisus

Üleslaadimisvormid on veebishellide sage tee. Nii kontrollite failitüüpe õigesti, salvestate faile turvaliselt ja takistate serveril üleslaaditud skriptide käivitamist.

Seis Lugemisaeg 5 minJuhendid

Lühidalt: PHP üleslaadimise turvalisuse puhul ei otsusta üksik kontroll, vaid kombinatsioon: failitüüp serveripoolselt kontrollida, failid ümber nimetada, hoida veebijuurest (webroot) väljaspool ja mitte lubada üleslaadimiskaustas skriptide käivitamist. Kontrollimata üleslaadimisvorm on üks klassikalisi teid, mille kaudu ründajad toovad veebiserverisse tagauksi.

Miks üleslaadimisvormid on eelistatud sissepääsuvärav

Iga vorm, mis faile vastu võtab, kirjutab võõraid andmeid teie serverisse. Siia kuuluvad kandideerimisvormid, klienditeenindusportaalid, pildigaleriid, tugialad ja paljud sisuhaldussüsteemide ning poodide laiendused. Kui ründajal õnnestub sinna paigutada fail, mida veebiserver seejärel PHP-na käivitab, on tal püsiv tagauks.

Juhatuse jaoks tähendab see: süütuna näiv elulookirjelduste üleslaadimine võib halvimal juhul viia kogu veebiserveri ülevõtmiseni. Lisaks asuvad üleslaadimiskaustades sageli isikuandmed, mis on vale seadistuse korral avalikult kättesaadavad.

Administraatorite ja arendajate jaoks tähendab see: rakenduse kood ja serveri seadistus peavad kokku sobima. Nõrkuse ühel tasandil püüab sageli kinni teine, kui mõlemad on puhtalt teostatud. Kuidas juba sissetoodud faile leida, kirjeldab juhend Veebishellide tuvastamine ja eemaldamine.

PHP üleslaadimise turvalisuse põhireeglid

Järgmised reeglid vastavad OWASP Cheat Sheetide soovitustele ja on töös end tõestanud:

  • Lubatud nimekiri keelunimekirja asemel: Võtke vastu ainult sõnaselgelt lubatud failitüüpe, näiteks PDF, JPG ja PNG. Üksikute laiendite keelunimekirju saab kõrvale kalduda variantide ja topeltlaiendite abil.
  • Kontrollige sisu, mitte ainult laiendit: Tegeliku tüübi tuvastage serveris finfo abil. MIME-tüüp massiivis $_FILES on saatja väide ja ei ole usaldusväärne.
  • Uus failinimi: Ärge kasutage kunagi algset nime failinimena. Looge juhuslik nimi ja lisage lubatud nimekirjast laiend.
  • Hoidmine veebijuurest väljaspool: Salvestage failid nii, et need ei ole URL-i kaudu otse kättesaadavad. Väljastatakse skripti kaudu, millel on õiguste kontroll.
  • Suurus piirata: Rakenduses, PHP-s ja veebiserveris.
  • Käivitamist ei ole: Kui üleslaadimised peavad siiski veebijuures olema, lülitage selles kataloogis skriptide käivitamine välja.
  • Kontroll ainult serveris: JavaScripti kontrollid brauseris parandavad kasutust, kuid ei kaitse.

Turvaline näide finfo ja juhusliku nimega

Järgmine näide näitab turvalise töötluse tuuma. See on teadlikult lühike ja tuleb teie rakendusse põimida, see tähendab koos sisselogimise, õiguste kontrolli, CSRF-kaitse ja logimisega.

<?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'; // veebijuurest väljaspool

$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);
// Salvestage algne nimi andmebaasi ainult tekstina
// ja põgenege see igal väljastamisel käsuga htmlspecialchars().

Piltide puhul tasub teha veel üks samm: kodeerida pilt GD või Imagickuga uuesti ja jätta metaandmed kõrvale. See ei asenda teisi kontrolle, kuid vähendab sisseehitatud võõrandmetest tulenevat jääkriski.

Tundmatutest allikatest pärinevate dokumentide puhul, näiteks kandideerimised või reklamatsioonifotod, on lisaks mõistlik viirusekontroll enne edastamist. See kaitseb vähem veebiserverit kui töötajaid, kes faile hiljem oma tööarvutites avavad. Logige lisaks iga üleslaadimine ajaga, konto, faili suuruse ja tuvastatud tüübiga, et ebatavalisi mustreid saaks hiljem jälgida.

Sisuhaldussüsteemide ja poodide sisseehitatud meediateekidel on enamasti oma kontrollid. Riskantsemad on vormilaiendused, impordifunktsioonid ja ise programmeeritud lisalehed, mis salvestavad faile teegist mööda. Just neid kohti peaksite kontrollimisel esimesena vaatama.

Näpunäide

Väljastage faile kaitstud kaustast päistega Content-Disposition: attachment ja X-Content-Type-Options: nosniff. Siis ei kuva brauser problemaatilist sisu otse, vaid pakub seda allalaadimiseks.

PHP käivitamise väljalülitamine üleslaadimiskaustas

Isegi kui vale sisuga fail läbi lipsab, ei tohi veebiserver seda skriptina käivitada. See teine kaitsekiht kuulub igasse serverisse, mis salvestab üleslaadimisi veebijuures.

Nginx koos PHP-FPM-iga:

location ^~ /uploads/ {
    location ~* \.(php|phtml|phar)$ {
        deny all;
    }
}

Apache'i jaoks, parim otse VirtualHost'is, mitte failis .htaccess, et rakendus ei saaks reeglit üle kirjutada:

<Directory "/var/www/html/uploads">
    AllowOverride None
    <FilesMatch "\.(php|phtml|phar)$">
        Require all denied
    </FilesMatch>
</Directory>

Kui PHP töötab Apache'i moodulina (mod_php), võite samas plokis lisaks seada php_admin_flag engine off. Kontrollige pärast muudatust süütu katsefailiga, mis väljastab ainult teksti, et server vastab päringule sellele koodiga 403.

Suuruspiirangud ja seos PHP2Shelliga

Üleslaadimised on tihedalt seotud PHP seadetega post_max_size ja upload_max_filesize. PHP2Shelli raames soovitab php.net üleminekumeetmena seada post_max_size väärtusele 8M, kui üleslaadimisi vaja ei ole, või 32M üleslaadimistega, ja hoida upload_max_filesize sellest allpool. See ei ole täielik kaitse ega asenda uuendust parandatud PHP versioonile.

; php.ini või FPM-i pool (php_admin_value), seejärel taaskäivitada kõik töötajad
file_uploads        = On
post_max_size       = 32M
upload_max_filesize = 20M
max_file_uploads    = 5

Kui veebisait üleslaadimisi üldse ei vaja, on file_uploads = Off puhtaim lahendus. Millised seaded on paigani mõistlikud, on kirjas lehel Kiirmeetmed ilma paigata. Sobivad õigused üleslaadimiskataloogidele kirjeldab juhend Failiõigused veebiserveris.

Tüüpilised vead üleslaadimisfunktsioonides

Olemasolevate rakenduste läbivaatamisel ilmuvad pidevalt samad mustrid. Kontrollige oma vorme sihipäraselt nende punktide suhtes:

  • Laiendit kontrollitakse ainult osaliselt, nii et mitme laiendiga failinimed lipsavad läbi.
  • Vormi algne nimi satub salvestustee sisse. See avab teed teemanipulatsioonile ja olemasolevate failide ülekirjutamisele.
  • Üleslaadimised asuvad avalikult etteaimatavate nimedega. Kandideerimiste või lepingute puhul on see ka andmekaitseprobleem.
  • Üleslaadimiskaust on veebiserverile kirjutatav ja samal ajal käivitatav.
  • Vanu üleslaadimislaiendusi või vormipluginaid ei uuendata, kuigi tootja on avaldanud turvauuendusi.
  • Vigu ei logita. Tagasi lükatud üleslaadimised on aga varane signaal sihipärastest katsetest.

Kuidas PHP SOS konkreetselt aitab?

  • Kontrollime teie üleslaadimisfunktsioone koodis ja serveri seadistuses ning nimetame konkreetsed nõrkused prioriteediga.
  • Seame käivituslukku üleslaadimiskaustas, sobivad õigused ja suuruspiirangud serveri karastamise raames.
  • Kahtluse korral otsime üleslaadimiskataloogidest sissetoodud skripte ja puhastame need kahjuliku koodi eemaldamise kaudu.
  • Soovi korral laseme teostuse penetratsioonitestiga sõltumatult üle kontrollida.

Korduma kippuvad küsimused

Kas piisab faililaiendi kontrollist üleslaadimisel?

Ei. Laiend ja brauseri teatatud MIME-tüüp pärinevad saatjalt ning neid saab vabalt valida. Kontrollige sisu serveripoolselt, andke uus failinimi ja lukustage skriptide käivitamine üleslaadimiskataloogis.

Kus tuleks üleslaaditud faile hoida?

Parim on avalikust veebikataloogist väljaspool. Väljastamise võtab siis üle skript, mis kontrollib enne, kas kasutaja tohib faili näha. Nii ei ole failid ei otse kättesaadavad ega käivitatavad.

Kas SVG-failid on piltidena ohutud?

Mitte automaatselt. SVG on XML ja võib sisaldada aktiivset sisu. Lubage SVG-d ainult siis, kui te faile puhastate või väljastate neid ainult allalaadimisena sobiva Content-Disposition päisega.

Kas üleslaadimise suurusel on PHP2Shelliga seost?

Jah, kaudselt. php.net soovitab üleminekumeetmena madalamaid väärtusi seadetele post_max_size ja upload_max_filesize. See vähendab riski, kuid ei asenda uuendust parandatud PHP versioonile ega kõigi töötajate taaskäivitamist.

Allikad

Kohene kontakt

Iga tund loeb. Kirjutage meile kohe.

Kirjeldage lühidalt süsteemi, PHP versiooni ja tähelepanekut. Võtame teiega ühendust, selgitame olukorra välja ja töötame kaugtööna, kuni intsident on lõpetatud ja dokumenteeritud.

Kohene abi