
← Tagasi blogisse
Kuidas XSS pääseb DOM-i, millised brauseri API-d on valamu, ja tootmises kehtivad leevendused - sanitisatsioon, CSP, küpsised ja CSRF paarimine.
Kui string tõlgendatakse markup või skriptina asemel inertse tekstina, siis see sisu käivitub kui kood teie lehe päritolus - samade õigustega kui teie pakett. See on XSS: mitte stiiliviga, segaduses volinik andmete ja juhiste vahel. See postitus on tehniline selgroog - rünnakumehaanika, valamu, skaleeruvad parandused, pluss käivitatav frontend-xss-demo (Vite + React main ; live: xss.lucascoliveira.com) ja viited sellele Next.js hoidlasse, kus päised ja MDX vähendavad vaikimisi riski.
Lehele sisestatud skriptid käivad koos samast päritolust kui teie pakett. Praktikas tähendab see sageli:
document.cookie nähtavus küpsiste jaoks, mida ei ole märgistatud HttpOnly (sessiooni vargus / fikseerimisahela);fetch() / XMLHttpRequest teie API-le ambitentidega , kui küpsised on saadetud ja CORS lubab seda - või tokenite salvestamine localStorage / sessionStorage , kui teie rakendus need sinna pani.Seega ei ole leevendus „kasuta Reactit” - see on mitte kunagi määrata ründaja kontrollitud baite valamusse, mis tõlgendab HTML-i või käivitab skripti, kui ülevaadatud torujuhe ei ole neid vähendanud turvalisele tüübile.
Salvestatud XSS - Usaldamata HTML (või kasutuskoormus, mis muutub HTML-iks pärast mallide laiendamist) on püsiv (DB, vahemälu, otsing indeks). Iga kasutaja, kes laadib selle kirje, tabab valamu. Esikülje mõju: esimene renderdus , mis teeb innerHTML = row.body või samaväärse ilma sanitisatsioonita, käivitab kasutuskoormuse.
Peegeldatud XSS - Kasutuskoormus ei püsi kunagi ; see põrkab serverist või marsruutimiskihist vastusesse. Klassika: ?q=<script>…</script> peegeldub HTML-i ilma kodeeringuta. SPA ekvivalent : location.search või räsi parsitud kliendi poolel ja kirjutatud DOM-i ilma kodeeringuta. Parandus on sama: kohtuvad stringid kui andmed ; kui peate neid peegeldama, kodeerige konteksti jaoks (vt allpool).
DOM-põhine XSS - Serveri vastus on „puhas”, kuid kliendi poolel skript loeb ründaja kontrollitud sisendit (location, referrer, postMessage, WebSocket sõnumid) ja edastab selle valamusse. Näide: eval("handle" + location.hash.slice(1)) või element.innerHTML = decodeURIComponent(...). Staatiline mallide analüüs ei piisa; peate auditeerima iga teed usaldamata sisendist valamusse.
Need on tavaliselt süüdlased React/SPA koodibaasides:
| Valamu | Risk |
|---|---|
element.innerHTML, insertAdjacentHTML | Parsib HTML-i; iga silt/sündmuste käitleja, mida lubate, võib käivitada skripti. |
dangerouslySetInnerHTML | Sama kui ülal - React ei sanitize. |
document.write | Sama. |
eval, new Function, setTimeout(string) | Otsene skripti käivitamine. |
javascript: URL-id href / src | Navigeerimine või ressursi laadimine, mis käivitub kui skript URL. |
postMessage käitlejad, mis eval või määravad HTML-i event.data põhjal | XSS, kui origin ei ole valideeritud või event.data jõuab valamusse ilma turvalise lepinguta - mitte ainult „vale aken” vead. |
Mitte valamu vaikimisi: textContent, createTextNode, Reacti tavaline tekstilaps, atribuudid, mida React käsitleb stringidena, kui te ei möödu tema põgenemisest. Markdown torujuhtmed muutuvad valamuteks, kui nad väljastavad toor-HTML-i ja määrate selle HTML-i DOM-ile ilma sanitisatsioonita.
Demo märkus (oluline): HTML5-s <script> sõlmed, mis on sisestatud innerHTML / dangerouslySetInnerHTML kaudu, ei käitu - parser ei käivita neid klassikalise peegeldatud XSS-i korral. Et näha käivitumist, kui HTML on sisestatud, kasutavad kasutuskoormused tavaliselt atribuutide käitlejaid (nt onerror on img) või sarnast. insecure-patterns dokument demo hoidlas selgitab seda välja, et saate rakendust testida näidetega, mis tegelikult käivituvad pärast sisestamist.
Kui UI vajab ainult lihtteksti - Siduge tekst textContent , Reacti tekstilapsed või MDX, mis kompileerub komponentideks ilma HTML-i torujuhtmeta. Sanitiseerijat ei nõuta; te ei ole HTML-i mängus.
Kui vajate rikast teksti (paks, loendid, lingid) - Teil on vaja kas piiratud märgistust, mis kompileerub turvalistele elementidele või HTML-i sanitisatsiooni lubatud nimekirjaga (sildid + atribuudid). Kodeering (nt HTML-entiteedi põgenemine) on andmete paigutamiseks HTML-tekstisõlmedesse ; sanitisatsioon on kui peate lubama HTML-i alamhulka. Ärge segi neid kahte.
Kaitse sügavus rikkaliku teksti jaoks reaalsetes toodetes - Valideerige/saniteerige kirjutamisel (API keeldub tundmatutest siltidest, pikkuse piirangutest) ja saniteerige või renderige turvalise tee kaudu lugemisel (renderduskiht). Salvestust saab tagasi võtta, rikkuda või kirjutada teise teenuse versiooni.
DOMPurify on brauseri sanitiseerija vaikimisi profiiliga; te konfigureerite selle oma toote jaoks:
ALLOWED_TAGS / ALLOWED_ATTR - Alustage minimaalselt (p, br, strong, em, a ainult href lubamisel). Iga lisa silt on rünnakupind.ADD_ATTR / FORBID_TAGS - Selge ületab „lubab peaaegu kõike”.RETURN_DOM / RETURN_TRUSTED_TYPE - Eelistage DOM-sõlmi või TrustedHTML-stiilis väljundit, kui integreerite Trusted Types-iga.afterSanitizeAttributes - Eemaldage href väärtused, mis algavad javascript: või veidrate data: MIME-tüüpidega, kui lubate linke.frontend-xss-demo main -s on turvaline marsruut (/secure) käitab todo teksti läbi DOMPurify enne dangerouslySetInnerHTML ; turvatu marsruut (/insecure**) ei tee seda - sama UI, erinev usalduspoliitika. Portugali /seguro ja /inseguro on endiselt olemas kui pärandi aliasid ja suunavad vastavalt /secure ja /insecure .
CSP vähendab mis võib käivituda, kui midagi libiseb läbi. Apps/web/next.config.ts selles saidis seab CSP-i default-src 'self' , range object-src 'none' , base-uri 'self' , form-action 'self' , frame-ancestors 'none' , pluss script-src / style-src koos 'unsafe-inline' , kuna Next.js App Router + MUI sx nõuavad praegu selles seadistuses sisemisi skripte/stiile - dokumenteeritud koodis. Nonce- või hash-põhine script-src eemaldaks laia sisemise skripti lubamise, kuid nõuab vahendvara nõuete süstimiseks.
Reaalsuse kontroll: CSP ei asenda sanitisatsiooni kasutaja HTML-i jaoks; see ** kitsendab** plahvatusraadiust (nt võib blokeerida skripti hostid, mida te ei lubanud). Sisemised sündmuste käitlejad (onerror jne) ei ole automaatselt neutraliseeritud ainult CSP-i tõttu - 'unsafe-inline' on script-src levinud reaalsetes rakendustes (sh selle saidi Next/MUI seadistus), ja blokeerivad käitlejad tavaliselt nõuavad selgesõnalist script-src / script-src-attr (või nonce/hashes), sõltuvalt brauserist ja CSP tasemest.
XSS võib mööda CSRF-märke , kui märk on lugemisvõimeline DOM-ist või kui ründaja skript teeb päringuid volitustega. Seega: eelistage XSS-i parandusi ; ka:
HttpOnly, Secure, SameSite=Lax või Strict , kus voogud lubavad - vähendab rist-site küpsiste lekkimist ja klassikalist CSRF-i.SameSite küpsistega, anti-CSRF märgistega või kohandatud päistega + CORS poliitikaga, et juhuslikud saidid ei saa saata nõudeid volitustega.Esikülje töö: ärge pange saladusi JS-lugemiseks salvestusse, kui vältida; kasutage fetch koos selgesõnalise credentials poliitikaga, mis on seotud teie API disainiga.
apps/web/next.config.ts: turvapäised /(.*) ; CSP string ehitatud koodis koos keskkonna-spetsiifilise script-src (dev unsafe-eval ainult React virnade jaoks, kus vaja).apps/web/app/api/chat/route.ts: JSON parsib, tühja kontroll, MAX_MESSAGE_LENGTH kork - kuritarvitamise kujundamine, mitte XSS ise.apps/web/lib/blog/mdx.tsx: MDX fikseeritud komponendi kaardiga (next-mdx-remote/rsc), mitte toor-HTML stringid CMS-ist. Erinev ohtude mudel kui „sõnumikeha koos HTML-iga”.main annabKloonige frontend-xss-demo, käitage npm install ja npm run dev → Vite serveerib rakendust http://localhost:5173.
/insecure koos kasutuskoormustega dokumentidest; sama voog /secure näitab saniteeritud väljundit.docs/xss/ all: ülevaade , kolm mõju jalutuskäiku (toimingud ilma kasutaja interaktsioonita, sisemine andmispüük, sessiooni kaaperdamine / salvestus), pluss turvatu mustrid ja turvalised mustrid kooditaseme do’s ja don’t’s jaoks.localStorage (vt 03-session-hijacking) , et näha, mida skript lehel lugeda saab; turvatu mustrid soovitab ka localStorage.getItem('auth_token') DevTools-is, et seda kontrollida.Võrrelge /insecure vs /secure Elements ja Console : samad komponendid, erinev stringi käsitlemine enne DOM-i jõudmist.
rg "dangerouslySetInnerHTML|innerHTML|insertAdjacentHTML|eval\\(|new Function" teie rakenduses ja sõltuvustes.<img src=x onerror=...>, javascript: URL-id - ja pidage meeles innerHTML ei käitu <script> , nagu paljud petulehed viitavad. innerHTML -stiili süstimisdemonstratsioonide jaoks eelistage onerror on img (või sarnast) ; <svg onload> on sageli ebakindel , kui seda sisestatakse sellisel viisil.SameSite, volitused ja CSRF strateegia koos backendiga; eeldage, et XSS ja CSRF saavad aheldatud.XSS on juhtimisvoog : andmed, mis ületavad tõlgendamist. Kaitse on tüpiseerimine piiril : lihttekst, turvalised struktureeritud komponendid või saniteeritud HTML minimaalse lubatud nimekirjaga - pluss CSP ja küpsiste semantika, mis piirab, mida hulkuv skript veel teha saab. Demo main -s muudab selle piiri nähtavaks: /insecure vs /secure, dokumenteeritud mõjud docs/xss/ all ja distsipliin igas PR-is, mis puudutab stringe lähedal DOM-ile.