🛡️ Øvelse 33 – Exception som angrebsvektor
ℹ️ Information
Formålet med denne øvelse er at introducere faren ved manglende håndtering af exceptions i ASP.NET Core MVC-applikationer. Hvis du har brug for at genopfriske den grundlæggende brug af exceptions i .NET Core, kan du med fordel kigge tilbage på Øvelse 21.
Når en exception bliver kastet i en webapplikation, er det vigtigt, at den aldrig bliver synlig for slutbrugeren (eller andre). En exception indeholder typisk det, der kaldes en stack trace, som viser hvilken kode, der kastede exceptionen, samt hele kæden af metodekald, der førte til kaldet af metoden, som kastede en exception. Stack trace og lignende indeholder altså information om softwarens eksekvering samt interne oplysninger om softwaren. Dette betyder, at en stack trace er en potentiel angrebsvektor, og kan derfor misbruges af trusselsaktører.
Et godt eksempel på stack trace som angrebsvektor er SQL Injection-angreb. Typisk vil sådan et angreb starte med, at angriberen forsøger at fremprovokere en fejl i applikationen ved at indsætte enten ' eller ; karakterer i et tekstfelt. Såfremt der opstår en fejl som følge af disse karakterer, er det meget sandsynligt, at applikationen er sårbar over for SQL Injection-angreb. Hvis den fremprovokerede fejl viser en SQL exception med stack trace, er applikationen helt sikkert sårbar over for SQL Injection-angreb, og den fjendtlige aktør opnår samtidig viden om implementeringen samt den del af koden, som kastede exceptionen.
🔐 Kobling til sikkerhedsprincipper: Fail Open og Fail Insecurely
Denne form for fejlreaktion er et klassisk eksempel på både fail open og fail insecurely:
- Fail Open: Systemet håndterer ikke fejlen korrekt og vælger at fortsætte – det returnerer en detaljeret stack trace i stedet for at afbryde sikkert. Det er en tilladende adfærd, hvor systemet "åbner op", i stedet for at lukke ned.
- Fail Insecurely: Den fejl, som vises, indeholder følsomme oplysninger om systemets indre struktur, f.eks. databasefelter, SQL-syntaks og præcise kodelinjer. Det giver angriberen en information og potentiel angrebsvektor.
Når en applikation ikke håndterer fejl sikkert, bliver det i sig selv en angrebsvektor. En teknisk fejl eskalerer til en sikkerhedsfejl, fordi systemet ikke følger princippet om fail secure – altså at fejle på en måde, der beskytter systemets fortrolighed, integritet og tilgængelighed.
I denne øvelse skal du først fremprovokere en fejl, som resulterer i, at der vises en stack trace fra en SQLException. Herefter skal du arbejde med håndtering af exception i ASP.NET Core.
Projektet, du skal arbejde med og klone, er WebGoat.
📝 Instruktioner
Først skal du verificere, at applikationen virker ved at foretage et køb. Når du har verificeret applikationens almindelige virke, skal du fremprovokere en SQL exception.
Start applikationen, og verificer at den virker
-
🛠️ Gå til den mappe, hvor du har klonet projektet, og byg Docker-billedet med følgende kommando:
-
🧪 Start applikationen med denne kommando:
💡 Her simulerer vi, at miljøvariablen fejlagtigt er sat tildocker run --rm -d -p 5000:8080 --name webgoat.net -e ASPNETCORE_ENVIRONMENT=Development webgoat.netDevelopment. Dette medfører, at fejlmeddelelser og stack traces vises til brugeren – en alvorlig sikkerhedsrisiko i produktion. En ikke urealitisk konfigurations fejl -
👤 Opret en bruger i applikationen.
-
🛒 Tilføj varer til indkøbskurven og gennemfør et køb.
Fremprovoker en SQL Exception
- 🛒 Læg nogle varer i indkøbskurven.
- 🧾 Gå til checkout.
- ✍️ Udfyld alle felter i checkout. Men i feltet Name to ship to skal du tilføje karakteren
'. - 📦 Klik Place order.
- 📖 Læs exceptionen og stack trace, som bliver vist. Hvilken information får du?
- 🕵️ Stack tracen viser, at linje 52 og linje 151 i kildekoden smed exceptionen. Prøv at finde disse i kildekoden. Hvad er årsagen til, at applikationen er sårbar?
I klassen OrderRepository kan man se årsagen til sårbarheden i metoden CreateOrder:
var sql = "INSERT INTO Orders (" +
"CustomerId, EmployeeId, OrderDate, RequiredDate, ShippedDate, ShipVia, Freight, ShipName, ShipAddress, " +
"ShipCity, ShipRegion, ShipPostalCode, ShipCountry" +
") VALUES (" +
$"'{order.CustomerId}','{order.EmployeeId}','{order.OrderDate:yyyy-MM-dd}','{order.RequiredDate:yyyy-MM-dd}'," +
$"{shippedDate},'{order.ShipVia}','{order.Freight}','{order.ShipName}','{order.ShipAddress}'," +
$"'{order.ShipCity}','{order.ShipRegion}','{order.ShipPostalCode}','{order.ShipCountry}')"; + ";\nSELECT OrderID FROM Orders ORDER BY OrderID DESC LIMIT 1;";
Der bliver anvendt sammentrækning af strenge fra order-objektet, som er af typen Order. Et hurtigt kig i Order-klassen afslører, at klassen ikke håndhæver invarians eller regler af nogen slags. Endvidere har metoden Checkout i controllerklassen CheckoutController, som kalder CreateOrder-metoden i OrderRepository-klassen, ingen inputvalidering. Inputvalidering i controllerklassen, eller brug af domæneprimitiver i Order-klassen (og dermed håndhævelse af invarians), ville have kunnet mitigere denne sårbarhed.
Sammentrækning af strenge bør aldrig anvendes til at oprette SQL-forespørgsler. Såfremt det ikke kan undgås, skal der anvendes parameterized statements. Men den bedste praksis er at anvende Object-Relational Mapper (ORM), som helt undgår brugen af tekststrenge.
Øvrige dele af kildekoden anvender ORM til interaktion med databasen. Nedenstående er der vist et eksempel fra metoden CreateOrderPayment:
var orderPayment = new OrderPayment()
{
AmountPaid = Convert.ToDouble(amountPaid),
CreditCardNumber = creditCardNumber,
ApprovalCode = approvalCode,
ExpirationDate = expirationDate,
OrderId = orderId,
PaymentDate = DateTime.Now
};
_context.OrderPayments.Add(orderPayment);
_context.SaveChanges();
ORM bør altid anvendes til interaktion med databaser fra kildekoden. Der kan undtagelsesvist i meget få tilfælde være en grund til at undlade at anvende ORM, men dette er dog meget sjældent.
🤔 Refleksionsspørgsmål
- ⚠️ Hvorfor er det farligt at vise en stack trace til slutbrugeren?
- 🔍 Hvordan kan manglende håndtering af exceptions føre til større angreb som SQL Injection?
- 🛠️ Hvordan kan brugen af parameterized queries og ORM forhindre SQL Injection?
- 🔄 Hvordan hænger inputvalidering og håndhævelse af invarians sammen med sikker kodning?
- 🛡️ Hvilke andre angrebsvektorer kan opstå ved uhensigtsmæssig fejl- og undtagelseshåndtering?
🔗 Kobling til relevante standarder og principper
| Element i øvelsen | Relateret standard / princip | Kommentar |
|---|---|---|
| Håndtering af exceptions | ISO/IEC 27002:2022, afsnit 8.28 (Secure coding) | Anbefaler anvendelse af sikre kodningsprincipper, herunder korrekt håndtering af input, output og potentielle fejl, som en del af en sikker udviklingspraksis. |
| OWASP ASVS 5.0.0, kontrol 16.5 (Error Handling) | Krav om korrekt håndtering af undtagelser for at undgå informationslækager og uventet adfærd. Fail secure nævnes direkte her. | |
| Secure by Design (Johnsson et al.) | Understreger vigtigheden af at undgå at exception flows kompromitterer systemets integritet. |
💡 God håndtering af exceptions beskytter både applikationens stabilitet og mod angreb ved at forhindre, at følsomme oplysninger lækkes til brugeren.