WordPress ja XSS-hyökkäykset kokonaisuutena
Cross-Site Scripting eli XSS on WordPress-ympäristöissä yksi yleisimmistä ja samalla aliarvioiduimmista haavoittuvuuksista. Se ei vaadi palvelimen kaappaamista, eikä edes kirjautumista järjestelmään. Riittää, että hyökkääjä saa haitallista JavaScriptiä suoritetuksi käyttäjän selaimessa. Ja WordPressissä siihen on lukemattomia reittejä, jos escaping tehdään väärin.
XSS ei ole yksittäinen bugi. Se on seuraus väärästä ajattelumallista.
Mikä XSS oikeasti on
XSS-hyökkäyksessä:
-
haitallinen koodi tallennetaan tai välitetään
-
se päätyy osaksi HTML-sivua
-
selain suorittaa sen luottamuksella
WordPress ei “aja JavaScriptiä vahingossa”. Selain ajaa sen, koska WordPress käski.
Siksi XSS on aina output-ongelma, ei input-ongelma.
Tallennettu vs. heijastettu XSS
Stored XSS
Tallennettu XSS syntyy, kun:
-
haitallinen sisältö tallennetaan tietokantaan
-
se renderöidään myöhemmin sivulle
-
jokainen sivun avaaja altistuu
WordPressissä tyypillisiä paikkoja:
-
post content
-
post meta
-
user meta
-
options-taulu
Yksi väärin escapattu kenttä voi altistaa koko sivuston.
Reflected XSS
Heijastettu XSS syntyy, kun:
-
URL-parametriä tulostetaan suoraan
-
lomakedataa ei escapata
-
virheilmoitus näyttää syötteen sellaisenaan
Nämä ovat usein lyhytikäisempiä, mutta helpompia hyväksikäyttää.
Escaping ei ole sama asia kuin sanitointi
Yleisin väärinkäsitys
Moni ajattelee:
“Sanitoin inputin, joten olen turvassa.”
Tämä ei pidä paikkaansa.
Sanitointi:
-
tehdään tallennusvaiheessa
-
muokkaa dataa yleiskäyttöön
Escaping:
-
tehdään tulostusvaiheessa
-
riippuu kontekstista
XSS torjutaan escapella, ei sanitoinnilla.
Kontekstisidonnainen escaping
HTML ei ole yksi konteksti
Escaping riippuu siitä, mihin data menee:
-
HTML-elementin sisältö
-
HTML-attribuutti
-
JavaScript
-
URL
-
CSS
Sama arvo vaatii eri escapauksen eri konteksteissa. Yksi funktio ei riitä kaikkeen.
WordPress tarjoaa tähän täsmälliset työkalut. Niitä pitää käyttää oikein.
WordPressin escaping-funktiot
Miksi omat ratkaisut ovat riski
WordPressin core:
-
tuntee omat kontekstinsa
-
kehittyy turvallisuus edellä
-
paikkaa edge-caset
Kun kehittäjä:
-
käyttää
htmlspecialchars()summittaisesti -
rakentaa omia helper-funktioita
-
sekoittaa sanitoinnin ja escapauksen
riskit kasvavat nopeasti.
Core-funktiot eivät ole koristeita. Ne ovat turvamekanismeja.
Admin ei ole turvallinen vyöhyke
Yleinen ja vaarallinen oletus
“Adminissa käyttäjät ovat luotettavia.”
Eivät ole.
Admin-XSS:
-
mahdollistaa käyttäjätilien kaappauksen
-
voi johtaa privilege escalationiin
-
leviää lisäosiin ja asetuksiin
Yksi XSS adminissa on usein koko sivuston kompromissi.
XSS ja lisäosat
Suurin hyökkäyspinta
Suurin osa WordPressin XSS-haavoittuvuuksista syntyy:
-
lisäosissa
-
custom-teemoissa
-
projektikohtaisessa koodissa
Yleisiä virheitä:
-
asetusten tulostus ilman escapeta
-
AJAX-vastaukset ilman kontekstia
-
REST API:n datan suora renderöinti
XSS ei ole core-ongelma. Se on ekosysteemihaaste.
REST API ja XSS
JSON ei poista ongelmaa
REST API:
-
palauttaa dataa, ei HTML:ää
-
mutta frontend renderöi sen
Jos frontend:
-
luottaa sokeasti API-dataan
-
käyttää innerHTML-ratkaisuja
-
ei escapaa renderöintivaiheessa
XSS syntyy yhtä helposti kuin perinteisessä PHP-renderöinnissä.
Headless ei tee WordPressistä automaattisesti turvallisempaa.
Escaping ja suorituskyky
Turvallisuus ei ole hidas
Escaping:
-
on kevyt operaatio
-
ei ole suorituskykypullonkaula
-
maksaa murto-osia millisekunnista
XSS:n korjaaminen jälkikäteen maksaa:
-
aikaa
-
rahaa
-
luottamusta
Suorituskyky ei ole hyväksyttävä syy ohittaa escapeta.
Yleisimmät XSS-virheet WordPressissä
Tyypillisimpiä virheitä ovat:
-
datan tulostus ilman escapeta
-
väärä escaping väärässä kontekstissa
-
admin-näkymien luottaminen
-
REST-vastauksien suora renderöinti
-
“tämä kenttä on turvallinen” -oletus
XSS ei synny yhdestä suuresta virheestä, vaan kymmenestä pienestä.
Milloin escaping on tehty oikein
Hyvin suojatussa WordPressissä:
-
kaikki output escapataan
-
konteksti on aina tiedossa
-
sanitointi ja escaping on erotettu
-
admin ja frontend käsitellään yhtä tarkasti
Usein paras merkki onnistumisesta on se, että XSS ei tule mieleen päivittäisessä työssä, koska se on oletuksena hallinnassa.
Lopuksi: XSS on WordPress-kehittäjän vastuulla
WordPress ei voi arvata, missä kontekstissa dataa käytetään. Siksi escaping on kehittäjän tehtävä.
Kun escaping tehdään oikein:
-
hyökkäyspinta pienenee dramaattisesti
-
lisäosat kestävät auditointeja
-
sivusto pysyy luotettavana
XSS ei ole monimutkainen ongelma. Se on kurinalaisuusongelma. Ja WordPressissä kurinalaisuus ratkaisee enemmän kuin yksikään turvalisäosa.
