Esikülje turvalisus: XSS, usalduspiirid ja demo, mida saate käivitada

← Tagasi blogisse

20. aprill 20266 min lugemine

Esikülje turvalisus: XSS, usalduspiirid ja demo, mida saate käivitada

Kuidas XSS pääseb DOM-i, millised brauseri API-d on valamu, ja tootmises kehtivad leevendused - sanitisatsioon, CSP, küpsised ja CSRF paarimine.

turvalisusesikülgreact

Kui string tõlgendatakse markup või skriptina asemel inertse tekstina, siis see sisu käivitub kui kood teie lehe päritolus - samad privileegid kui teie paketti. See on XSS: mitte stiiliviga, segaduses volinik andmete ja juhiste vahel. See postitus on tehniline selgroog - rünnakumehaanika, valamu, skaleeruvad parandused, pluss käivitatav mänguväljak (Vite + React main; live: playgrounds.lucascoliveira.com) ja viited sellele Next.js hoidlasse, kus päised ja MDX vähendavad vaikimisi riski.

Sama päritolu: mida ründaja tegelikult võidab

Lehele sisestatud skriptid käivad koos samadega päritoluga 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 ambitsiooniliste volitustega, kui küpsised on saadetud ja CORS lubab seda - või tokenite väljavõtmine, mis on salvestatud localStorage / sessionStorage-s, kui teie rakendus need sinna pani.
  • DOM lugemised mittevajalikust PII-st, mis on lehel kuvatud, ja UI ümbersuunamine (võltsvormid, ülekatte) andmispüügi jaoks rakenduse aknas.

Seega ei ole leevendus "kasuta Reactit" - see on mitte kunagi ründaja kontrollitud baitide määramine valamusse, mis tõlgendab HTML-i või käivitab skripti, kui ülevaadatud torujuhe ei ole neid vähendanud turvalisele tüübile.

Salvestatud, peegeldatud ja DOM-põhine XSS (mehaanika)

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 on klient-poolselt tõlgendatud ja kirjutatud DOM-i ilma kodeeringuta. Parandus on sama: kohelda URL-ist pärit stringe kui andmeid; kui peate neid peegeldama, kodeerige konteksti jaoks (vt allpool).

DOM-põhine XSS - Serveri vastus on "puhas", kuid klient-poolsed skriptid loevad ründaja kontrollitud sisendit (location, referrer, postMessage, WebSocket sõnumid) ja edastavad 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.

Valamu: API-d, mis muudavad stringid käivitamiseks või HTML-iks

Need on tavalised süüdlased React/SPA koodibaasides:

ValamuRisk
element.innerHTML, insertAdjacentHTMLParsib HTML-i; iga silt/sündmuse käitleja, mida lubate, võib käivitada skripti.
dangerouslySetInnerHTMLSama mis eespool - React ei sanitize.
document.writeSama.
eval, new Function, setTimeout(string)Otsene skripti käivitamine.
javascript: URL-id href / srcNavigeerimine või ressursi laadimine, mis käivitub skripti URL-ina.
postMessage käitlejad, mis eval või määravad HTML-i event.data-stXSS, 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 laps tekst, atribuudid, mida React käsitleb stringidena, kui te ei kõrvalda selle ümbersõnastamist. Markdown torujuhtmed muutuvad valamuteks, kui nad väljastavad toor-HTML-i ja määrate selle HTML-i DOM-i 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äidata käivitumist, kui HTML on sisestatud, kasutavad kasutuskoormused tavaliselt atribuutide käitlejaid (nt onerror on img) või sarnast. XSS mänguväljak hoiab kasutuskoormused eelseatud (vt payloadPresets.ts), et saate testida juhtumeid, mis tegelikult käivituvad pärast sisestamist.

Leevendus 1: kontekstikohane kodeering vs sanitisatsioon

  • Kui UI vajab ainult lihtteksti - Siduge tekst textContent-ga, Reacti tekstilaste või MDX-iga, mis kompileerub komponentideks ilma HTML-i torujuhtmeta. Sanitisatsiooni pole vaja; te ei ole HTML-i mängus.

  • Kui vajate rikast teksti (paks, loendid, lingid) - Teil on vaja kas piiratud märgistuskeelt, mis on kompileeritud turvalisteks elementideks või HTML-i sanitisatsiooni koos lubatud nimekirjaga (sildid + atribuudid). Kodeering (nt HTML-entiteetide 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, pikkusepiirangutest) ja saniteerige või renderige läbi turvalise tee lugemisel (renderduskiht). Salvestus saab tagasi pöörata, rikutud või kirjutatud teise teenuse versiooni poolt.

Leevendus 2: DOMPurify (ja kuidas seda tõsiselt kasutada)

DOMPurify on brauseri sanitisatsioon vaikimisi profiiliga; te konfigureerite selle oma toote jaoks:

  • ALLOWED_TAGS / ALLOWED_ATTR - Alustage minimaalselt (p, br, strong, em, a ainult siis, kui vajate linke). 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.
  • Konkureerige afterSanitizeAttributes - Eemaldage href väärtused, mis algavad javascript:-st või veidratest data: MIME tüüpidest, kui lubate linke.

Mänguväljakus main-s võrdleb XSS mänguväljak turvamata renderdus tee turvatud teega (DOMPurify lubatud nimekiri) - sama UI, erinev usalduspoliitika.

Leevendus 3: Content-Security-Policy (piirangud, mitte asendus)

CSP vähendab mis võib käivituda, kui midagi libiseb läbi. Apps/web/next.config.ts-s määrab see sait 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 inline skripti/stiili - dokumenteeritud koodis. Nonce- või hash-põhine script-src eemaldaks laia inline 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). Inline sündmuse käitlejad (onerror jne) ei ole automaatselt neutraliseeritud, kui määrate CSP-i - 'unsafe-inline' on script-src-s tavaline reaalses rakenduses (sh selle saidi Next/MUI seadistus), ja blokeerivad käitlejad tavaliselt nõuavad selgesõnalist script-src / script-src-attr (või nonces/hashes), sõltuvalt brauserist ja CSP tasemest.

Leevendus 4: küpsised ja CSRF (paariga XSS)

XSS võib mööda minna CSRF tokenitest, kui token on lugemiseks DOM-ist või kui ründaja skript teeb päringuid volitustega. Seega: eelistage XSS-i parandusi; ka:

  • Sessiooni küpsised: HttpOnly, Secure, SameSite=Lax või Strict seal, kus vood lubavad - vähendab rist-site küpsiste lekkimist ja klassikalist CSRF-i.
  • Muutvad lõpppunktid: paaritage SameSite küpsistega, anti-CSRF tokenitega või kohandatud päistega + CORS poliitikaga, et juhuslikud saidid ei saa POST päringuid 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.

See koodibaas (konkreetne)

  • Päised / CSP - apps/web/next.config.ts: turvapäised /(*); CSP string on ehitatud koodis koos keskkonna-spetsiifilise script-src-ga (arendaja unsafe-eval ainult React virnale, kus vaja).
  • Chat API - apps/web/app/api/chat/route.ts: JSON parsib, tühja kontroll, MAX_MESSAGE_LENGTH piirang - kuritarvitamise kujundamine, mitte XSS ise.
  • Blogi - apps/web/lib/blog/mdx.tsx: MDX koos fikseeritud komponendi kaardiga (next-mdx-remote/rsc), mitte toor-HTML stringid CMS-ist. Erinev ohtude mudel kui "sõnumi keha HTML-iga".

Käivitatav võrdlus: mida main annab

Kloonige mänguväljak, käivitage npm install ja npm run devVite serveerib rakendust http://localhost:5173-s.

  • Live sait: playgrounds.lucascoliveira.com - sama demo kui hoidlas; kasutage seda, kui eelistate mitte kohalikult käivitada.
  • Todo UI (ainult mälus) - Lisage üksusi /insecure-s koos dokumentidest pärit kasutuskoormustega; sama voo /secure näitab saniteeritud väljundit.
  • Dokumentatsioon / sisemised toimingud - Alustage hoidla README, seejärel kontrollige payloadPresets.ts ja simulateXssImpact.ts tegelike juhtumite ja "mõju" kaardistamiseks.
  • Vale token - Rakendus salvestab demo tokeni localStorage-s (vt 03-session-hijacking) nii, et näete, mida skript lehel lugeda saab; insecure-patterns soovitab ka localStorage.getItem('auth_token') DevTools-is, et seda kontrollida.

Võrrelge /insecure vs /secure Elements ja Console-s: samad komponendid, erinev stringi käsitlemine enne DOM-i jõudmist.

Kontroll-loend (rakenduse tasemel)

  1. Inventariseerige valamu - rg "dangerouslySetInnerHTML|innerHTML|insertAdjacentHTML|eval\\(|new Function" teie rakenduses ja sõltuvustes.
  2. Rikkalik tekst - Lubatud nimekirja sanitisatsioon iga HTML-i tee jaoks; ühik-testige kasutuskoormustega nagu <img src=x onerror=...>, javascript: URL-id - ja pidage meeles, et innerHTML ei käivita <script> nii, nagu paljud petulehed viitavad. **innerHTML-stiili süstimisdemo jaoks eelistage onerror ** img (või sarnast); <svg onload> on sageli ebakindel, kui see on sisestatud sellisel viisil.
  3. URL parameetrid → DOM - Ärge määrutage kunagi otsingut/räsi HTML-iks; kui peate kuvama, tekst või kodeerige konteksti jaoks.
  4. Markdown - Saniteerige pärast täielikku MD → HTML konversiooni; keelake toor-HTML Markdownis, kui toode lubab.
  5. CSP - Kinnitage järk-järgult; kasutage arenduses Report-Only, kui vaja.
  6. Küpsised / API - Kohandage SameSite, volitused ja CSRF strateegia koos backendiga; eeldage, et XSS ja CSRF saavad aheldatud.

Kokkuvõte

XSS on juhtimisvoog: andmed, mis ületavad tõlgendamist. Kaitse on tüüpimine piiril: lihttekst, turvalised struktureeritud komponendid või saniteeritud HTML koos minimaalse lubatud nimekirjaga - pluss CSP ja küpsiste semantika, mis piiravad, mida hulkuv skript veel teha saab. Mänguväljak muudab selle piiri nähtavaks: turvamata renderdus tee vs saniteeritud tee, pluss eelseatud kasutuskoormused ja kaardistatud "mõju" käitumine hoidlas.