# XSS megelőzése PHP-ban: a Cross-Site Scripting biztonságos kivédése

> XSS megelőzése PHP-ban: a kimenetek helyes kódolása környezetenként, automatikus escape-elésű sablonok és Content Security Policy beállítása. Példákkal.

Forrás: https://phpsos.de/hu/ratgeber/xss-php/  
Állapot: 2026. 10. 25.  
Szolgáltató: PHP SOS, PHP-vészhelyzeti segítség és szerverbiztonság. Azonnali segítség WhatsAppon: https://wa.me/491736494914?text=%C3%9Cdv%C3%B6zl%C3%B6m%2C%20PHP%20SOS%21%20Seg%C3%ADts%C3%A9gre%20van%20sz%C3%BCks%C3%A9g%C3%BCnk%20a%20PHP-szerver%C3%BCnkkel.%20C%C3%A9g%3A%20%E2%80%A6%20Weboldal%3A%20%E2%80%A6

**Röviden:** Az XSS-t PHP-ban úgy előzi meg, hogy minden kimenetet a környezetének megfelelően kódol: `htmlspecialchars()` a HTML-hez, `json_encode()` védelmi opciókkal a JavaScripthez, ellenőrzött URL-ek a linkekhez. Az automatikus escape-elésű sablonok ennek sokat levesznek a válláról. A Content Security Policy és a HttpOnly cookie-k korlátozzák a kárt arra az esetre, ha mégis marad rés.

## Miért érdemes most a Cross-Site Scriptinget is ellenőrizni

2026 októberében a figyelem a PHP2Shellre irányul, a PHP-értelmezőben lévő két kritikus résre, amelyekhez 2026. 10. 21. óta állnak rendelkezésre javítások. Sok vállalkozás ennek keretében ellenőrizteti a webalkalmazásait. Ez jó alkalom arra is, hogy megnézze a saját kódban lévő sebezhetőségeket, amelyeket nem old meg egyetlen PHP-frissítés sem.

A Cross-Site Scripting, röviden XSS, ezek egyike. Az OWASP Top 10 az XSS-t az Injection kategórián belül tartja számon. A szerveren lévő réstől eltérően itt a támadás a weboldala látogatói és felhasználói ellen irányul, például a webshop ügyfelei vagy az admin felület munkatársai ellen.

A következmények jelentősek lehetnek: átvett rendszergazdai munkamenetek, manipulált űrlapok, amelyek adatokat küldenek harmadik félnek, vagy hamisított tartalmak a weboldalán. Ha egy rendszergazdai fiókot átvesznek, az az alkalmazás feletti teljes uralomig vezethet.

## Hogyan keletkezik az XSS PHP-alkalmazásokban?

Az XSS akkor keletkezik, ha egy alkalmazás egy megbízhatatlan forrásból származó adatokat ellenőrzés nélkül ad ki egy oldalon. A böngésző ekkor már nem tud különbséget tenni az Ön tartalmai és a bejuttatott kód között, és mindkettőt végrehajtja.

Három formát különböztetnek meg. A reflektált XSS-nél a tartalom közvetlenül az aktuális kérésből származik, például az URL-ben lévő keresőkifejezésből. A tárolt XSS-nél az adatbázisban van, például egy hozzászólásban vagy profilmezőben, és mindenkit elér, aki az oldalt meghívja. A DOM-alapú XSS a böngésző JavaScriptjében keletkezik, amikor a szkriptek az URL-ből származó értékeket írnak az oldalba.

Megbízhatatlan minden adat, amely nem fixen áll a kódban: űrlapmezők, URL-paraméterek, cookie-k, fájlnevek, külső interfészek válaszai és a saját adatbázis tartalmai, amelyek valamikor kívülről érkeztek.

## A kimenet helyes kódolása környezetenként

A legfontosabb szabály: kódoljon a kimenetnél, és pedig ahhoz a helyhez illően, ahová az érték kerül. HTML-tartalomhoz és idézőjelek közötti attribútumokhoz a `htmlspecialchars()` a választandó eszköz. Egy kis segédfüggvény megakadályozza, hogy az opciók elfelejtődjenek:

```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'] ?? '') ?>">
```

Más környezetekhez más eszközök kellenek:

| Környezet | Biztonságos módszer |
|---|---|
| HTML-tartalom, idézőjelek közötti attribútum | `htmlspecialchars()` `ENT_QUOTES` kapcsolóval és UTF-8-cal |
| Adatok JavaScripthez | `json_encode()` a `JSON_HEX_TAG`, `JSON_HEX_AMP`, `JSON_HEX_APOS`, `JSON_HEX_QUOT` kapcsolókkal |
| Paraméter egy URL-ben | `rawurlencode()` az egyes értékre |
| Teljes URL felhasználói bevitelből | a séma ellenőrzése, csak `https` és `http` engedélyezése, majd `htmlspecialchars()` |
| Idézőjel nélküli attribútumok, eseménykezelők, CSS | kerülje, ott ne illesszen be értékeket |

Egy szkript által igényelt adatokhoz többnyire egy adatattribútum vagy egy JSON-blokk a legtisztább út:

```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>
```

A JavaScriptben az értéket ezután az adatattribútumon keresztül olvassa ki, a tartalmakat pedig `textContent`-tel, nem `innerHTML`-lel állítsa be.

## Sablonok, HTML-tisztítás és keretrendszerek

Az olyan sablonmotorok, mint a Twig és a Blade, alapértelmezetten automatikusan kódolják a kimeneteket. Ez a tipikus hibák nagy részét kizárja. Veszélyessé ott válik, ahol ezt a viselkedést tudatosan kikapcsolják, például a Twigben a `raw` szűrővel vagy a Bladében a `{!! !!}` szintaxissal. Az ilyen helyeknek ritkáknak kell lenniük a kódban, és minden review-nál célzottan ellenőrizni kell őket.

Ha az alkalmazása tudatosan engedi a felhasználók HTML-jét, például formázásokat a hozzászólásokban vagy egy szerkesztőségi rendszerben, a kódolás nem elég, mert a HTML-t ugyanis meg kell jeleníteni. Ekkor ellenőrzött tisztító könyvtárra van szükség, például a HTML Purifierre, amely csak az engedélyezett elemek és attribútumok rögzített listáját engedi át. A reguláris kifejezésekkel készült saját szűrők tapasztalat szerint hiányosak.

> **Fontos:**
> Különösen az admin területeket ellenőrizze. Az XSS-t azokban a nézetekben, amelyeket csak rendszergazdák látnak, gyakran alábecsülik, pedig éppen a legtöbb joggal rendelkező fiókokat éri.

## XSS keresése a meglévő PHP-kódban

A kialakult alkalmazásokban az első kérdés többnyire nem az, hogyan kell helyesen kódolni, hanem hogy hol felejtették el eddig. Pragmatikus kezdet azoknak a helyeknek a keresése, ahol a változókat közvetlenül adják ki:

```bash
# Kérésadatok közvetlen kiadása
grep -rnE "(echo|print|<\?=)\s*\\\$_(GET|POST|REQUEST|COOKIE|SERVER)" src/ templates/ --include="*.php"
# Kikapcsolt automatikus escape-elés Twigben és Bladében
grep -rnE "\|raw|\{!!" templates/ resources/views/
```

A találatok vizsgálati feladatok, nem kész megállapítások. A tárolt XSS-t egy ilyen keresés csak korlátozottan találja meg, mert az értékek ott az adatbázisból jönnek. Ezért ellenőrizzen ezen felül minden olyan nézetet, amely felhasználók tartalmait jeleníti meg: hozzászólások, profilok, rendelési megjegyzések, támogatási jegyek. CMS-eknél és webshopoknál a harmadik felek bővítményei és témái kifejezetten idetartoznak, mert a kimeneti logika nagy része ott van.

## Második védvonal: CSP és biztonságos cookie-k

Gondos kód mellett is előfordulhat, hogy egy helyet átnéznek. Két intézkedés ekkor korlátozza a kárt. A Content Security Policy csak meghatározott forrásokból engedélyez szkripteket a böngészőnek, és tiltja a beágyazott szkripteket, amennyiben nincsenek kifejezetten engedélyezve:

```apache
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
```

Egy ilyen irányelvet fokozatosan vezessen be, először tisztán jelentési módban a `Content-Security-Policy-Report-Only` fejlécen keresztül, mert az elemző vagy fizetési szolgáltatások meglévő beágyazásait többnyire ki kell egészíteni. További fejléceket a [Biztonsági fejlécek weboldalakhoz](https://phpsos.de/hu/ratgeber/sicherheits-header/) útmutató ír le.

Emellett a munkamenet-cookie-knak viselniük kell a `HttpOnly` attribútumot, hogy a szkriptek ne tudják kiolvasni őket. Hogyan védheti a munkameneteket egészében, azt a [Munkamenetek védelme PHP-ban](https://phpsos.de/hu/ratgeber/session-sicherheit-php/) útmutató írja le. Egy rokon, az adatbázis oldalán lévő sebezhetőséggel az [SQL-injection megelőzése PHP-ban](https://phpsos.de/hu/ratgeber/sql-injection-php/) foglalkozik.

## Hogyan segít konkrétan a PHP SOS?

- Ellenőrizzük az alkalmazása sablonjait és kimeneteit hiányzó vagy hibás kódolás szempontjából.
- A leleteket az elérhetőség és az érintett fiókok szerint értékeljük, és konkrét javításokat mutatunk.
- Fokozatosan bevezetünk egy Content Security Policyt, a webshop- vagy fizetési funkciók zavarása nélkül.
- A javítás után újra tesztelünk, és dokumentáljuk az eredményt.

Egy független ellenőrzést a [Biztonsági audit és penetrációs teszt](https://phpsos.de/hu/leistungen/sicherheitsaudit-penetrationstest/) szolgáltatás ír le.


## Gyakori kérdések

**Elég a htmlspecialchars az XSS ellen?**  
Normál szövegre a HTML-tartalomban és idézőjelek közötti attribútumokban igen, ha megadja az ENT_QUOTES kapcsolót és az UTF-8 karakterkészletet. JavaScriptben, URL-ekben vagy CSS-ben más szabályok érvényesek, ott saját, megfelelő kódolásra van szükség.

**A bemeneteket tároláskor vagy kimenetkor szűrjem?**  
Kódoljon a kimenetnél, a célnak megfelelően. A bemeneteket fogadáskor a hihetőségükre ellenőrizze, például a hosszra és a formátumra. Aki csak tároláskor szűr, figyelmen kívül hagyja a más forrásokból származó adatokat, és megnehezíti a későbbi felhasználást más környezetekben.

**Mit ad egy Content Security Policy?**  
A Content Security Policy meghatározza, mely forrásokból tölthet be és futtathat szkripteket a böngésző. Egy figyelmen kívül hagyott XSS-rés hatásait jelentősen korlátozhatja, de a helyes kódolást nem pótolja.

**Hogyan engedélyezzem a formázásokat, például a félkövért vagy a linkeket a hozzászólásokban?**  
Használjon ellenőrzött HTML-tisztító könyvtárat az engedélyezett elemek és attribútumok engedélylistájával. A szkriptek eltávolítására szolgáló saját reguláris kifejezések hibára hajlamosak, és nem szabad használni őket.

## Források

- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/)
- [php.net: biztonsági közlemények](https://www.php.net/)
