Actuele situatie: PHP2Shell. Twee kritieke PHP-kwetsbaarheden (CVSS 9.2) maken schadelijke code zonder inloggen mogelijk. Patches sinds 21-10-2026.Wat u nu moet doen →

Ingebouwde beveiligingsfuncties van PHP

PHP levert veilige bouwstenen mee voor wachtwoorden, willekeurige waarden, escaping, cryptografie en sessies. Wie ze consequent gebruikt, vermijdt de meest voorkomende toepassingsfouten.

Stand 5 min. leestijdPHP-kennis

Kort gezegd: PHP levert voor de meest voorkomende beveiligingstaken kant-en-klare, geteste functies mee: password_hash() voor wachtwoorden, random_bytes() en random_int() voor tokens, htmlspecialchars() tegen cross-site scripting, voorbereide queries met PDO tegen SQL-injectie, hash_equals() voor veilige vergelijkingen en de Sodium-extensie voor cryptografie. Wie deze bouwstenen consequent gebruikt, vermijdt de meeste toepassingslekken. Tegen fouten in de PHP-interpreter zelf, zoals bij PHP2Shell, helpen ze niet; daar helpt alleen de update.

Waarom ingebouwde PHP-beveiligingsfuncties?

Beveiligingscode zelf schrijven is foutgevoelig. Een eigen wachtwoordhash, een zelfgebouwde tokengenerator of een zelfgemaakt filter voor HTML-uitvoer zien er vaak goed uit en zijn het toch niet. De ingebouwde functies zijn gedocumenteerd, getest en worden met PHP-updates onderhouden.

Voor beslissers betekent dat: vraag uw bureau of ontwikkelteam niet of beveiligingsfuncties zelf zijn gebouwd, maar of de standaardfuncties van de taal worden gebruikt. De tabel geeft een overzicht.

Taak Functie Beschikbaar sinds Belangrijke aanwijzing
Wachtwoorden opslaan password_hash(), password_verify() PHP 5.5 kolom tot 255 tekens; bcrypt kapt af op 72 bytes
Willekeurige tokens random_bytes(), random_int() PHP 7.0 nooit rand() of mt_rand() voor geheimen
Toeval objectgeoriënteerd Random\Randomizer PHP 8.2 dezelfde veiligheid, flexibelere interface
HTML-uitvoer escapen htmlspecialchars() van oudsher standaardvlaggen sinds 8.1 escapen ook enkele aanhalingstekens
Vergelijking in constante tijd hash_equals() PHP 5.6 gebruikersinvoer als tweede argument
Moderne cryptografie Sodium (sodium_*) PHP 7.2 in plaats van eigen versleuteling
Geheimen in stacktraces #[\SensitiveParameter] PHP 8.2 waarde verschijnt niet in de trace
Invoer controleren filter_var() PHP 5.2 controleert formaat, vervangt geen escaping

Wachtwoorden en tokens

password_hash() maakt een gezouten hash, password_verify() controleert hem. Met PASSWORD_DEFAULT gebruikt PHP momenteel bcrypt; sinds PHP 8.4 ligt de standaardkostenfactor volgens de handleiding op 12 in plaats van 10. Omdat het standaardalgoritme kan veranderen, adviseert de handleiding een databasekolom van 255 tekens. Bij bcrypt worden wachtwoorden na 72 bytes afgekapt, wat bij zeer lange wachtzinnen in acht moet worden genomen.

<?php
// Registratie
$hash = password_hash($passwort, PASSWORD_DEFAULT);

// Aanmelding, inclusief automatische opwaardering van oude hashes
if (password_verify($eingabe, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($eingabe, PASSWORD_DEFAULT); // opnieuw opslaan
    }
}

// Token voor een link om het wachtwoord opnieuw in te stellen
$token = bin2hex(random_bytes(32));

Voor vergelijkingen van geheimen, bijvoorbeeld een handtekening, hoort hash_equals() te worden gebruikt. Een gewone vergelijking met === kan volgens de handleiding via de looptijd verraden vanaf welke plaats twee waarden verschillen. Uitgebreider: Wachtwoorden in PHP veilig opslaan en veilige willekeurige getallen en tokens.

Uitvoer escapen en de database veilig bevragen

Cross-site scripting ontstaat wanneer gebruikersinvoer ongefilterd in HTML terechtkomt. htmlspecialchars() zet speciale tekens om in HTML-entiteiten. Sinds PHP 8.1 zijn de standaardvlaggen ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401; daarvoor werden enkele aanhalingstekens niet omgezet. Wie oudere versies moet ondersteunen, geeft de vlaggen uitdrukkelijk op.

SQL-injectie voorkomen voorbereide queries. De waarden worden gescheiden van de SQL-tekst overgedragen en kunnen de query niet wijzigen:

<?php
$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE email = :email');
$stmt->execute(['email' => $email]);
$kunde = $stmt->fetch();

echo htmlspecialchars($kunde['name'] ?? '', ENT_QUOTES, 'UTF-8');

De details staan onder Cross-site scripting in PHP voorkomen en op de pagina over SQL-injectie.

Invoer controleren is een tweede, afzonderlijke stap. filter_var() stelt vast of een waarde een geldig formaat heeft, bijvoorbeeld een e-mailadres of een geheel getal binnen een toegestaan bereik. Dat vervangt echter geen escaping bij de uitvoer en geen voorbereide query, want ook formeel geldige waarden kunnen speciale tekens bevatten.

Geheimen uit foutmeldingen houden

Een onderschat datalek zijn stacktraces. Treedt in een functie een fout op, dan legt PHP de aanroepketen vast inclusief argumenten. Staat daarin een wachtwoord of API-sleutel, dan belandt die in het log. Sinds PHP 8.2 markeert het attribuut #[\SensitiveParameter] zulke parameters; hun waarde verschijnt in de trace dan alleen als object SensitiveParameterValue.

<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
    // ... controle ...
    throw new RuntimeException('Datenbank nicht erreichbar');
}

Volgens een aanwijzing in de handleiding werkt het attribuut alleen bij de concrete implementatie, niet bij de methode van een interface. Plaats het daarom daar waar de code daadwerkelijk draait.

Sessies: veilige instellingen en nieuwe standaarden

Sessies zijn een veelvoorkomend aanvalsdoel. Drie instellingen zijn centraal: session.use_strict_mode=1 weigert sessie-ID's die de server niet zelf heeft gemaakt; session.cookie_httponly=1 verhindert toegang tot de sessiecookie via JavaScript; session.cookie_samesite=Lax bemoeilijkt het meesturen bij vreemde sites. Volgens de aangenomen RFC worden precies deze drie waarden met PHP 8.6 de standaard. Stel ze tot die tijd zelf in, en ook daarna uitdrukkelijk, zodat de configuratie niet van de standaard afhangt.

session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.cookie_secure = 1

Meer daarover onder Sessies in PHP beveiligen.

Wat ingebouwde functies niet kunnen

Het PHP-project is in zijn beveiligingsbeleid duidelijk: PHP is geen sandbox. Omzeilingen van open_basedir of disable_functions, kwaadaardige invoer voor unserialize() en ongecontroleerde argumenten voor functies als mysqli_query() gelden niet als beveiligingslekken van PHP. Voor beheerders betekent dat: deze instellingen zijn nuttige hardening, maar geen beveiligingsgrens, en unserialize() heeft met vreemde gegevens niets te maken.

Het tweede punt betreft PHP2Shell. CVE-2026-109618 en CVE-2026-109619 maken volgens php.net code-uitvoering mogelijk voordat of terwijl uw toepassing draait; bij mod_php is een exploit getoond voordat er überhaupt toepassingscode wordt uitgevoerd. Geen enkele functie in uw code kan dat opvangen. Veilig programmeren en een actuele PHP-versie zijn twee afzonderlijke plichten, en beide moeten worden vervuld.

Hoe helpt PHP SOS concreet?

In de beveiligingsaudit voor PHP-toepassingen controleren wij gericht:

  • Wachtwoord- en tokenafhandeling: Worden password_hash() en random_bytes() gebruikt, of zijn er eigen constructies?
  • Uitvoer en queries: Waar komt invoer ongefilterd in HTML, SQL of shell-opdrachten terecht?
  • Sessieconfiguratie: Zijn strict mode, HttpOnly, SameSite en Secure ingesteld en niet te overschrijven?
  • Looptijd: Draait er een ondersteunde PHP-versie met de correcties van 21 oktober 2026?

Veelgestelde vragen

Hoe slaat men wachtwoorden in PHP goed op?

Met password_hash() en PASSWORD_DEFAULT; gecontroleerd wordt met password_verify(). De databasekolom moet volgens de handleiding tot 255 tekens kunnen bevatten, omdat het standaardalgoritme in de toekomst kan veranderen.

Is rand() geschikt voor tokens?

Nee. Voor tokens, sleutels en wachtwoordlinks horen random_bytes() of random_int() te worden gebruikt. Ze leveren volgens de handleiding cryptografisch veilige willekeurige waarden.

Sinds wanneer zit Sodium in PHP?

De Sodium-extensie voor moderne cryptografie maakt sinds PHP 7.2.0 deel uit van PHP. Oudere versies konden haar alleen via PECL achteraf toevoegen.

Beschermen deze functies tegen PHP2Shell?

Nee. Ze beschermen tegen fouten in uw toepassing. PHP2Shell zit in de interpreter zelf en wordt alleen gedicht met een PHP-update, gevolgd door de herstart van alle PHP-processen.

Veranderen de sessiestandaarden in PHP 8.6?

Ja, volgens de aangenomen RFC worden session.use_strict_mode en session.cookie_httponly standaard ingeschakeld en wordt session.cookie_samesite op Lax gezet. Bestaande configuraties moet u toch zelf uitdrukkelijk instellen.

Bronnen

Direct contact

Elk uur telt. Schrijf ons nu.

Beschrijf kort het systeem, de PHP-versie en wat u opmerkt. Wij nemen contact op, brengen de situatie in kaart en werken op afstand tot het incident is afgerond en gedocumenteerd.

Directe hulp