Situația actuală: PHP2Shell. Două vulnerabilități critice PHP (CVSS 9.2) permit cod malițios fără autentificare. Patchuri din 21.10.2026.Ce este de făcut acum →

Validarea și filtrarea intrărilor în PHP cu filter_var

Cum verifică dezvoltatorii intrările în PHP cu filter_var, filter_input_array și liste de permisiuni, ce filtre sunt depășite și de ce validarea nu înlocuiește prepared statements și codarea la ieșire.

Stadiu 6 min de cititDezvoltare sigură

Pe scurt: Validați intrările în PHP cu filter_var() sau filter_input_array() și cu reguli clare pentru fiecare câmp: tip, interval, lungime și valori permise. Ce nu se potrivește este respins, nu transformat pe tăcute. Validarea este importantă pentru date curate și o suprafață de atac mai mică, dar nu înlocuiește nici prepared statements împotriva SQL injection, nici codarea adecvată contextului împotriva XSS.

De ce „filtrează totul” nu este un concept

În multe proiecte PHP mai vechi se găsește la începutul fiecărui fișier o buclă care trece toate valorile din $_GET și $_POST printr-o funcție de curățare. Aceasta dă o senzație de siguranță. În practică, elimină uneori prea mult, de exemplu apostrofurile din nume de familie, și alteori prea puțin, pentru că aceeași funcție ar trebui să fie valabilă simultan pentru SQL, HTML și nume de fișiere.

O validare rezonabilă lucrează altfel: se întreabă pentru fiecare câmp ce este permis acolo. O cantitate comandată este un număr întreg între 1 și o limită superioară. Un câmp de sortare este una dintre trei valori fixe. O dată are un anumit format și se află înainte sau după o altă dată. Orice altceva este respins.

OWASP distinge aici două niveluri: verificarea sintactică, dacă o valoare are forma corectă, și verificarea semantică, dacă are sens în context. Ambele aparțin serverului; verificările din browser servesc doar comodității de utilizare.

Ce filtre oferă PHP

Extensia de filtre este inclusă în PHP în mod implicit. Cele mai importante filtre de validare conform manualului PHP:

Filtru Verifică Opțiuni și observații importante
FILTER_VALIDATE_INT număr întreg min_range, max_range
FILTER_VALIDATE_FLOAT număr zecimal decimal pentru separator
FILTER_VALIDATE_BOOL valoare booleană cu FILTER_NULL_ON_FAILURE se poate deosebi de „fals”
FILTER_VALIDATE_EMAIL forma unei adrese de e-mail nu dovedește că poșta există
FILTER_VALIDATE_URL forma unei URL verificați singuri schema, fără domenii internaționalizate
FILTER_VALIDATE_IP adresă IP flaguri pentru intervale private și rezervate
FILTER_VALIDATE_REGEXP tipar propriu ancorați tiparul cu ^ și $

Filtrul de curățare FILTER_SANITIZE_STRING este depășit începând cu PHP 8.1. Cine îl mai folosește ar trebui să treacă validarea la filtre potrivite și să folosească htmlspecialchars() la ieșire.

filter_var în PHP: verificarea curată a unui formular

Cu filter_input_array() se poate verifica un întreg formular într-un singur pas, pe baza unei definiții. Câmpurile necunoscute nu sunt preluate:

<?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);
    // Afișați mesajul de eroare pentru fiecare câmp, nu procesați intrările
}

Rețineți comparațiile stricte cu ===: o valoare validă 0 sau un șir gol nu are voie să fie confundată cu un eșec. De ce comparațiile lejere sunt periculoase aici explică Type Juggling: comparațiile lejere ca risc de securitate. Cum pune PHP, în general, la dispoziție datele cererii descrie Superglobals: $_GET, $_POST, $_FILES și celelalte.

Capcane la e-mail, URL și texte libere

Unele filtre fac mai puțin decât sugerează numele lor:

  1. URL-uri: FILTER_VALIDATE_URL acceptă și alte scheme decât http și https. Verificați apoi schema cu parse_url() față de o listă fixă. Dacă URL-ul este apelat de server, se aplică reguli suplimentare, vedeți Prevenirea Server-Side Request Forgery în PHP.
  2. Adrese de e-mail: Filtrul verifică forma, nu proprietatea. Cine trebuie să fie sigur trimite un link de confirmare.
  3. Text liber: Numele, mesajele și adresele pot fi greu limitate în mod rezonabil la anumite caractere. Verificați lungimea și codarea caracterelor, de exemplu cu mb_check_encoding($wert, 'UTF-8'), și bazați-vă la ieșire pe codare.
  4. Expresii regulate: Fără ^ și $, un tipar verifică doar dacă apare undeva în text, nu dacă se potrivește întreaga valoare.
  5. Array-uri în loc de șiruri: Un atacator poate trimite un array în loc de un text. Fără verificarea tipului, aceasta duce la avertismente sau la comportament neașteptat.
Sfat

Pentru valori de selecție fixe, precum sortarea, limba sau modul de expediere, o listă de permisiuni cu in_array($wert, $erlaubt, true) sau cu o expresie match este mai simplă și mai strictă decât orice expresie regulată.

O altă greșeală frecventă privește numerele cu semnificație, de exemplu prețurile, cantitățile sau reducerile. Faptul că o valoare este un număr valid nu spune nimic despre dacă este permisă în context. O cantitate negativă, o reducere peste valoarea mărfii sau un preț preluat din formular în loc de baza de date sunt erori clasice de logică. Prețurile, permisiunile și valorile de stare aparțin de aceea întotdeauna serverului și niciodată unor câmpuri ascunse de formular.

JSON, webhook-uri și importuri: validarea dincolo de formulare

Multe intrări nu mai sunt astăzi formulare, ci cereri JSON de la aplicații, webhook-uri de la servicii de plată sau fișiere de import de la furnizori. Și aici se aplică: mai întâi citire sigură, apoi verificare. OWASP sfătuiește să limitați dimensiunea și adâncimea de imbricare înainte ca datele să fie citite. În PHP, json_decode() cu o adâncime maximă și JSON_THROW_ON_ERROR preia o parte din aceasta:

<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // cel mult 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;
}

La webhook-uri, înaintea verificării conținutului se pune întrebarea dacă mesajul provine într-adevăr de la serviciul indicat. Dacă serviciul oferă o semnătură, verificați-o și comparați-o cu hash_equals(). La fișierele de import, verificați fiecare rând ca pe un formular și opriți-vă curat la erori, în loc să preluați înregistrări pe jumătate.

Mesajele de eroare ar trebui să numească câmpul afectat, dar să nu returneze nefiltrată valoarea respinsă. Altfel apare chiar la mesajul de eroare un nou punct de ieșire, care trebuie codat din nou.

Ce nu poate realiza validarea

Validarea reduce suprafața de atac, dar, potrivit OWASP, nu este apărarea principală împotriva injection. Un nume de familie cu apostrof este valid și trebuie totuși să ajungă în siguranță într-o bază de date. Aceasta reușește doar cu prepared statements, așa cum arată ghidul Prevenirea SQL injection în PHP. Iar un text de comentariu valid devine inofensiv abia prin codarea adecvată contextului la ieșire.

Ordinea corectă este deci: validați la primire, parametrizați la procesare, codați la ieșire. În plus, înaintea lor trebuie să stea limitele de dimensiune: cererile mult prea mari nu ar trebui să fie procesate integral nici de serverul web, nici de PHP. Servesc pentru aceasta setări precum post_max_size, care oricum ar trebui verificate după PHP2Shell.

Cum ajută PHP SOS concret?

  • Inventariem toate intrările aplicației dumneavoastră: formulare, interfețe, upload-uri, importuri și webhook-uri.
  • Stabilim pentru fiecare câmp ce este permis și înlocuim funcțiile globale de curățare cu verificări clare.
  • Verificăm dacă accesul la baza de date și ieșirile sunt securizate independent de validare.
  • Documentăm regulile astfel încât echipa dumneavoastră să le poată continua la funcții noi.

O verificare sistematică descrie serviciul Audit de securitate și test de penetrare.

Întrebări frecvente

Care este diferența dintre validare și curățare?

Validarea verifică dacă o valoare corespunde așteptărilor și, altfel, o respinge. Curățarea modifică valoarea, de exemplu prin eliminarea unor caractere. Pentru deciziile de securitate, respingerea este aproape întotdeauna mai bună, deoarece o valoare modificată pe tăcute poate produce erori noi.

Mai este utilizabil FILTER_SANITIZE_STRING?

Filtrul este marcat ca depășit începând cu PHP 8.1. Manualul PHP recomandă în schimb htmlspecialchars() la ieșire. Ar trebui să convertiți codul existent, deoarece funcțiile depășite pot dispărea în versiuni viitoare.

Este suficient FILTER_VALIDATE_URL pentru a face linkurile sigure?

Nu. Filtrul verifică doar forma adresei. Potrivit manualului, o URL validă nu trebuie să înceapă cu http, de aceea trebuie să verificați singuri schema față de o listă de permisiuni, precum https. Numele de domeniu internaționalizate sunt respinse de filtru.

Trebuie să validez și datele din propria bază de date?

La ieșire, ele sunt considerate nesigure și sunt codate corespunzător. O nouă validare este utilă dacă datele au venit inițial din exterior și sunt acum folosite într-un context nou, de exemplu ca nume de fișier sau parte dintr-o comandă.

Ajută validarea împotriva PHP2Shell?

Nu. PHP2Shell privește procesarea cererilor în interpretorul PHP, înainte ca să ruleze măcar codul aplicației dumneavoastră. Împotriva ei ajută doar actualizarea PHP, urmată de repornirea tuturor proceselor PHP.

Surse

Contact imediat

Fiecare oră contează. Scrieți-ne acum.

Descrieți pe scurt sistemul, versiunea PHP și ce ați observat. Ne vom face auziți, clarificăm situația și lucrăm la distanță până când incidentul este încheiat și documentat.

Ajutor imediat