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

Sisendi valideerimine ja filtreerimine PHP-s funktsiooniga filter_var

Kuidas arendajad kontrollivad sisendit PHP-s funktsioonidega filter_var, filter_input_array ja lubatud väärtuste nimekirjadega, millised filtrid on vananenud ja miks valideerimine ei asenda Prepared Statements'e ega väljundi kodeerimist.

Seis Lugemisaeg 5 minTurvaline arendus

Lühidalt: Sisendit valideerite PHP-s funktsiooniga filter_var() või filter_input_array() ja selgete reeglitega iga välja kohta: tüüp, vahemik, pikkus ja lubatud väärtused. Mis ei sobi, lükatakse tagasi, mitte ei ehitata vaikselt ümber. Valideerimine on oluline puhaste andmete ja väiksema ründepinna jaoks, kuid ei asenda ei Prepared Statements'e SQL-injection'i vastu ega kontekstikohast kodeerimist XSS-i vastu.

Miks „kõike filtreerida“ ei ole kontseptsioon

Paljudes vanemates PHP-projektides on iga faili alguses tsükkel, mis saadab kõik väärtused massiividest $_GET ja $_POST läbi puhastusfunktsiooni. See tundub turvaline. Praktikas eemaldab see vahel liiga palju, näiteks apostroofe perekonnanimedest, ja vahel liiga vähe, sest sama funktsioon peab korraga kehtima SQL-i, HTML-i ja failinimede jaoks.

Mõistlik valideerimine töötab teisiti: see küsib iga välja kohta, mis seal on lubatud. Tellimuse kogus on täisarv vahemikus 1 kuni ülempiirini. Sorteerimisväli on üks kolmest kindlast väärtusest. Kuupäev on kindlas vormingus ja asub teisest kuupäevast hiljem või varem. Kõik muu lükatakse tagasi.

OWASP eristab seejuures kahte taset: süntaktilist kontrolli, kas väärtusel on õige vorm, ja semantilist kontrolli, kas see on kontekstis mõistlik. Mõlemad kuuluvad serverisse; brauseris tehtavad kontrollid teenivad ainult kasutatavust.

Milliseid filtreid PHP kaasa toob

Filter-laiendus kuulub PHP-sse vaikimisi. Olulisemad valideerimisfiltrid PHP käsiraamatu järgi:

Filter Kontrollib Olulised valikud ja märkused
FILTER_VALIDATE_INT täisarv min_range, max_range
FILTER_VALIDATE_FLOAT kümnendarv decimal eraldaja jaoks
FILTER_VALIDATE_BOOL tõeväärtus koos FILTER_NULL_ON_FAILURE eristatav väärtusest „väär“
FILTER_VALIDATE_EMAIL e-posti aadressi vorm ei tõenda, et postkast olemas on
FILTER_VALIDATE_URL URL-i vorm skeemi kontrollige ise, ei toeta internatsionaliseeritud domeene
FILTER_VALIDATE_IP IP-aadress lipud privaatsete ja reserveeritud vahemike jaoks
FILTER_VALIDATE_REGEXP oma muster ankurdage muster märkidega ^ ja $

Puhastusfilter FILTER_SANITIZE_STRING on PHP 8.1-st vananenud. Kes seda veel kasutab, peaks valideerimise üle viima sobivatele filtritele ja väljundi jaoks kasutama htmlspecialchars().

filter_var PHP-s: vormi puhas kontroll

Funktsiooniga filter_input_array() saab terve vormi ühe sammuga definitsiooni vastu kontrollida. Tundmatud väljad ei võeta seejuures üle:

<?php
declare(strict_types=1);

$regeln = [
    'menge'   => ['filter' => FILTER_VALIDATE_INT,
                  'options' => ['min_range' => 1, 'max_range' => 50]],
    'email'   => FILTER_VALIDATE_EMAIL,
    'agb'     => ['filter' => FILTER_VALIDATE_BOOL, 'flags' => FILTER_NULL_ON_FAILURE],
    'versand' => ['filter' => FILTER_VALIDATE_REGEXP,
                  'options' => ['regexp' => '/^(standard|express)$/']],
];

$daten  = filter_input_array(INPUT_POST, $regeln) ?? [];
$fehler = [];

foreach ($regeln as $feld => $_) {
    if (!array_key_exists($feld, $daten) || $daten[$feld] === false || $daten[$feld] === null) {
        $fehler[] = $feld;
    }
}

if ($fehler !== []) {
    http_response_code(422);
    // Väljasta veateade iga välja kohta, sisendit mitte töödelda
}

Pöörake tähelepanu rangetele võrdlustele märgiga ===: kehtivat väärtust 0 või tühja stringi ei tohi segi ajada ebaõnnestumisega. Miks lõdvad võrdlused on siin ohtlikud, selgitab Type Juggling: lõdvad võrdlused turvariskina. Kuidas PHP päringuandmeid üldse kättesaadavaks teeb, kirjeldab Superglobals: $_GET, $_POST, $_FILES ja kaasosalised.

Lõksud e-posti, URL-i ja vabateksti puhul

Mõned filtrid teevad vähem, kui nimi lubab:

  1. URL-id: FILTER_VALIDATE_URL aktsepteerib ka muid skeeme kui http ja https. Kontrollige skeemi seejärel funktsiooniga parse_url() kindla nimekirja vastu. Kui URL-i server ise pärib, kehtivad lisareeglid, vt Server-Side Request Forgery vältimine PHP-s.
  2. E-posti aadressid: Filter kontrollib vormi, mitte omandit. Kes peab kindel olema, saadab kinnituslingi.
  3. Vabatekst: Nimesid, sõnumeid ja aadresse on märkidega vaevalt mõistlikult piirata. Kontrollige pikkust ja märgikodeeringut, näiteks mb_check_encoding($wert, 'UTF-8') abil, ning toetuge väljundis kodeerimisele.
  4. Regulaaravaldised: Ilma ^ ja $ kontrollib muster ainult, kas see esineb kuskil tekstis, mitte kas kogu väärtus sobib.
  5. Massiivid stringide asemel: Ründaja võib teksti asemel saata massiivi. Ilma tüübikontrollita viib see hoiatuste või ootamatu käitumiseni.
Näpunäide

Fikseeritud valikuväärtuste, nagu sorteerimine, keel või saatmisviis, jaoks on lubatud väärtuste nimekiri funktsiooniga in_array($wert, $erlaubt, true) või match-avaldisega lihtsam ja rangem kui iga regulaaravaldis.

Veel üks sage viga puudutab tähendusega arve, näiteks hindu, koguseid või allahindlusi. See, et väärtus on kehtiv arv, ei ütle midagi selle kohta, kas see on kontekstis lubatud. Negatiivne kogus, kaubaväärtusest suurem allahindlus või hind, mis võetakse vormist, mitte andmebaasist, on klassikalised loogikavead. Hinnad, õigused ja olekuväärtused kuuluvad seetõttu alati serverisse ja mitte kunagi peidetud vormiväljadesse.

JSON, veebikonksud ja impordid: valideerimine väljaspool vorme

Paljud sisendid ei ole tänapäeval enam vormid, vaid rakenduste JSON-päringud, makseteenuste veebikonksud (webhook) või tarnijate impordifailid. Ka seal kehtib: esmalt turvaliselt sisse lugeda, siis kontrollida. OWASP soovitab piirata suurust ja pesastussügavust enne, kui andmeid üldse sisse loetakse. PHP-s võtab osa sellest üle json_decode() maksimaalse sügavuse ja JSON_THROW_ON_ERROR-iga:

<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // kuni 64 KB
try {
    $daten = json_decode($roh, true, 16, JSON_THROW_ON_ERROR);
} catch (JsonException) {
    http_response_code(400);
    exit;
}
if (!is_array($daten) || !is_string($daten['bestellnummer'] ?? null)) {
    http_response_code(422);
    exit;
}

Veebikonksude puhul on enne sisulist kontrolli küsimus, kas sõnum tõesti pärineb märgitud teenusest. Kui teenus pakub allkirja, kontrollige seda ja võrrelge hash_equals() abil. Impordifailide puhul kontrollige iga rida nagu vormi ja katkestage vigade korral puhtalt, selle asemel et üle võtta pooleli jäänud kirjeid.

Veateated peaksid nimetama asjaomase välja, kuid mitte tagastama tagasilükatud väärtust filtreerimata kujul. Muidu tekib veateatesse endasse uus väljundikoht, mida tuleb jälle kodeerida.

Mida valideerimine ei suuda

Valideerimine vähendab ründepinda, kuid ei ole OWASP-i andmetel peamine kaitse injection'i vastu. Apostroofiga perekonnanimi on kehtiv ja peab siiski turvaliselt andmebaasi jõudma. See õnnestub ainult Prepared Statements'iga, nagu näitab juhend SQL-injection'i vältimine PHP-s. Ja kehtiv kommentaaritekst muutub ohutuks alles kontekstikohase kodeerimisega väljundis.

Õige järjekord on seega: vastuvõtul valideerida, töötlemisel parametriseerida, väljundis kodeerida. Lisaks kuuluvad sellele eelnema suuruspiirid: liiga suuri päringuid ei peaks veebiserver ja PHP üldse täielikult töötlema. Selleks on sätted, nagu post_max_size, mida tuleks pärast PHP2Shelli niikuinii üle vaadata.

Kuidas PHP SOS konkreetselt aitab?

  • Me kaardistame teie rakenduse kõik sisendid: vormid, liidesed, üleslaadimised, impordid ja veebikonksud.
  • Me määrame iga välja kohta kindlaks, mis on lubatud, ning asendame üldised puhastusfunktsioonid selgete kontrollidega.
  • Me kontrollime, kas andmebaasipäringud ja väljundid on valideerimisest sõltumatult kaitstud.
  • Me dokumenteerime reeglid nii, et teie meeskond saab neid uute funktsioonide puhul jätkata.

Süstemaatilise kontrolli kirjeldab teenus Turvaaudit ja läbitungimistest.

Korduma kippuvad küsimused

Mis vahe on valideerimisel ja puhastamisel?

Valideerimine kontrollib, kas väärtus vastab ootustele, ja lükkab selle muidu tagasi. Puhastamine muudab väärtust, näiteks eemaldades märke. Turvaotsuste jaoks on tagasilükkamine peaaegu alati parem, sest vaikselt muudetud väärtus võib tekitada uusi vigu.

Kas FILTER_SANITIZE_STRING on veel kasutatav?

Filter on PHP 8.1-st märgitud vananenuks. PHP käsiraamat soovitab selle asemel väljundis kasutada htmlspecialchars(). Olemasoleva koodi peaksite üle viima, sest vananenud funktsioonid võivad tulevastes versioonides kaduda.

Kas FILTER_VALIDATE_URL piisab linkide turvaliseks muutmiseks?

Ei. Filter kontrollib ainult aadressi vormi. Käsiraamatu kohaselt ei pea kehtiv URL algama http-ga, seetõttu peate skeemi ise kontrollima lubatud väärtuste nimekirja, näiteks https, vastu. Internatsionaliseeritud domeeninimesid filter tagasi lükkab.

Kas pean valideerima ka oma andmebaasi andmeid?

Väljundis loetakse need mitteusaldusväärseks ja kodeeritakse sobivalt. Uuesti valideerimine on mõistlik, kui andmed pärinesid algselt väljastpoolt ja neid kasutatakse nüüd uues kontekstis, näiteks failinimena või käsu osana.

Kas valideerimine aitab PHP2Shelli vastu?

Ei. PHP2Shell puudutab päringute töötlemist PHP interpretaatoris, enne kui teie rakenduse kood üldse käivitub. Selle vastu aitab ainult PHP uuendus koos kõigi PHP protsesside taaskäivitamisega.

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