Starka svar html. Galna former. Mejladresser

Cross-site scriptinjection attacker

I en XSS-attack (cross-site scripting) injicerar en angripare skadlig kod på en legitim webbsida, som sedan kör ett skadligt skript på klientsidan. När en användare besöker en infekterad sida laddas skriptet ner till användarens webbläsare och körs där. Detta schema har många varianter. Ett skadligt skript kan komma åt webbläsarcookies, sessionstokens eller annan känslig information som lagras i webbläsaren. Men alla attacker fungerar enligt schemat som visas i figur 1.

Figur 1. Figur 1. Typisk XSS-attack
XSS-sårbarheter

I en typisk XSS-attack hittar angriparen ett sätt att injicera en sträng på serverns webbsida. Låt oss säga att en angripare injicerade följande rad på en webbsida: alert("du är under attack") . Varje gång en användare besöker den här sidan laddar deras webbläsare ner det här skriptet och kör det tillsammans med resten av sidans innehåll. I det här fallet, som ett resultat av att köra skriptet, kommer användaren att se ett popup-fönster med texten "du är under attack."

Konsekvenser av XSS

Om en angripare kunde utnyttja en XSS-sårbarhet i en webbapplikation, kunde han injicera skript på sidan som skulle ge tillgång till data konto användare. I det här fallet kan angriparen utföra många skadliga åtgärder, till exempel:

  • stjäla ett konto;
  • sprider virus;
  • komma åt din webbhistorik och innehållet i urklipp;
  • Få en möjlighet fjärrkontroll webbläsare;
  • skanna och använda hårdvaru- och mjukvaruresurser och applikationer på det interna nätverket.
Förhindra XSS-attacker

För att förhindra XSS-attacker måste applikationen kryptera sidutgången innan den levereras till slutanvändaren. Vid kryptering av utdata HTML-uppmärkning ersatt av alternativa representationer - föremål. Webbläsaren visar dessa objekt men startar dem inte. Till exempel konverterat till .

Tabell 1 visar objektnamnen för några vanliga HTML-tecken.

Tabell 1. Objektnamn för HTML-tecken Resultat Beskrivning Objektnamn Objektnummer
Icke-brytande utrymme
< Mindre än<
> Mer än> >
& Ampersand& &
¢ Cent¢ ¢
£ Lb£ £
¥ Jena¥ ¥
Euro
§ Paragraf§ §
© upphovsrätt ©
® ® ®
Varumärke

När webbläsaren stöter på objekten konverteras de tillbaka till HTML och skrivs ut, men de avfyras inte. Till exempel, om en angripare infogar strängvarningen ("du är under attack") i ett variabelt fält på serverns webbsida, när den beskrivna strategin används kommer servern att returnera strängvarningen ("du är under attack") .

När webbläsaren laddar ner det krypterade skriptet kommer det att konvertera det till alert ("du är under attack") och visa skriptet som en del av webbsidan, men kommer inte att köra det.

Lägga till HTML-kod till en Java-applikation på serversidan

För att förhindra att skadlig skriptkod renderas tillsammans med sidan måste din applikation kryptera alla strängvariabler innan de renderas på sidan. Kryptering består av enkel förvandling varje tecken till motsvarande HTML-objektnamn, som visas i Java-kod visas i lista 1.

Lista 1. Konvertera tecken till HTML-objektnamn public class EscapeUtils ( public static final HashMap m = new HashMap(); static ( m.put(34, """); //< - меньше чем m.put(60, ""); // >- större än //Användaren måste matcha alla html-objekt med motsvarande decimalvärden. //Objektmappningar till decimala värden visas i tabellen nedan) public static String escapeHtml() ( String str = "alert(\"abc\")"); prova ( StringWriter writer = new StringWriter((int) (str) .length() * 1,5)); escape(writer, str); System.out.println("kodad sträng är " + writer.toString()); return writer.toString(); ) catch (IOException ioe) ( ioe .printStackTrace(); return null; ) ) public static void escape(Writer writer, String str) kastar IOException ( int len ​​​​= str.length(); för (int i = 0; i< len; i++) { char c = str.charAt(i); int ascii = (int) c; String entityName = (String) m.get(ascii); if (entityName == null) { if (c >0x7F) ( writer.write(""); writer.write(Integer.toString(c, 10)); writer.write(";"); ) else ( writer.write(c); ) ) else ( writer. write(entityName); ) ) ) )

Java-koden i Lista 1 kodar HTML-strängen String String "alert(\"abc\)" . Använd följande procedur:

Som ett resultat kommer följande rad att visas i utgången: alert("abc") .

Tabell 2 visar mappningen av HTML-objekt till deras decimalvärden.

Tabell 2. HTML-objekts decimalvärden Decimalvärde Objektbeskrivning
160 Icke-brytande utrymme
60 < Mindre än
62 > Mer än
38 & Ampersand
162 ¢ Cent
163 £ Lb
165 ¥ Jena
8364 Euro
167 § Paragraf
169 upphovsrätt
174 ® Registrerat varumärke
8482 Varumärke
Slutsats

Skriptinjektion över platsen är en av de vanligaste metoderna för att attackera en användares dator. Du kan dock avsevärt minska en angripares förmåga att infektera din webbapplikation med skadlig kod. När du bygger din applikation, var noga med att kryptera alla sidutgångsvärden innan du skickar dem till slutanvändarens webbläsare.

Genererar ett svar från styrenheter

Efter att kontrollanten har avslutat bearbetningen av begäran behöver den vanligtvis generera ett svar. När vi skapar en lågnivåkontroller genom att direkt implementera IController-gränssnittet, måste vi ta ansvar för varje aspekt av förfrågningsbehandling, inklusive att generera ett svar till klienten.

Till exempel, för att skicka ett HTML-svar, måste du skapa och komponera HTML-data och sedan skicka den till klienten med metoden Response.Write(). På samma sätt, för att omdirigera användarens webbläsare till en annan URL, måste du anropa metoden Response.Redirect() och skicka den nödvändiga URL:en. Båda tillvägagångssätten visas i koden nedan, som visar tillägg av BasicController-klassen som vi skapade i en tidigare artikel genom att implementera IController-gränssnittet:

Använder System.Web.Mvc; använder System.Web.Routing; namespace ControllersAndActions.Controllers ( public class BasicController: IController ( public void Execute(RequestContext requestContext) ( string controller = (string)requestContext.RouteData.Values["controller"]; string action = (string)requestContext.RouteData.Values "]; if (action.ToLower() == "redirect") ( requestContext.HttpContext.Response.Redirect("/Derived/Index"); ) else ( requestContext.HttpContext.Response.Write(string.Format("Controller : (0), Åtgärdsmetod: (1)", styrenhet, åtgärd)); ) ) ) )

Samma tillvägagångssätt kan tillämpas vid ärvning av en controller från Controller-klassen. Klassen HttpResponseBase, som returneras när egenskapen requestContext.HttpContext.Response läses i metoden Execute() är tillgänglig via egenskapen Controller.Response, som visas i exemplet nedan, som utökar klassen DerivedController, som också skapades tidigare av ärver från klassen Controller:

Använda System; använder System.Web; använder System.Web.Mvc; namespace ControllersAndActions.Controllers ( public class DerivedController: Controller ( public ActionResult Index() ( // ... ) public void ProduceOutput() ( if (Server.MachineName == "ProfessorWeb") Response.Redirect("/Basic/Index" ); else Response.Write("Controller: Derived, Action Method: ProduceOutput"); ) ) )

Metoden ProduceOutput() använder värdet för egenskapen Server.MachineName för att bestämma vilket svar som ska skickas till klienten. ("ProfessorWeb" är namnet på min utvecklingsmaskin.)

Även om detta tillvägagångssätt att generera ett svar till användaren fungerar, finns det flera problem med det:

    Controllerklasser ska innehålla information om HTML-struktur eller URL, vilket gör klasser svåra att läsa och underhålla.

    En styrenhet som genererar ett svar direkt på utsignalen är svår att enhetstesta. Du måste skapa skenimplementationer av Response-objektet och sedan kunna bearbeta utdata från styrenheten för att avgöra vad det är. Detta kan till exempel innebära behovet av att analysera HTML-uppmärkning till nyckelord, vilket är en lång och omständlig process.

    Att bearbeta de små detaljerna i varje svar på detta sätt är komplext och felbenäget. Vissa programmerare gillar den absoluta kontrollen som tillhandahålls genom att bygga en lågnivåkontroller, men detta blir vanligtvis komplicerat mycket snabbt.

Lyckligtvis har MVC Framework ett praktiskt verktyg som löser alla dessa problem - resultatet av åtgärder. Följande avsnitt förklarar konceptet med handlingsresultat och visar olika sätt dess användning för att generera svar från styrenheter.

Resultat av åtgärder

Åtgärdsresultat i MVC-ramverket används för att skilja avsiktsförklaringar från verkställande av avsikt (ursäkta tautologin). Konceptet kommer att verka enkelt när du väl fått kläm på det, men det tar lite tid att förstå på grund av viss indirekthet.

Istället för att ta itu direkt med ett Response-objekt, returnerar åtgärdsmetoder ett ActionResult-härlett klassobjekt som beskriver vad svaret från styrenheten ska vara – till exempel rendering av en vy eller omdirigering till en annan URL eller åtgärdsmetod. Men (detta är själva indirektheten) är svaret inte direkt genererat. Istället skapas ett ActionResult-objekt, som MVC Framework bearbetar för att producera resultatet efter att åtgärdsmetoden har anropats.

Ett åtgärdsresultatsystem är ett exempel på kommandodesignmönstret. Det här mönstret representerar scenarier där du lagrar och skickar objekt som beskriver de operationer som utförs.

När MVC Framework tar emot ett ActionResult-objekt från en åtgärdsmetod anropar det ExecuteResult()-metoden, definierad i klassen för detta objekt. Implementeringen av åtgärdsresultaten fungerar sedan på Response-objektet och genererar utdata som matchar din avsikt. För att visa detta i praktiken, låt oss skapa en Infrastructure-mapp och lägga till en ny klassfil till den som heter CustomRedirectResult.cs med en anpassad ActionResult-implementering som visas i exemplet nedan:

Använder System.Web.Mvc; namespace ControllersAndActions.Infrastructure ( offentlig klass CustomRedirectResult: ActionResult ( public string URL ( get; set; ) public override void ExecuteResult(ControllerContext context) ( string fullUrl = UrlHelper.GenerateContentUrl(Url, context.HttpContext.Redirect.HttpContext); context.Redirect.HttpContext (full URL); ) ) )

Denna klass är baserad på hur klassen System.Web.Mvc.RedirectResult fungerar. En av fördelarna med MVC Framework med öppen källkod är förmågan att utforska det inre av vad som helst. Klassen CustomRedirectResult är mycket enklare än dess MVC-motsvarighet, men är tillräcklig för syftet med denna artikel.

När vi instansierar klassen RedirectResult skickar vi in ​​URL:en som användaren ska omdirigeras till. Metoden ExecuteResult(), som kommer att exekveras av MVC Framework när åtgärdsmetoden är klar, tar emot Responsobjekt att göra en förfrågan genom ControllerContext-objektet som tillhandahålls av ramverket och anropar antingen metoden RedirectPermanent() eller metoden Redirect() (detta speglar exakt vad som gjordes i lågnivåimplementeringen av IController i exemplet tidigare i artikeln).

Användningen av klassen CustomRedirectResult illustreras i exemplet nedan, som visar ändringarna som gjordes i den härledda styrenheten:

// ... med ControllersAndActions.Infrastructure; namespace ControllersAndActions.Controllers ( public class DerivedController: Controller ( public ActionResult Index() ( // ... ) public ActionResult ProduceOutput() ( if (Server.MachineName == "MyMachineName") returnerar nytt CustomRedirectResult ( Url = "/Basic/ Index" ); else ( Response.Write("Controller: Derived, Action Method: ProduceOutput"); return null; ) ) ) )

Observera att vi var tvungna att ändra resultatet av åtgärdsmetoden för att returnera ActionResult. Vi returnerar null om vi inte vill att MVC Framework ska göra något när vår åtgärdsmetod körs, vilket är vad vi gjorde om CustomRedirectResult-instansen inte returnerades.

Enhetstestning av styrenheter och åtgärder

Många delar av MVC Framework är utformade för att göra enhetstester enklare, och detta gäller särskilt för åtgärder och kontroller. Det finns flera anledningar till detta stöd:

Du kan testa åtgärder och kontroller utanför webbservern. Kontextobjekt nås via sina basklasser (som HttpRequestBase), vilket är lätt att håna.

För att testa resultatet av en åtgärdsmetod behöver du inte analysera HTML-uppmärkningen. För att säkerställa att du får de förväntade resultaten kan du inspektera det returnerade ActionResult-objektet.

Emulering av klientförfrågningar behövs inte. MVC Frameworks modellbindningssystem låter dig skriva åtgärdsmetoder som tar emot indata i sina parametrar. För att testa en åtgärdsmetod anropar du den helt enkelt direkt och anger lämpliga parametervärden.

Framtida artiklar om att generera data från kontroller kommer att visa dig hur du skapar enhetstester för olika typer av åtgärdsresultat.

Glöm inte att enhetstestning bara är en del av bilden. Komplext beteende i en applikation uppstår när åtgärdsmetoder anropas sekventiellt. Enhetstestning fungerar bäst i kombination med andra testmetoder.

Nu när du vet hur det speciella resultatet av en omdirigeringsåtgärd fungerar kan du byta till dess motsvarighet som erbjuds av MVC-ramverket, som är kraftfullare och har testats grundligt av Microsoft. Den nödvändiga ändringen av den härledda styrenheten anges nedan:

// ... public ActionResult ProduceOutput() ( returnera nytt RedirectResult("/Basic/Index"); ) // ...

Det villkorliga uttalandet har tagits bort från åtgärdsmetoden, vilket innebär att efter att ha kört applikationen och navigerat till en URL som /Derived/ProduceOutput kommer webbläsaren att omdirigeras till en URL som /Basic/Index. För att förenkla åtgärdsmetodkod innehåller klassen Controller bekvämlighetsmetoder för att generera olika typer av ActionResult-objekt. Så, till exempel, kan vi uppnå samma effekt som i exemplet ovan genom att returnera resultatet av metoden Redirect():

// ... public ActionResult ProduceOutput() ( return Redirect("/Basic/Index"); ) // ...

Det finns inget särskilt komplicerat med åtgärdsresultatsystemet, men det hjälper i slutändan till att producera enklare, renare, mer konsekvent kod som är lätt att läsa och enhetstesta. Till exempel, vid omdirigering kan du helt enkelt kontrollera att åtgärdsmetoden returnerar en RedirectResult-instans vars URL-egenskap innehåller det förväntade målet.

MVC-ramverket definierar många inbyggda åtgärdsresultattyper, som beskrivs i tabellen nedan:

Inbyggda ActionResult-typer Typ Beskrivning Hjälpmetoder för klassen Controller
Visa Resultat

Återger den angivna eller standardvymallen

Se()
PartialViewResult

Återger den angivna eller standardmallen för delvy

PartialView()
RedirectToRouteResult

frågor HTTP-omdirigering 301 eller 302 till en åtgärdsmetod eller specificerad ruttpost, genererar en URL enligt routingkonfigurationen

RedirectToAction()
RedirectToActionPermanent()
RedirectToRoute()
RedirectToRoutePermanent()
RedirectResult

Utfärdar en HTTP 301 eller 302 omdirigering till den givna URL:en

Dirigera om()
RedirectPermanent()
ContentResult

Returnerar oformaterad textdata till webbläsaren och ställer dessutom in rubriken för innehållstyp

Innehåll()
Filresultat

Överför binära data (som en fil på disk eller en byte-array i minnet) direkt till webbläsaren

Fil()
JsonResult

Serialiserar ett .NET-objekt till JSON-format och skickar det som ett svar. Svar av denna typ genereras oftare när du använder webb-API och AJAX-verktyg

Json()
JavaScriptResultat

Skickar ett fragment källkod JavaScript som måste köras av webbläsaren

JavaScript()
HttpUnauthorizedResult

Ställer in HTTP-svarsstatuskoden till 401 (vilket betyder "ej auktoriserad"), vilket gör att autentiseringsmekanismen på plats (formulärautentisering eller Windows-autentisering) uppmanar besökaren att logga in

Nej
HttpNotFoundResult

Returnerar HTTP-fel med kod 404 - Hittade inte (hittades ej)

HttpNotFound()
HttpStatusCodeResult

Returnerar den angivna HTTP-koden

Nej
Tomt Resultat

Gör inget

Nej

Alla dessa typer härrör från ActionResult-klassen, och många av dem har praktiska hjälpmetoder i Controller-klassen. Vi kommer att visa användningen av dessa typer av resultat i efterföljande artiklar.

Efter att ha tagit emot och tolkat ett förfrågningsmeddelande, svarar en server med ett HTTP-svarsmeddelande:

  • En statusrad
  • Noll eller fler rubrikfält (Allmänt|Svar|Entitet) följt av CRLF
  • En tom rad (dvs. en rad med ingenting som föregår CRLF) som indikerar slutet av rubrikfälten
  • Eventuellt en meddelandetext
  • Följande avsnitt förklarar vart och ett av de enheter som används i ett HTTP-svarsmeddelande.

    Meddelandestatusrad

    En Status-Line består av protokollversionen följt av en numerisk statuskod och dess tillhörande textfras. Elementen är åtskilda av SP-tecken.

Status-Line = HTTP-version SP Status-Code SP Orsak-fras CRLF HTTP-version

En server som stöder HTTP version 1.1 kommer att returnera följande versionsinformation:

HTTP-version = HTTP/1.1

Statuskod

Statuskodelementet är ett 3-siffrigt heltal där den första siffran i statuskoden definierar svarsklassen och de två sista siffrorna inte har någon kategoriseringsroll. Det finns 5 värden för den första siffran:

S.N. Kod och beskrivning
1 1xx: Information

Det betyder att begäran mottogs och processen fortsätter.

2 2xx: Framgång

Det betyder att åtgärden mottogs, förstods och accepterades.

3 3xx: Omdirigering

Det betyder att ytterligare åtgärder måste vidtas för att fullfölja begäran.

4 4xx: Klientfel

Det betyder att begäran innehåller felaktig syntax eller inte kan uppfyllas.

5 5xx: Serverfel

Det betyder att servern inte kunde uppfylla en uppenbarligen giltig begäran.

HTTP-statuskoder kan utökas och HTTP-applikationer krävs inte för att förstå innebörden av alla registrerade statuskoder. En lista över alla statuskoder finns i ett separat kapitel för din referens.

Fält för svarshuvud

Vi kommer att studera General-header och Entity-header i ett separat kapitel när vi kommer att lära oss HTTP-rubrikfält. För nu, låt oss kontrollera vad svarsrubrikfält är.

Svarshuvudfälten tillåter servern att skicka ytterligare information om svaret som inte kan placeras i statusraden. Dessa rubrikfält ger information om servern och om ytterligare åtkomst till resursen som identifieras av Request-URI.

  • Proxy-autentisera

  • WWW-Autentisera

Du kan introducera dina anpassade fält om du ska skriva din egen anpassade webbklient och server.

Exempel på svarsmeddelande

Låt oss nu lägga ihop allt för att bilda ett HTTP-svar för en begäran om att hämta hello.htm-sidan från webbserver kör på plats

HTTP/1.1 200 OK Datum: Mån, 27 Jul 2009 12:28:53 GMT Server: Apache/2.2.14 (Win32) Senast ändrad: Ons, 22 Jul 2009 19:15:56 GMT Innehållslängd: 88 Innehåll- Typ: text/html Anslutning: Stängd Hej världen!

Följande exempel visar ett HTTP-svarsmeddelande som visar feltillstånd när webbservern inte kunde hitta den begärda sidan:

HTTP/1.1 404 Not Found Datum: Sön, 18 Okt 2012 10:36:20 GMT Server: Apache/2.2.14 (Win32) Innehållslängd: 230 Anslutning: Stängt Innehållstyp: text/html; charset=iso-8859-1 404 Hittade inte hittades inte

Den begärda webbadressen /t.html hittades inte på den här servern.

Följande är ett exempel på ett HTTP-svarsmeddelande som visar feltillstånd när webbservern stötte på en felaktig HTTP-version i den givna HTTP-begäran:

HTTP/1.1 400 Dålig förfrågan Datum: sön, 18 okt 2012 10:36:20 GMT Server: Apache/2.2.14 (Win32) Innehållslängd: 230 Innehållstyp: text/html; charset=iso-8859-1 Anslutning: Stängd 400 Bad Request Bad Request

Din webbläsare skickade en begäran som den här servern inte kunde förstå.

Begäransraden innehöll ogiltiga tecken efter protokollsträngen.