# PHP:n sisäänrakennetut tietoturvafunktiot

> PHP:n tietoturvafunktiot yleiskatsauksena: salasanat, satunnaisuus, maskaus, kryptografia ja istunnot sekä niiden rajat PHP2Shellin kaltaisissa aukoissa.

Lähde: https://phpsos.de/fi/php/eingebaute-sicherheitsfunktionen/  
Tilanne: 25.10.2026  
Palveluntarjoaja: PHP SOS, PHP-hätäapu ja palvelimen tietoturva. Pikaapu WhatsAppilla: https://wa.me/491736494914?text=Hei%20PHP%20SOS%2C%20tarvitsemme%20apua%20PHP-palvelimemme%20kanssa.%20Yritys%3A%20%E2%80%A6%20Verkkosivusto%3A%20%E2%80%A6

**Lyhyesti:** PHP tarjoaa yleisimpiin tietoturvatehtäviin valmiita, tarkastettuja funktioita: `password_hash()` salasanoille, `random_bytes()` ja `random_int()` tunnisteille, `htmlspecialchars()` cross-site scriptingiä vastaan, PDO:n valmistellut kyselyt SQL-injektiota vastaan, `hash_equals()` turvallisiin vertailuihin ja Sodium-laajennus kryptografiaan. Näitä rakennuspalikoita johdonmukaisesti käyttämällä vältetään suurin osa sovellusaukoista. PHP-tulkin omia virheitä, kuten PHP2Shelliä, ne eivät torju; siihen auttaa vain päivitys.

## Miksi PHP:n sisäänrakennetut tietoturvafunktiot?

Tietoturvakoodin kirjoittaminen itse on virhealtista. Oma salasanatiiviste, itse rakennettu tunnistegeneraattori tai itse väsätty HTML-tulosteiden suodatin näyttävät usein oikeilta mutta eivät ole sitä. Sisäänrakennetut funktiot on dokumentoitu, testattu, ja niitä ylläpidetään PHP-päivityksissä.

Päättäjälle tämä tarkoittaa: älkää kysykö toimistoltanne tai kehitystiimiltänne, onko tietoturvafunktioita rakennettu itse, vaan sitä, käytetäänkö kielen vakiofunktioita. Taulukko antaa yleiskuvan.

| Tehtävä | Funktio | Saatavilla alkaen | Tärkeä huomautus |
|---|---|---|---|
| Salasanojen tallennus | `password_hash()`, `password_verify()` | PHP 5.5 | Sarake jopa 255 merkkiä; bcrypt typistää 72 tavuun |
| Satunnaiset tunnisteet | `random_bytes()`, `random_int()` | PHP 7.0 | älä koskaan `rand()` tai `mt_rand()` salaisuuksille |
| Satunnaisuus olio-orientoituneesti | `Random\Randomizer` | PHP 8.2 | sama turvallisuus, joustavampi rajapinta |
| HTML-tulosteen maskaus | `htmlspecialchars()` | aina | Oletuslipuilla versiosta 8.1 lähtien maskataan myös yksinkertaiset lainausmerkit |
| Ajallisesti vakio vertailu | `hash_equals()` | PHP 5.6 | Käyttäjän syöte toisena argumenttina |
| Moderni kryptografia | Sodium (`sodium_*`) | PHP 7.2 | oman salauksen sijaan |
| Salaisuudet pinojäljissä | `#[\SensitiveParameter]` | PHP 8.2 | arvo ei näy jäljessä |
| Syötteiden tarkistus | `filter_var()` | PHP 5.2 | tarkistaa muodon, ei korvaa maskausta |

## Salasanat ja tunnisteet

`password_hash()` tuottaa suolatun tiivisteen, `password_verify()` tarkistaa sen. Vakiolla `PASSWORD_DEFAULT` PHP käyttää tällä hetkellä bcryptiä; versiosta PHP 8.4 lähtien oletusarvoinen kustannuskerroin on käsikirjan mukaan 12 eikä 10. Koska oletusalgoritmi voi muuttua, käsikirja suosittelee 255 merkin tietokantasaraketta. Bcryptissä salasanat katkaistaan 72 tavun kohdalla, mikä on otettava huomioon hyvin pitkien salalauseiden kohdalla.

```php
<?php
// Rekisteröityminen
$hash = password_hash($passwort, PASSWORD_DEFAULT);

// Kirjautuminen, mukaan lukien vanhojen tiivisteiden automaattinen päivitys
if (password_verify($eingabe, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($eingabe, PASSWORD_DEFAULT); // tallenna uudelleen
    }
}

// Tunniste salasanan palautuslinkkiä varten
$token = bin2hex(random_bytes(32));
```

Salaisuuksien, kuten allekirjoituksen, vertailuun kuuluu käyttää funktiota `hash_equals()`. Tavallinen vertailu operaattorilla `===` voi käsikirjan mukaan paljastaa suoritusajalla, mistä kohdasta kaksi arvoa eroavat. Tarkemmin: [Salasanojen turvallinen tallennus PHP:ssä](https://phpsos.de/fi/blog/passwoerter-in-php-speichern/) ja [turvalliset satunnaisluvut ja tunnisteet](https://phpsos.de/fi/blog/sichere-tokens-php/).

## Tulosteiden maskaus ja tietokannan turvallinen kysely

Cross-site scripting syntyy, kun käyttäjän syötteet päätyvät suodattamattomina HTML:ään. `htmlspecialchars()` muuntaa erikoismerkit HTML-entiteeteiksi. Versiosta PHP 8.1 lähtien oletuslippuina ovat `ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401`; aiemmin yksinkertaisia lainausmerkkejä ei muunnettu. Jos on tuettava vanhempia versioita, liput ilmoitetaan nimenomaisesti.

SQL-injektion estävät valmistellut kyselyt. Arvot välitetään erillään SQL-tekstistä, eivätkä ne voi muuttaa kyselyä:

```php
<?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');
```

Yksityiskohdat ovat sivulla [Cross-site scriptingin estäminen PHP:ssä](https://phpsos.de/fi/ratgeber/xss-php/) ja SQL-injektiota käsittelevällä sivulla.

Syötteiden tarkistus on toinen, erillinen vaihe. `filter_var()` toteaa, onko arvolla kelvollinen muoto, esimerkiksi sähköpostiosoite tai kokonaisluku sallitulla alueella. Se ei kuitenkaan korvaa tulosteen maskausta eikä valmisteltua kyselyä, sillä muodollisesti kelvollisetkin arvot voivat sisältää erikoismerkkejä.

## Salaisuudet pois virheilmoituksista

Aliarvioitu tietovuoto ovat pinojäljet. Kun funktiossa tapahtuu virhe, PHP kirjaa kutsuketjun argumentteineen. Jos siinä on salasana tai API-avain, se päätyy lokiin. Versiosta PHP 8.2 lähtien attribuutti `#[\SensitiveParameter]` merkitsee tällaiset parametrit; niiden arvo näkyy jäljessä silloin vain oliona `SensitiveParameterValue`.

```php
<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
    // ... tarkistus ...
    throw new RuntimeException('Datenbank nicht erreichbar');
}
```

Käsikirjan huomautuksen mukaan attribuutti vaikuttaa vain konkreettiseen toteutukseen, ei rajapinnan metodiin. Asettakaa se siksi siihen, missä koodi todella suoritetaan.

## Istunnot: turvalliset asetukset ja uudet oletukset

Istunnot ovat yleinen hyökkäyskohde. Kolme asetusta on keskeistä: `session.use_strict_mode=1` hylkää istuntotunnisteet, joita palvelin ei ole itse luonut; `session.cookie_httponly=1` estää JavaScript-pääsyn istuntoevästeeseen; `session.cookie_samesite=Lax` vaikeuttaa mukana lähettämistä vierailla sivuilla. Hyväksytyn RFC:n mukaan juuri nämä kolme arvoa tulevat oletuksiksi versiossa PHP 8.6. Asettakaa ne siihen asti itse, ja myös sen jälkeen nimenomaisesti, jotta konfiguraatio ei riipu oletuksesta.

```ini
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.cookie_secure = 1
```

Lisää kohdassa [Istuntojen suojaaminen PHP:ssä](https://phpsos.de/fi/ratgeber/session-sicherheit-php/).

## Mitä sisäänrakennetut funktiot eivät tee

PHP-hanke on tietoturvakäytännössään selkeä: PHP ei ole hiekkalaatikko. `open_basedir`- tai `disable_functions`-asetusten kiertäminen, `unserialize()`-funktiolle annetut pahantahtoiset syötteet ja tarkistamattomat argumentit funktioille kuten `mysqli_query()` eivät ole PHP:n tietoturva-aukkoja. Ylläpitäjälle se tarkoittaa: nämä asetukset ovat hyödyllistä koventamista mutta eivät tietoturvarajoja, eikä `unserialize()`-funktiolla ole vieraan datan kanssa mitään tekemistä.

Toinen seikka koskee PHP2Shelliä. Haavoittuvuudet CVE-2026-109618 ja CVE-2026-109619 mahdollistavat php.netin mukaan koodin suorituksen ennen sovelluksenne ajoa tai sen aikana; mod_php:ssä on esitetty hyökkäys, joka toimii ennen kuin sovelluskoodia ylipäätään suoritetaan. Mikään koodinne funktio ei voi pysäyttää sitä. Turvallinen ohjelmointi ja ajantasainen PHP-versio ovat kaksi erillistä velvoitetta, ja molemmat on täytettävä.

## Miten PHP SOS auttaa konkreettisesti?

[PHP-sovellusten tietoturvatarkastuksessa](https://phpsos.de/fi/leistungen/sicherheitsaudit-penetrationstest/) tarkistamme kohdennetusti:

- **Salasanojen ja tunnisteiden käsittely:** Käytetäänkö funktioita `password_hash()` ja `random_bytes()` vai onko olemassa omia rakennelmia?
- **Tulosteet ja kyselyt:** Missä syötteet päätyvät suodattamattomina HTML:ään, SQL:ään tai komentorivikäskyihin?
- **Istuntokonfiguraatio:** Onko Strict Mode, HttpOnly, SameSite ja Secure asetettu, eikä niitä voi ylikirjoittaa?
- **Ajoympäristö:** Onko käytössä tuettu PHP-versio 21.10.2026 julkaistuine korjauksineen?


## Usein kysytyt kysymykset

**Miten salasanat tallennetaan PHP:ssä oikein?**  
Funktiolla password_hash() ja vakiolla PASSWORD_DEFAULT, tarkistus tehdään funktiolla password_verify(). Tietokantasarakkeeseen pitäisi käsikirjan mukaan mahtua jopa 255 merkkiä, koska oletusalgoritmi voi muuttua tulevaisuudessa.

**Sopiiko rand() tunnisteisiin?**  
Ei sovi. Tunnisteisiin, avaimiin ja salasanan palautuslinkkeihin kuuluu käyttää funktioita random_bytes() tai random_int(). Käsikirjan mukaan ne tuottavat kryptografisesti turvallisia satunnaisarvoja.

**Mistä lähtien Sodium on osa PHP:tä?**  
Modernin kryptografian Sodium-laajennus on ollut osa PHP:tä versiosta PHP 7.2.0 lähtien. Vanhempiin versioihin sen sai asennettua vain PECL:n kautta.

**Suojaavatko nämä funktiot PHP2Shellilta?**  
Eivät suojaa. Ne suojaavat sovelluksenne virheiltä. PHP2Shell on itse tulkissa, ja se suljetaan vain PHP-päivityksellä, jota seuraa kaikkien PHP-prosessien uudelleenkäynnistys.

**Muuttuvatko istuntojen oletusarvot PHP 8.6:ssa?**  
Kyllä, hyväksytyn RFC:n mukaan session.use_strict_mode ja session.cookie_httponly kytketään oletuksena päälle ja session.cookie_samesite asetetaan arvoon Lax. Nykyiset konfiguraatiot kannattaa silti asettaa itse nimenomaisesti.

## Lähteet

- [PHP-käsikirja: password_hash()](https://www.php.net/manual/en/function.password-hash.php)
- [PHP-käsikirja: random_bytes()](https://www.php.net/manual/en/function.random-bytes.php)
- [PHP-käsikirja: hash_equals()](https://www.php.net/manual/en/function.hash-equals.php)
- [PHP RFC: Secure Session Configuration Defaults](https://wiki.php.net/rfc/session_security_defaults)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
