.NET / ASP.NET code auditing
TL;DR: ASP.NET audits split into Framework (.NET 4.x, full IIS) and Core (.NET 6+, Kestrel). Same bug families — deserialization RCE, ViewState abuse, SSRF, SQLi via raw queries, Razor SSTI, weak crypto — but the sink names and pipeline shapes differ. Map controllers, find the sinks in dangerous-aspnet-sinks, check the binder for mass-assignment.
What it is
.NET source review on a Web/MVC/WebAPI app is a high-yield audit target because Microsoft made dangerous defaults easy: BinaryFormatter ships in the BCL, ViewState MAC is sometimes disabled, EF Core’s FromSqlRaw is one call away, and Razor’s @Html.Raw looks innocent. The discipline mirrors java-code-auditing — enumerate request entry points, classify sinks by impact, trace binders backwards.
Preconditions / where it applies
- Source (
*.cs,*.cshtml,*.csproj) — or decompiled assemblies via dnSpy / ILSpy - Framework version — .NET Framework 4.x and .NET Core/5+/6+/8+ have different sink surfaces
- Knowledge of ASP.NET routing (
MapControllerRoute, attribute routing, minimal APIs)
Technique
- Map entry points.
- Classic MVC/WebAPI: classes ending in
Controller, methods with[HttpGet]/[HttpPost]/[Route(...)],ApiController. - Minimal APIs (.NET 6+):
app.MapGet("/...", (...) => ...)lambdas inProgram.cs. - SignalR hubs: classes inheriting
Hub. - Web Forms (.NET Framework):
*.aspx.cscode-behind,Page_Load, postback handlers.
- Classic MVC/WebAPI: classes ending in
- Trace sources. Action parameters bound from
[FromBody],[FromQuery],[FromRoute],[FromForm],[FromHeader]. WatchHttpContext.Request.Form/Query/Headers/Body,Request.RouteValues, and Web FormsRequest[...]. Model-binder reflection means any public setter on a bound model is reachable. - Sink catalogue. Top-impact list:
1 2 3 4 5 6
rg -n '\bBinaryFormatter|LosFormatter|NetDataContractSerializer|ObjectStateFormatter|SoapFormatter|JavaScriptSerializer|TypeNameHandling\s*=\s*TypeNameHandling\.(All|Auto|Objects)' . rg -n 'FromSqlRaw|ExecuteSqlRaw|SqlCommand\(.*\$|new\s+SqlCommand\(\s*\$' . rg -n 'Process\.Start|new ProcessStartInfo' . rg -n 'XmlReader\.Create\([^)]*\)|XmlDocument\(\)|DtdProcessing\s*=\s*DtdProcessing\.Parse|XmlResolver\s*=\s*new\s+XmlUrlResolver' . rg -n '@Html\.Raw|Razor\.Parse|RazorEngine\.Compile|@\{[^}]*\}' . rg -n 'WebRequest\.Create\(|HttpClient.*\.GetAsync\(\$|HttpClient.*\.PostAsync\(\$' .
- ViewState (Framework only). Check
<pages enableViewStateMac="false">or<machineKey>exposed in repo — both lead toLosFormatter/ObjectStateFormatterRCE. See viewstate-attacks. - Newtonsoft.Json
TypeNameHandling. Anything other thanNoneplus a$typefield in attacker JSON = arbitrary type instantiation → deserialization RCE chain. System.Text.Json’sJsonSerializerOptions.TypeInfoResolverpolymorphism is safer but still abusable when type discriminators are user-controlled. - Mass-assignment. Binding a request body to an EF entity directly (
public IActionResult Update([FromBody] User u)) exposes every public setter, includingIsAdmin. Audit DTO/ViewModel boundaries; flag any_db.Users.Update(u)on a directly-bound entity. - Razor SSTI. Server compiles
@(...)Razor with full C# reflection. If an admin panel doesRazorEngine.Razor.Parse(userTemplate), that’s RCE. Even@Html.Raw(userInput)is XSS, not SSTI — but Razor templates loaded from user-writable storage (DB, S3) is. - Crypto and tokens.
MD5/SHA1for password hashing, hard-codedmachineKey, signed tokens without expiry check, JWTnoneallowed (TokenValidationParameters.ValidateLifetime=falsein audit logs). - Static tooling. Microsoft DevSkim, SecurityCodeScan (Roslyn analyzer),
dotnet list package --vulnerablefor known-CVE deps, Semgrepcsharp.lang.security.
Detection and defence
- Ban
BinaryFormatteroutright (it’s obsolete in .NET 8+). Migrate toSystem.Text.Jsonwith disabled polymorphism. - Use parameterised LINQ / EF Core methods;
FromSqlRawonly with parameters{0}not string interpolation. - Enforce
DtdProcessing.ProhibitandXmlResolver = nullon everyXmlReader/XmlDocument. - Bind to DTOs, never entities. Use
[Bind]whitelists for legacy MVC. - Ship Roslyn analyzers in CI; treat warnings as errors.