Många säkerhetsproblem i webben kommer från att lita på användaren för mycket. De flesta användare av din webbapplikation kommer bara att göra vad de behöver, en nyfiken eller skadlig användare vill ofta trycka kanterna på åtkomst. Vid dessa kanter visas säkerhetshål ofta i din ansökan. Jag har skrivit om att förhindra två vanliga typer av sårbarheter, SQL Injection och Cross Site Request Forgery, i ASP.NET-appar före. Denna artikel ser till att förhindra Cross Site Scripting, en tredje vanlig typ av sårbarhet på webbplatser.
Medan en modern ram gör mycket för att göra dessa attacker svårare, tror jag att vi först bör förstå hur en app är utsatt för en attack. Låt oss först titta på vilken Cross Site Scripting är och hur den kan utnyttjas.
Cross Site Scripting (ofta förkortad som XSS) möjliggör injektion av skadliga skript till en annan betrodd webbplats. Denna injektion sker utan användarens kunskaper. Det injicerade skriptet körs som om det kom från den ursprungliga webbplatsen. Det skadliga skriptet kan alltså få tillgång till eventuella resurser på den värdwebbplats som användaren skulle ha tillgång till, till exempel cookies eller sessionstoken.
Öppningen för en cross-site scripting attack kommer när en webbapplikation visar inmatning från användare eller externa resurser utan att korrekt validera eller koda det. Vid de flesta övergripande scripting-attacker försöker attackeren att injicera JavaScript på webbsidan för en betrodd server. Anfallaren kan också försöka injicera HTML, Flash eller något annat som webbläsaren ska utföra. Oavsett scriptet är målet fortfarande att få webbläsaren att utföra kod för angriparens val.
Det finns tre kategorier av cross-site scripting attacker, dividerat med injektionsmetoden och metod för att förhindra attacken. I den första typen av attack lagras manuset permanent på målservern och kallas sålunda en kvarstående script-attack. Den här attacken försöker integrera det skadliga skriptet i något som ett forumpost som lagras i en databas eller ett till synes godartat fält, t.ex. en databasens hemsida. Med skriptet kvarhållit, blir varje besökare på webbplatsen som ser posten, meddelandet eller på annat sätt komprometterat objekt ett potentiellt offer för attacken.
Attackers som försöker denna typ av attack riktar sig i allmänhet till kommentarerfält, forum, sociala medier och andra områden där något godtyckligt slutanvändarinput förväntas och är en vanlig del av applikationen. Attackeren kan innehålla manuset i ett foruminlägg i en annars giltig del av en konversation. Varje gång någon tittar på inlägget, kommer manuset att utföras.
I den andra typen av cross-site scripting attack, känd som reflekterad cross site scripting, levererar angriparen det injicerade skriptet till den sårbara webbplatsen så att den omedelbart kommer tillbaka till användaren. Vanliga metoder för att göra detta, målsidor där användarinmatning blir en del av utmatningen på en sida. En söksida kan visa sökvillkoren för användaren och kan ge ett uttag för denna attack. Det injicerade skriptet i en användares inmatning ska aldrig lagras av webbapplikationen.
Den tredje cross-site scripting attacken sker helt i webbläsaren. Attacken fungerar genom att manipulera den interna modellen på webbsidan i webbläsaren kallad DOM och kallas DOM-baserade attacker. Dessa igen tillåter angriparen att utföra skadlig kod, men kod som returneras av servern manipuleras till exekverbar JavaScript av webbsidan.
I slutändan är en cross-site scripting attack en cross-site scripting attack, oavsett hur den levereras. Eftersom den injicerade koden kommer från en annan betrodd server, kan den ofta utföras under webbplatsens behörigheter. Det kan därför fungera som om det var inbyggt kod på webbplatsen.
En lyckad cross-site scripting attack kan tillåta åtkomst till cookies på en webbsida. Dessa cookies kan innehålla känslig information inklusive sessionsidentifierare som gör det möjligt för angriparen att efterlikna den angripna användaren. Attacken kan också ändra HTML-innehåll på en sida för att visa ett falskt inloggningsformulär och stjäla användarens inloggningsuppgifter. Attackeren kan undersöka och skicka innehåll på sidan som gör det möjligt att fånga känslig information som kontonumrar. En mer avancerad attack kan i själva verket installera en nyckelloggare som skickar all information som är inskriven på webbsidan till en angripare.
Mitigating cross scripting kräver inte att man litar på någon inmatning från en användare eller någon annan extern källa. Webapplikationen måste behandla dessa data som potentiellt farliga, oavsett källan. Låt oss titta på några metoder som är specifika för ASP.NET för att förhindra att dessa attacker använder komponenter inbyggda i ramverket och fritt tillgängliga bibliotek.
Webapplikationen bör validera inmatning till programmet innan den används. Precis som med andra injektionsattacker som SQL Injection. Ansökan validerar företrädesvis denna ingång mot en vit lista av acceptabla värden. Valideringen tar bort eller ersätter eventuella oväntade komponenter i ingången med ett kodat värde. En svartlistningsmetod, som endast tar bort en lista med kända oönskade tecken, kan användas, men är mer sårbar för nya angreppsmetoder.
Om vi vet att ett värde alltid ska vara ett heltal, kan du validera inmatningen med hjälp av kod som:
int medlemId; om (! int.TryParse (externalValue, out memberId)) returnera RedirectToAction ("InputError");
Om ramen inte kan analysera det tidigare hämtat externalValue
som ett heltal, omdirigerar koden till en sida som skulle visa ett fel. Annars vet vi det memberId
innehåller ett heltal värde. Denna process fungerar också med andra grundläggande typer. Vissa vanligare typer ger också metoder för att validera informationen. Nätet Uri
klassen innehåller en metod IsWellFormedUriString
som kan validera en webbadress Detta skulle möjliggöra validering att en användares hemsidainmatning innehåller en giltig URL före visning.
var userHomePage = userRecord ["hemsida"]; om (! Uri.IsWellFormedUriString (newUrl, UriKind.Absolute)) Model.homepage = "none"; else Model.homepage = Html.Encode (userHomePage);
Andra och mer komplexa datatyper behöver mer komplext validering. Validering av ett kreditkortsnummerfält kan ta bort alla tecken i strängen som inte är siffror. Validering av mer komplexa strängar kan behöva regelbundna uttryck. Valideringen av en klass kan också behöva mer komplexa kontroller.
ASP.NET ger effektivt skydd mot reflekterade attacker med begäran om validering. Om ASP.NET upptäcker markering eller kod i en förfrågan, kastar det ett "potentiellt farligt värde detekterades" undantag och stoppar behandlingen av begäran.
Medan det är värdefullt, finns det tillfällen att du måste tillåta dessa värden i en förfrågan. Ett vanligt exempel kommer att tillåta rik textinmatning i en form. I dessa fall är förfrågningsvalideringen tyvärr för ofta avstängd för hela webbplatsen. En bättre lösning stänger av denna validering endast vid behov. I tidigare versioner av ASP.NET, lägger du till validateRequest = "false"
till Sida
direktivet i Webforms skulle stänga av valideringen för en sida. I ASP.NET MVC, lägger du till [ValidateInput (false)]
Attribut till en controller-åtgärd stänger av validering för den åtgärden medan du lägger till [AllowHtml]
attributet stänger av validering för ett fält.
ASP.NET 4.0 ändrade begäran validering på flera sätt. Denna och senare versioner av ramverket gör validering tidigt i HTTP-förfrågan. Valideringen gäller även för alla ASP.NET-förfrågningar och inte bara .aspx
sidförfrågningar. Detta inkluderar även anpassade HTTP-moduler. Sidor som bygger på det ursprungliga beteendet kan återgå till den äldre metoden genom att ställa in requestValidationMode
attribut i web.config
fil till version 2,0
.
Ännu bättre är att avaktivera detta endast för sidor där det behövs, med hjälp av syntaxen i web.config
fil:
ASP.NET 4.5 lade till möjligheten att skjuta upp valideringen tills den begärde data. Ställa in requestValidationMode
attribut i din web.config
fil till version 4,5
aktiverar detta nya beteende.
ASP.NET 4.5 lade också till HttpRequest.Unvalidated
fast egendom. Användning av denna egenskap gör det lättare att komma till det obestämda formvärdet när det behövs. Genom att kombinera försenad validering och Fraktpris saknas
egendom, kan du komma åt de ovaliderade värdena när det behövs, men skydda andra formuläringångar.
Innan du visar externa data på en webbsida ska din HTML vara kodad så att den inte behandlas av webbläsaren. Ta till exempel en ASP.NET-sida så att ett meddelande kan skickas för visning, till exempel en statusuppdatering. En applikation kan använda den här sidan för att visa användaren att deras konto har skapats utan fel. Webbadressen för denna sida skulle normalt likna http: // appname / placeorder / Account + Skapad
. Den resulterande sidan visar meddelandet till användaren med ett fält, till exempel:
<%= Html.Label("Message", Model.message) %>
... och visas som:
Om vi ändrar URL-samtalet till http: / appname / placeorder /
, vi får nu något annat.
Skriptet kan vara allt självklart och inte bara den ofarliga varningsrutan som visas här. Förfrågan Validering skulle få ovanstående exempel och återge ett undantag före visning. Om den är avstängd, kan kodningen av utmatningen förhindra attacken.
ASP.NET gör det enkelt att koda data för att förhindra attacker. Tidiga versioner av MVC med Webforms syntax innehöll ofta kod som det som inte kodade HTML.
<%= status >
Du måste manuellt koda utmatningen så att någon HTML skulle konverteras till ett visningsformat. Så <
tecken blir strängen <
. De Html.Encode
funktionen ger denna omvandling. Den säkrare form av kod blir således:
<%= Html.Encode(status) >
ASP.NET MVC introducerade senare en syntax för att göra detta i ett steg genom att ersätta <=
med <:
så koden kan förkortas till:
<%: status >
Med hjälp av Razor-visningsmotorn är all utmatning HTML-kodad om du inte specifikt använder en metod för att inte koda den. I Razor blir koden som motsvarar ovanstående:
@status
Razor hanterar automatiskt HTML-kodning av vad som helst strängen status
innehåller. I ett fall där du behöver göra de råa data kan du använda HTML.Raw ()
metod. För att visa resultatet utan kodning kan vi använda:
@ Html.Raw (status)
I det här exemplet skulle ovanstående kod göra vår ansökan sårbar igen. Så det finns några omständigheter där du inte bör koda produktionen. Om du inaktiverar den här funktionen på ett fält måste du vara extra försiktig för att säkerställa att data är saniterade före visning. Lyckligtvis finns det ett bibliotek som hjälper till med detta samtidigt som du gör mer för att skydda din ansökan från cross-site scripting.
Om du skriver en ASP.NET-applikation ska du använda AntiXSS-biblioteket för ASP.NET. Från projektets hemsida, "AntiXSS ger en myriad av kodningsfunktioner för användarinmatning, inklusive HTML, HTML-attribut, XML, CSS och JavaScript."
Biblioteket innehåller metoder som är inriktade på att sanitera utifrån data baserat på den avsedda användningen av data. Dessa metoder använder den föredragna vita listbaserade metoden. Det betyder att kodad data, avsedd för en HTML-attribut, kan saneras för att innehålla endast giltiga data för ett HTML-attribut. Den traditionella ASP.NET HtmlEncode
metoder använder den svarta noteringsmetoden som endast kodar för vissa, potentiellt farliga tecken.
Microsoft började inkludera kärnrutiner från detta bibliotek till ASP.NET 4.5 i ett nytt System.Web.Security.AntiXss
namnutrymmet. Du kan också ställa in ramverket för att använda dessa AntiXSS-metoder i stället för de inbyggda kodningsrutinerna. Du gör det genom att ställa in encoderType
attribut av httpRuntime
i web.config
fil för ansökan:
Om din ansökan har någon signifikant visning av externa data, kommer användningen av AntiXSS att göra mycket för att skydda din ansökan från cross-site scripting. Om du använder ASP.NET 4.5, ändrar du din applikation för att använda de nya AntiXSS-metoderna för standardkodning, vilket ger ännu mer skydd för din webbapplikation.
Att förebygga cross-site-skript är hårdare än vad som ursprungligen verkar. OWASP listar över 80 vektorer som kan riktas mot användning av cross-site scripting attacks. Den organisationen listar också dessa sårbarheter som tredje i deras 2013-lista över de tio bästa sårbarheterna.
Om du inte säkerställer att all extern data som tagits in i din ansökan är korrekt undgåd eller inte validerar inmatning innan du placerar den på en utmatningssida, lämnar du din webbansökan sårbar för att överskrida webbplatsens skript. I ASP.NET kan detta göras av: