LabbCybersäkerhet · Etisk hackning
0/0
Laboration

Utdatakodning och Content Security Policy

Mål: Förstå varför data från en användare kan hamna som kod hos en annan, och bygga försvar i flera lager.

Observera

Genomför PortSwigger-akademins XSS-moduler eller DVWA:s XSS-övningar (Reflected och Stored), på nivå Low och därefter High. OWASP Juice Shop har också bra, guidade utmaningar här.

Notera särskilt skillnaden mellan reflected (data studsar tillbaka i svaret på en förfrågan) och stored (data sparas och visas sedan för alla besökare). Den senare är allvarligare eftersom den drabbar andra användare utan att de gör något ovanligt.

Analysera grundorsaken

Grundorsaken är spegelbilden av Lab 3: användardata placeras i ett HTML-dokument utan att kodas om för det sammanhang den hamnar i. Webbläsaren kan inte skilja på innehåll som applikationen menade som text och innehåll som råkar vara markup.

Studera källkoden i DVWA mellan nivåerna och identifiera var utdata skrivs ut. Lägg märke till att sammanhanget spelar roll — samma data behöver olika behandling beroende på om den hamnar i HTML-text, i ett attribut, i en URL eller i ett JavaScript-block.

Bygg försvaret

1. Kontextkorrekt utdatakodning. Använd ramverkets inbyggda mekanismer, som gör detta rätt som standard:

Ramverk Säkert som standard Farlig konstruktion att undvika
React {variabel} dangerouslySetInnerHTML
Vue {{ variabel }} v-html
Django {{ variabel }} \|safe, mark_safe()
Jinja2 {{ variabel }} (med autoescape) \|safe
PHP htmlspecialchars($v, ENT_QUOTES, 'UTF-8') direkt echo $v

Regeln: om du letar efter ett sätt att stänga av ramverkets escaping har du nästan alltid hamnat fel.

2. Content Security Policy. CSP är ett andra lager som begränsar vad webbläsaren överhuvudtaget får köra, även om något skulle slinka igenom:

add_header Content-Security-Policy
  "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'" always;
Vad koden gör — förklaring rad för rad

En nginx-rad som skickar med en Content Security Policy. Den talar om för webbläsaren vad den överhuvudtaget får köra på sidan — ett andra skyddslager om något skulle slinka igenom.

default-src 'self'
Som utgångspunkt: ladda bara saker från vår egen domän.
script-src 'self'
Kör bara JavaScript från vår egen domän. Skript inskrivna direkt i sidan blockeras, vilket är just det en angripare skulle försöka smuggla in.
object-src 'none'
Tillåt inga inbäddade objekt som Flash eller liknande. none betyder ingenting alls.
frame-ancestors 'none'
Ingen annan webbplats får bädda in din sida i en ram. Skyddar mot att din sida läggs osynlig ovanpå en annan.

script-src 'self' innebär att endast skript från den egna domänen körs — inline-skript blockeras. Det kräver att applikationen är byggd utan inline-JavaScript, vilket är gott hantverk i sig.

3. HttpOnly på sessionskakan (se Lab 1) gör att sessionskakan inte kan läsas av JavaScript, vilket begränsar konsekvensen av ett problem.

4. Rensa HTML när användare ska få använda formatering. Om användare legitimt ska kunna skriva fetstil och länkar räcker inte escaping — då behövs ett bibliotek som rensar bort allt utom en vitlista av tillåtna taggar. Använd ett etablerat bibliotek (DOMPurify för JavaScript, Bleach för Python, HTML Purifier för PHP). Skriv aldrig en egen HTML-rensare; det är ett problem som är betydligt svårare än det ser ut.

Verifiera

Kontrollera att CSP-headern faktiskt levereras:

curl -I https://exempel.se | grep -i content-security-policy
Vad koden gör — förklaring rad för rad

Ett kontrollkommando som bekräftar att policyn faktiskt skickas med. Två verktyg kedjas ihop.

curl -I https://exempel.se
Hämtar svarshuvudena från sajten.
|
Det lodräta strecket kallas pipe. Det skickar resultatet från kommandot till vänster vidare in i kommandot till höger.
grep -i content-security-policy
grep letar efter en viss text och visar bara de rader som matchar. -i betyder att stora och små bokstäver behandlas lika.

Öppna webbläsarens utvecklarkonsol och leta efter CSP-överträdelser — de visas som tydliga felmeddelanden och är ett utmärkt sätt att hitta kvarvarande inline-skript i din egen applikation.

Dokumentera

Dokumentera både typen (reflected/stored) och sammanhanget där problemet uppstod, eftersom åtgärden skiljer sig åt. Bifoga en rekommendation i två lager: kodningen som primärt försvar och CSP som sekundärt.

Reflektionsfrågor: Varför är försvar i flera lager ("defense in depth") särskilt relevant här? Vad händer med CSP-skyddet om applikationen använder 'unsafe-inline'?


Kunskapskontroll

Välj ett svar per fråga. Du får återkoppling direkt, och avsnittet markeras som klart när alla frågor är besvarade.

1Varför är lagrad (stored) XSS allvarligare än reflekterad?

2Vad innebär `script-src 'self'` i en Content Security Policy?

3Användare ska legitimt kunna skriva fetstil och länkar. Vad krävs utöver escaping?