i det här avsnittet beskriver vi några allmänna principer för att förhindra serveröverskridande skriptsårbarheter och sätt att använda olika vanliga tekniker för att skydda mot XSS-attacker.

Cross-site scripting prevention kan generellt uppnås via två lager av försvar:

  • koda data på utdata
  • validera indata Vid ankomst

du kan använda Burp Scanner för att skanna dina webbplatser för många säkerhetsproblem, inklusive XSS. Burps banbrytande skanningslogik replikerar en skicklig angripares handlingar och kan uppnå motsvarande hög täckning av XSS-sårbarheter. Du kan använda Burp Scanner för att få försäkran om att ditt försvar mot XSS-attacker fungerar effektivt.

koda data på utdata

kodning bör tillämpas direkt innan användarkontrollerbara data skrivs till en sida, eftersom sammanhanget du skriver in bestämmer vilken typ av kodning du behöver använda. Till exempel kräver värden i en JavaScript-sträng en annan typ av flykt till dem i ett HTML-sammanhang.

i ett HTML-sammanhang bör du konvertera icke-vitlistade värden till HTML-enheter:

  • < konverterar till: &lt;
  • > konverterar till: &gt;

i ett JavaScript-strängkontext bör icke-alfanumeriska värden vara Unicode-escaped:

  • < konverterar till: \u003c
  • > konverterar till: \u003e

ibland måste du tillämpa flera lager av kodning, i rätt ordning. Till exempel, för att säkert bädda in användarinmatning i en händelsehanterare, måste du hantera både JavaScript-sammanhanget och HTML-sammanhanget. Så du måste först Unicode-Fly inmatningen och sedan HTML-koda den:

<a href="#" onclick="x='This string needs two layers of escaping'">test</a>

validera input vid ankomst

kodning är förmodligen den viktigaste raden i XSS-försvar, men det är inte tillräckligt för att förhindra XSS-sårbarheter i alla sammanhang. Du bör också validera input så strikt som möjligt vid den tidpunkt då den först tas emot från en användare.

exempel på inmatningsvalidering inkluderar:

  • om en användare skickar in en URL som kommer att returneras i svar, validerar att den börjar med ett säkert protokoll som HTTP och HTTPS. Annars kan någon utnyttja din webbplats med ett skadligt protokoll som javascript eller data.
  • om en användare levererar ett värde som det förväntas vara numeriskt, validerar att värdet faktiskt innehåller ett heltal.
  • validering av den inmatningen innehåller endast en förväntad uppsättning tecken.

Inmatningsvalidering bör helst fungera genom att blockera ogiltig inmatning. Ett alternativt tillvägagångssätt, att försöka rengöra ogiltig inmatning för att göra den giltig, är mer felbenägen och bör undvikas där det är möjligt.

vitlista vs svartlista

inmatningsvalidering bör i allmänhet använda vitlistor snarare än svartlistor. Till exempel, istället för att försöka göra en lista över alla skadliga protokoll (javascript, data, etc.), gör helt enkelt en lista över säkra protokoll (HTTP, HTTPS) och tillåt allt som inte finns på listan. Detta säkerställer att ditt försvar inte bryts när nya skadliga protokoll visas och gör det mindre mottagligt för attacker som försöker dölja ogiltiga värden för att undvika en svartlista.

att tillåta” säker ” HTML

att tillåta användare att posta HTML-markering bör undvikas när det är möjligt, men ibland är det ett företagskrav. Till exempel kan en bloggwebbplats tillåta att kommentarer publiceras med viss begränsad HTML-markering.

det klassiska tillvägagångssättet är att försöka filtrera bort potentiellt skadliga taggar och JavaScript. Du kan försöka implementera detta med hjälp av en vitlista över säkra taggar och attribut, men tack vare avvikelser i webbläsarparsningsmotorer och quirks som mutation XSS är detta tillvägagångssätt extremt svårt att implementera säkert.

det minst dåliga alternativet är att använda ett JavaScript-bibliotek som utför filtrering och kodning i användarens webbläsare, till exempel DOMPurify. Andra bibliotek tillåter användare att tillhandahålla innehåll i wiki-format och konvertera Wiki till HTML. Tyvärr har alla dessa bibliotek XSS-sårbarheter då och då, så det här är inte en perfekt lösning. Om du använder en bör du övervaka noga för säkerhetsuppdateringar.

notera

förutom JavaScript kan annat innehåll som CSS och till och med vanlig HTML vara skadligt i vissa situationer.

attacker med skadlig CSS

hur man förhindrar XSS med en mallmotor

många moderna webbplatser använder mallmotorer på serversidan som Twig och Freemarker för att bädda in dynamiskt innehåll i HTML. Dessa definierar vanligtvis sitt eget flyktningssystem. I Twig kan du till exempel använda filtret e() med ett argument som definierar sammanhanget:

{{ user.firstname | e('html') }}

vissa andra mallmotorer, som Jinja och React, undviker dynamiskt innehåll som standard vilket effektivt förhindrar de flesta förekomster av XSS.

vi rekommenderar att du granskar escaping-funktioner noggrant när du utvärderar om du vill använda en viss mallmotor eller ram.

notera

om du direkt sammanfogar användarinmatning i mallsträngar kommer du att vara sårbar för mallinsprutning på serversidan, vilket ofta är allvarligare än XSS.

hur man förhindrar XSS i PHP

i PHP finns en inbyggd funktion för att koda enheter som heter htmlentities. Du bör ringa den här funktionen för att undkomma din inmatning när du är inne i ett HTML-sammanhang. Funktionen ska anropas med tre argument:

  • din inmatningssträng.
  • ENT_QUOTES, vilket är en flagga som anger att alla citat ska kodas.
  • teckenuppsättningen, som i de flesta fall ska vara UTF-8.

till exempel:

<?php echo htmlentities($input, ENT_QUOTES, 'UTF-8');?>

när du är i ett JavaScript-strängkontext måste du Unicode-escape-ingång som redan beskrivits. Tyvärr tillhandahåller PHP inte ett API för Unicode-escape a string. Här är lite kod för att göra det i PHP:

<?php

function jsEscape($str) {
$output = '';
$str = str_split($str);
for($i=0;$i<count($str);$i++) {
$chrNum = ord($str);
$chr = $str;
if($chrNum === 226) {
if(isset($str) && ord($str) === 128) {
if(isset($str) && ord($str) === 168) {
$output .= '\u2028';
$i += 2;
continue;
}
if(isset($str) && ord($str) === 169) {
$output .= '\u2029';
$i += 2;
continue;
}
}
}
switch($chr) {
case "'":
case '"':
case "\n";
case "\r";
case "&";
case "\";
case "<":
case ">":
$output .= sprintf("\u%04x", $chrNum);
break;
default:
$output .= $str;
break;
}
}
return $output;
}
?>

så här använder du funktionen jsEscape i PHP:

<script>x = '<?php echo jsEscape($_GET)?>';</script>

Alternativt kan du använda en mallmotor.

så här förhindrar du XSS-klientsidan i JavaScript

för att undvika användarinmatning i ett HTML-sammanhang i JavaScript behöver du din egen HTML-kodare eftersom JavaScript inte tillhandahåller ett API för att koda HTML. Här är några exempel JavaScript-kod som konverterar en sträng till HTML-enheter:

function htmlEncode(str){
return String(str).replace(//gi, function(c){
return '&#'+c.charCodeAt(0)+';';
});
}

du skulle då använda den här funktionen enligt följande:

<script>document.body.innerHTML = htmlEncode(untrustedValue)</script>

om din inmatning finns i en JavaScript-sträng behöver du en kodare som utför Unicode-flykt. Här är ett exempel Unicode-encoder:

function jsEscape(str){
return String(str).replace(//gi, function(c){
return '\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
});

}

du skulle då använda den här funktionen enligt följande:

<script>document.write('<script>x="'+jsEscape(untrustedValue)+'";<\/script>')</script>

hur man förhindrar XSS i jQuery

den vanligaste formen av XSS i jQuery är när du skickar användarinmatning till en jQuery-väljare. Webbutvecklare skulle ofta använda location.hash och skicka den till väljaren vilket skulle orsaka XSS eftersom jQuery skulle göra HTML. jQuery kände igen problemet och lappade sin väljarlogik för att kontrollera om inmatningen börjar med en hash. Nu kommer jQuery bara att göra HTML om det första tecknet är en <. Om du skickar otillförlitliga data till jQuery-väljaren, se till att du undviker värdet korrekt med funktionen jsEscape ovan.

Mitigating XSS using content security policy (CSP)

Content security policy (CSP) är den sista försvarslinjen mot cross-site scripting. Om ditt XSS-förebyggande misslyckas kan du använda CSP för att mildra XSS genom att begränsa vad en angripare kan göra.

CSP låter dig styra olika saker, till exempel om externa skript kan laddas och om inline-skript kommer att köras. För att distribuera CSP måste du inkludera en HTTP-svarsrubrik som heter Content-Security-Policy med ett värde som innehåller din policy.

ett exempel CSP är som följer:

default-src 'self'; script-src 'self'; object-src 'none'; frame-src 'none'; base-uri 'none';

den här principen anger att resurser som bilder och skript endast kan laddas från samma ursprung som huvudsidan. Så även om en angripare framgångsrikt kan injicera en XSS-nyttolast kan de bara ladda resurser från det aktuella ursprunget. Detta minskar risken för att en angripare kan utnyttja XSS-sårbarheten.

om du behöver ladda externa resurser, se till att du bara tillåter skript som inte hjälper en angripare att utnyttja din webbplats. Om du till exempel vitlista vissa domäner kan en angripare ladda alla skript från dessa domäner. Om möjligt, försök att vara värd för resurser på din egen domän.

om det inte är möjligt kan du använda hash – eller nonce-baserad policy för att tillåta skript på olika domäner. En nonce är en slumpmässig sträng som läggs till som ett attribut för ett skript eller en resurs, som bara körs om den slumpmässiga strängen matchar den servergenererade. En angripare kan inte gissa den randomiserade strängen och kan därför inte anropa ett skript eller en resurs med en giltig nonce och så kommer resursen inte att köras.

mildra XSS-attacker med CSP

Lämna ett svar

Din e-postadress kommer inte publiceras.