WordPress-kehityksessä – ja web-kehityksessä ylipäätään – harva aihe synnyttää yhtä paljon hiljaista sekaannusta kuin sanitization ja escaping. Termit kuulostavat samankaltaisilta. Molemmat liittyvät turvallisuuteen. Molemmat käsittelevät dataa. Ja silti ne eivät ole sama asia, eivätkä ne ole vaihdettavissa keskenään.
Kyse ei ole semantiikasta tai terminologiasta. Kyse on koko sovelluksen turvallisuusmallista.
Sanitization ja escaping ovat kuin kaksi eri ajallista ulottuvuutta datan elämässä. Toinen tapahtuu ennen kuin data hyväksytään järjestelmään. Toinen tapahtuu juuri ennen kuin data päästetään ulos.
Ja juuri tämä ajallinen ero on kaiken ydin.
Data ei ole koskaan vain dataa
Kun käyttäjä syöttää tietoa WordPressiin, kyse ei ole vain tekstistä. Kyse ei ole vain lomakekentästä. Kyse on rajapinnasta järjestelmän ja ulkomaailman välillä.
Ulkoa tuleva data on lähtökohtaisesti epäluotettavaa.
Ei siksi, että käyttäjä olisi pahantahtoinen. Vaan siksi, että järjestelmä ei voi tehdä oletuksia. Turvallisuus ei perustu optimismiin.
Sanitization ja escaping ovat mekanismeja, joilla WordPress käsittelee tätä epistemologista ongelmaa: mitä voimme luottaa, ja milloin.
Sanitization: sisäänpääsyn vartija
Sanitization tapahtuu, kun data tulee järjestelmään.
Se kysyy:
“Mitä tämä data saa olla?”
Sanitization ei ole pelkkää haitallisen sisällön poistamista. Se on datan normalisointia. Muokkaamista. Siistimistä. Rajoittamista.
Kun käytät esimerkiksi sanitize_text_field()-funktiota, et vain “poista vaarallisia merkkejä”. Muotoilet datan vastaamaan odotettua rakennetta.
Sanitization määrittelee datan kelpoisuuden.
Sanitization on intentiokeskeinen
Sanitization perustuu oletukseen, että tiedämme, millaista dataa haluamme.
Esimerkiksi:
-
Tekstikenttä → vain tekstiä
-
Email → validi sähköpostiosoite
-
Numero → numero
Sanitization ei ole universaali suodatin. Se on kontekstisidonnainen muunnos.
Se ei kysy “onko tämä vaarallista?”, vaan “onko tämä sellaista dataa kuin odotamme?”.
Escaping: ulospääsyn turvaportti
Escaping tapahtuu, kun data lähtee järjestelmästä.
Se kysyy:
“Miten tämä data esitetään turvallisesti tässä kontekstissa?”
Escaping ei muuta datan merkitystä. Se muuttaa sen representaatioita.
Kun käytät esc_html()-funktiota, data ei muutu sisällöllisesti. Sen esitysmuoto muuttuu. Erikoismerkit muutetaan turvallisiksi HTML-entiteeteiksi.
Escaping suojaa renderöintiympäristöä.
Escaping on kontekstikeskeinen
Escaping riippuu siitä, missä data näytetään.
HTML-konteksti → esc_html()
Attribuuttikonteksti → esc_attr()
URL-konteksti → esc_url()
JavaScript-konteksti → esc_js()
Sama data tarvitsee eri escaping-logiikan riippuen ympäristöstä.
Escaping ei ole datan validointia. Se on ympäristön suojaamista.
Ajallinen ero: koko pelin ydin
Sanitization ja escaping eivät ole kilpailijoita. Ne toimivat eri hetkissä.
Sanitization → ennen tallennusta
Escaping → ennen outputia
Tämä ei ole mielipidekysymys. Tämä on turvallisuusarkkitehtuurin perusperiaate.
Ilman sanitizationia:
-
tietokantaan päätyy roskaa
-
data voi olla rakenteellisesti virheellistä
-
logiikka voi hajota
Ilman escapingia:
-
XSS-hyökkäykset mahdollisia
-
renderöintikonteksti rikkoontuu
-
käyttäjä näkee haitallista sisältöä
Toinen suojaa järjestelmää sisältäpäin. Toinen suojaa käyttöliittymää ulospäin.
Klassinen väärinkäsitys: “sanitoin kaiken tallennuksessa, olen turvassa”
Tämä on yksi yleisimmistä ajatusvirheistä.
Sanitization ei ole escaping.
Sanitoitu data voi silti olla vaarallista output-kontekstissa.
Esimerkiksi:
Käyttäjä syöttää tekstin, joka on täysin validia sisältöä, mutta sisältää HTML-merkkejä. Sanitization voi hyväksyä sen, koska data on rakenteellisesti kelvollista.
Ilman escapingia selain voi tulkita sisällön koodina.
Sanitization ei suojaa renderöintiä.
Toinen väärinkäsitys: “escapaan kaiken outputissa, sanitization turhaa”
Escaping ei ole datan validointia.
Ilman sanitizationia:
-
tietokantaan tallentuu odottamatonta dataa
-
logiikka voi rikkoontua
-
kyselyt voivat epäonnistua
-
suorituskyky voi kärsiä
Escaping ei tee datasta semanttisesti järkevää.
Se tekee siitä vain turvallisesti näytettävää.
Datan elinkaari: sisään, lepo, ulos
Ajattele dataa matkustajana.
Sanitization tarkistaa passin rajalla.
Escaping tarkistaa, ettei matkustaja kanna tulitikkurasiaa polttoainevarastoon.
Eri tarkastuspisteet. Eri riskit.
Data voi viettää tietokannassa vuosia. Sen käyttökonteksti voi muuttua. Output-ympäristö voi muuttua.
Escaping tapahtuu aina suhteessa nykyiseen kontekstiin.
XSS: miksi escaping on kriittinen
XSS (Cross-Site Scripting) ei ole datan tallennusongelma. Se on renderöintiongelma.
Selain ei tiedä:
-
mikä on dataa
-
mikä on koodia
Escaping tekee tämän erottelun eksplisiittiseksi.
Se sanoo selaimelle:
“Tämä on sisältöä, ei koodia.”
Sanitization ei ratkaise tätä ongelmaa.
SQL-injektio: miksi sanitization ei ole ratkaisu
Sanitization ei ole SQL-suojaus.
SQL-injektio estetään:
-
valmistelluilla kyselyillä
-
parametrien sitomisella
-
$wpdb->prepare()
Sanitization voi auttaa datan normalisoinnissa, mutta se ei ole turvallinen SQL-suojausstrategia.
Sanitization ei ole turvallisuuden hopealuoti.
Trust boundary: missä epäluotettavuus alkaa?
Turvallisuusarkkitehtuurissa keskeinen käsite on trust boundary.
Se on raja:
-
luotettavan
-
epäluotettavan
välillä.
Sanitization tapahtuu trust boundaryn ylityksessä.
Escaping tapahtuu trust boundaryn toisessa päässä, kun data kohtaa selaimen.
“Escape late” – WordPressin turvallisuusmantra
WordPress-kehityksessä toistuu periaate:
Escape late.
Escaping tehdään juuri ennen outputia.
Miksi?
Koska konteksti ratkaisee.
Data voi:
-
päätyä HTMLiin
-
päätyä attribuuttiin
-
päätyä JavaScriptiin
-
päätyä URLiin
Väärä escaping väärässä kontekstissa = haavoittuvuus.
Escaping ei ole kertatoimenpide.
Sanitization vs validation: hienovarainen ero
Sanitization ja validation eivät ole identtisiä.
Validation kysyy:
“Onko tämä arvo validi?”
Sanitization kysyy:
“Miten tämä arvo muokataan validiksi?”
Validation voi hylätä.
Sanitization voi korjata.
Usein ne toimivat yhdessä.
Defense-in-depth: miksi kerroksia tarvitaan
Turvallisuus ei ole yksi mekanismi. Se on kerroksia.
Sanitization → datan eheys
Escaping → renderöintiturvallisuus
Prepared statements → SQL-turvallisuus
Noncet → CSRF-suojaus
Capabilityt → käyttöoikeudet
Yksi kerros ei korvaa toista.
Turvallisuus on arkkitehtuuria, ei funktiokutsuja.
Psykologinen ansa: “turvallisuus = yksi ratkaisu”
Ihmismieli rakastaa yksinkertaisia selityksiä.
“Sanitoin → valmis.”
Web-turvallisuus ei toimi näin.
Riskit syntyvät eri vaiheissa:
-
input
-
tallennus
-
käsittely
-
output
Sanitization ja escaping suojaavat eri vaiheita.
Miksi tämä kaikki on niin helppo sotkea?
Koska molemmat käsittelevät dataa.
Koska molemmat liittyvät turvallisuuteen.
Koska molemmat “muuttavat jotain”.
Mutta niiden tarkoitus on täysin eri.
Sanitization → muokkaa dataa
Escaping → muokkaa esitystä
Sanitization → sisään
Escaping → ulos
Ajallinen ajattelu ratkaisee sekaannuksen.
Lopuksi: kyse ei ole funktioista, vaan ajattelumallista
Sanitization ja escaping eivät ole WordPress-spesifejä kikkoja. Ne ovat universaaleja turvallisuusperiaatteita.
Kun ymmärtää datan elinkaaren, trust boundaryt ja kontekstuaalisen renderöinnin, molemmat alkavat tuntua itsestäänselviltä.
Sanitization pitää järjestelmän loogisena.
Escaping pitää käyttöliittymän turvallisena.
Yksi ilman toista on puolustus, jossa on reikä.
Turvallinen WordPress ei ole “sanitoitu” tai “escapattu”.
Se on molempia.
Ja juuri oikeassa järjestyksessä.
