# XSS-i vältimine PHP-s: Cross-Site-Scripting turvaliselt tõrjuda

> XSS-i vältimine PHP-s: kodeerige väljund konteksti järgi õigesti, kasutage automaatse põgenduse (auto-escaping) mallisüsteeme ja seadke Content Security Policy.

Allikas: https://phpsos.de/et/ratgeber/xss-php/  
Seis: 25.10.2026  
Pakkuja: PHP SOS, PHP hädaabi ja serveri turvalisus. Kohene abi WhatsAppis: https://wa.me/491736494914?text=Tere%2C%20PHP%20SOS%2C%20vajame%20abi%20oma%20PHP-serveriga.%20Ettev%C3%B5te%3A%20%E2%80%A6%20Veebisait%3A%20%E2%80%A6

**Lühidalt:** XSS-i PHP-s väldite, kodeerides iga väljundi vastavalt selle kontekstile: `htmlspecialchars()` HTML-i jaoks, `json_encode()` kaitsevalikutega JavaScripti jaoks, kontrollitud URL-id linkide jaoks. Automaatse põgenemisega mallid võtavad sellest suure osa teilt ära. Content Security Policy ja HttpOnly-küpsised piiravad kahju, kui mõni auk siiski alles jääb.

## Miks tuleks Cross-Site-Scripting praegu kaasa kontrollida

2026. aasta oktoobris on tähelepanu PHP2Shellil, kahel kriitilisel turvaaugul PHP interpretaatoris, mille paigad on saadaval alates 21.10.2026. Paljud ettevõtted lasevad sellega seoses oma veebirakendusi üle kontrollida. See on hea põhjus vaadata ka oma koodi nõrkusi, mida ükski PHP uuendus ei kõrvalda.

Cross-Site-Scripting ehk XSS on üks neist. OWASP Top 10 loetleb XSS-i kategoorias Injection. Erinevalt serveri turvaaugust on rünnak siin suunatud teie veebisaidi külastajate ja kasutajate vastu, näiteks poe klientide või halduse töötajate vastu.

Tagajärjed võivad olla tõsised: üle võetud administraatorite sessioonid, manipuleeritud vormid, mis saadavad andmeid kolmandatele, või võltsitud sisu teie veebisaidil. Kui administraatori konto üle võetakse, võib see viia rakenduse üle täieliku kontrollini.

## Kuidas XSS PHP rakendustes tekib?

XSS tekib, kui rakendus väljastab andmeid mitteusaldusväärsest allikast kontrollimata lehele. Brauser ei suuda siis enam eristada teie sisu ja sissetoodud koodi ning käivitab mõlemad.

Eristatakse kolme vormi. Peegeldatud XSS-i puhul pärineb sisu otse käimasolevast päringust, näiteks otsingusõnast URL-is. Salvestatud XSS-i puhul asub see andmebaasis, näiteks kommentaaris või profiiliväljal, ja tabab igaüht, kes lehe avab. DOM-põhine XSS tekib brauseri JavaScriptis, kui skriptid kirjutavad väärtusi URL-ist lehele.

Mitteusaldusväärsed on kõik andmed, mis ei ole koodis kindlalt kirjas: vormiväljad, URL-i parameetrid, küpsised, failinimed, väliste liideste vastused ja sisu oma andmebaasist, mis kunagi väljastpoolt tuli.

## Väljund kontekstile vastavalt õigesti kodeerida

Tähtsaim reegel on: kodeerige väljastamisel ja just selle koha järgi, kuhu väärtus satub. HTML-i sisu ja jutumärkides atribuutide jaoks on `htmlspecialchars()` õige vahend. Väike abifunktsioon takistab valikute unustamist:

```php
<?php
function e(?string $wert): string
{
    return htmlspecialchars($wert ?? '', ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
}
?>
<h2><?= e($produkt['name']) ?></h2>
<input type="text" name="suche" value="<?= e($_GET['q'] ?? '') ?>">
```

Teised kontekstid vajavad teisi vahendeid:

| Kontekst | Turvaline meetod |
|---|---|
| HTML-i sisu, jutumärkides atribuut | `htmlspecialchars()` valikuga `ENT_QUOTES` ja UTF-8 |
| Andmed JavaScripti jaoks | `json_encode()` valikutega `JSON_HEX_TAG`, `JSON_HEX_AMP`, `JSON_HEX_APOS`, `JSON_HEX_QUOT` |
| Parameeter URL-is | `rawurlencode()` üksiku väärtuse jaoks |
| Täielik URL kasutaja sisendist | skeem kontrollida, lubada ainult `https` ja `http`, seejärel `htmlspecialchars()` |
| Atribuudid ilma jutumärkideta, sündmuste käsitlejad, CSS | vältida, väärtusi sinna mitte paigutada |

Andmete jaoks, mida skript vajab, on andmeatribuut või JSON-plokk enamasti puhtaim tee:

```php
<?php
$daten = json_encode($konfiguration, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
?>
<div id="app" data-konfig="<?= e($daten) ?>"></div>
```

JavaScriptis loete väärtuse seejärel andmeatribuudi kaudu välja ja seate sisu käsuga `textContent`, mitte `innerHTML`.

## Mallid, HTML-i puhastamine ja raamistikud

Mallimootorid nagu Twig ja Blade kodeerivad väljundit vaikimisi automaatselt. See välistab suure osa tüüpilistest vigadest. Ohtlikuks muutub see seal, kus see käitumine teadlikult välja lülitatakse, näiteks Twigi filtriga `raw` või Blade'i süntaksiga `{!! !!}`. Selliseid kohti peaks koodis olema vähe ja neid tuleks igal ülevaatusel sihipäraselt kontrollida.

Kui teie rakendus peab teadlikult lubama kasutajate HTML-i, näiteks kommentaaride vormindust või toimetussüsteemis, kodeerimisest ei piisa, sest HTML tuleb ju kuvada. Siis on vaja kontrollitud puhastamise teeki nagu HTML Purifier, mis laseb läbi ainult lubatud elementide ja atribuutide kindla nimekirja. Oma regulaaravaldistega filtrid on kogemuse järgi lünklikud.

> **Oluline:**
> Kontrollige eriti halduspiirkondi. XSS vaadetes, mida näevad ainult administraatorid, alahinnatakse sageli, kuid tabab just kõige rohkem õigusi omavaid kontosid.

## XSS-i leidmine olemasolevas PHP koodis

Kasvanud rakendustes ei ole esimene küsimus enamasti see, kuidas õigesti kodeerida, vaid kus on seda seni unustatud. Pragmaatiline algus on otsida kohti, kus muutujaid väljastatakse otse:

```bash
# Päringuandmete otsene väljastamine
grep -rnE "(echo|print|<\?=)\s*\\\$_(GET|POST|REQUEST|COOKIE|SERVER)" src/ templates/ --include="*.php"
# Välja lülitatud automaatne põgenemine Twigis ja Blade'is
grep -rnE "\|raw|\{!!" templates/ resources/views/
```

Tabamused on kontrolliülesanded, mitte valmis leiud. Salvestatud XSS-i selline otsing leiab vaid osaliselt, sest väärtused tulevad seal andmebaasist. Kontrollige seetõttu lisaks kõiki vaateid, mis kuvavad kasutajate sisu: kommentaarid, profiilid, tellimusmärkmed, tugipiletid. Sisuhaldussüsteemide ja poodide puhul kuuluvad kolmandate osapoolte pluginad ja teemad sõnaselgelt juurde, sest seal asub suur osa väljundiloogikast.

## Teine kaitseliin: CSP ja turvalised küpsised

Ka hoolika koodi korral võib mõni koht märkamata jääda. Kaks meedet piiravad siis kahju. Content Security Policy lubab brauseril ainult kindlaksmääratud allikatest skripte ja keelab sisseehitatud skriptid, kui neid ei ole sõnaselgelt lubatud:

```apache
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
```

Võtke selline poliitika kasutusele järk-järgult, esmalt ainult aruandlusrežiimis päisega `Content-Security-Policy-Report-Only`, sest olemasolevaid analüüsi- või maksemeetodite integratsioone tuleb enamasti täiendada. Edasisi päiseid kirjeldab juhend [Turvapäised veebisaitidele](https://phpsos.de/et/ratgeber/sicherheits-header/).

Lisaks peaksid sessiooniküpsised kandma atribuuti `HttpOnly`, et skriptid neid välja lugeda ei saaks. Kuidas sessioone tervikuna turvata, on kirjas juhendis [Sessioonide turvamine PHP-s](https://phpsos.de/et/ratgeber/session-sicherheit-php/). Sugulasnõrkust andmebaasi poolel käsitleb [SQL-injektsiooni vältimine PHP-s](https://phpsos.de/et/ratgeber/sql-injection-php/).

## Kuidas PHP SOS konkreetselt aitab?

- Kontrollime teie rakenduse malle ja väljundeid puuduva või vale kodeerimise suhtes.
- Hindame leide kättesaadavuse ja mõjutatud kontode järgi ning näitame konkreetseid parandusi.
- Võtame Content Security Policy kasutusele järk-järgult, poe- või maksefunktsioone segamata.
- Testime pärast parandust uuesti ja dokumenteerime tulemuse.

Sõltumatut kontrolli kirjeldab teenus [Turvaaudit ja penetratsioonitest](https://phpsos.de/et/leistungen/sicherheitsaudit-penetrationstest/).


## Korduma kippuvad küsimused

**Kas htmlspecialchars piisab XSS-i vastu?**  
Tavalise teksti jaoks HTML-i sisus ja jutumärkides atribuutides jah, kui märgite ENT_QUOTES ja märgistiku UTF-8. JavaScriptis, URL-ides või CSS-is kehtivad teised reeglid, seal on vaja oma sobivat kodeerimist.

**Kas peaksin sisendit filtreerima salvestamisel või väljastamisel?**  
Kodeerige väljastamisel, sihtkohale vastavalt. Sisendi usutavust peaksite kontrollima vastuvõtul, näiteks pikkust ja vormingut. Kes filtreerib ainult salvestamisel, jätab märkamata andmed teistest allikatest ja raskendab hilisemat kasutamist teistes kontekstides.

**Mida annab Content Security Policy?**  
Content Security Policy määrab, millistest allikatest tohib brauser skripte laadida ja käivitada. See võib märkamata jäänud XSS-i turvaauku mõju oluliselt piirata, kuid ei asenda korrektset kodeerimist.

**Kuidas lubada kommentaarides vormindust nagu rasvane kiri või lingid?**  
Kasutage kontrollitud HTML-i puhastamise teeki, kus on lubatud elementide ja atribuutide lubatud nimekiri. Oma regulaaravaldised skriptide eemaldamiseks on veaaldid ja neid ei tohiks kasutada.

## Allikad

- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
- [php.net: turvateated](https://www.php.net/)
