Sandbox Escape in Aspnet
How Sandbox Escape Manifests in Aspnet
ASP.NET's sandbox escape vulnerabilities typically occur when untrusted input flows through the application's object graph and reaches privileged execution contexts. In ASP.NET Core specifically, the model binding system and dynamic code execution features create several attack vectors that can lead to sandbox escape.
One common pattern involves the System.Text.Json deserializer, which can instantiate arbitrary types when deserializing JSON payloads. Consider this vulnerable controller action:
public class UserController : ControllerBase
{
[HttpPost("create")]
public IActionResult CreateUser([FromBody] UserDto user)
{
// Object graph traversal can reach dangerous types
var processed = ProcessUser(user);
return Ok(processed);
}
}
public class UserDto
{
public string Name { get; set; }
public object Data { get; set; }
}
public class DangerousType
{
public void Execute()
{
// Can access file system, network, or other resources
System.IO.File.WriteAllText("/tmp/escape.txt", "Sandbox escaped!");
}
}The vulnerability here is that UserDto.Data accepts object, allowing an attacker to craft JSON that instantiates DangerousType and executes its constructor or methods during deserialization.
Another ASP.NET-specific vector involves System.Linq.Dynamic.Core or similar dynamic LINQ providers. When user input is passed directly to dynamic query methods, it can execute arbitrary code:
public class ProductController : ControllerBase
{
[HttpGet("search")]
public IActionResult Search([FromQuery] string filter)
{
var products = dbContext.Products
.Where(filter) // Dynamic LINQ injection
.ToList();
return Ok(products);
}
}An attacker could supply filter=1=1; System.IO.File.Delete("C:\\important.txt") to execute arbitrary commands.
ASP.NET Web Forms applications face additional risks through <%= %> expressions and Page.DataBind() operations that can evaluate expressions containing dangerous method calls. The ViewState mechanism can also be exploited to inject serialized objects that execute code during deserialization.
ASP.NET-Specific Detection
Detecting sandbox escape vulnerabilities in ASP.NET applications requires examining both the code structure and runtime behavior. Static analysis tools should flag dangerous patterns like:
[FromBody] objector[FromQuery] objectparameters- Dynamic LINQ usage with user input
- Reflection-based type instantiation from untrusted sources
- ViewState with viewstateEncryptionMode="Always" (can hide malicious payloads)
- Use of
Type.GetType()orActivator.CreateInstance()with user input
Dynamic analysis through black-box scanning tools like middleBrick can identify sandbox escape attempts by testing for:
POST /api/users/create HTTP/1.1
Host: example.com
Content-Type: application/json
{
"$type": "System.Diagnostics.Process, System.Diagnostics.Process"
}This JSON payload attempts to force the deserializer to create a Process object, which could lead to command execution if the vulnerability exists.
middleBrick's black-box scanning approach tests for sandbox escape by sending specially crafted payloads that attempt to:
- Trigger type confusion through polymorphic deserialization
- Execute dynamic code via LINQ providers
- Access restricted resources through reflection
- Escape the application's security context
The scanner evaluates whether the application's response indicates successful exploitation, such as unexpected error messages, timing differences, or access to protected resources.
ASP.NET-Specific Remediation
Remediating sandbox escape vulnerabilities in ASP.NET requires a defense-in-depth approach. Start with strict type validation during model binding:
public class UserController : ControllerBase
{
[HttpPost("create")]
public IActionResult CreateUser([FromBody] UserDto user)
{
// Validate type before processing
if (user.Data != null && user.Data.GetType() != typeof(string))
{
return BadRequest("Invalid data type");
}
var processed = ProcessUser(user);
return Ok(processed);
}
}For dynamic LINQ scenarios, use parameterized queries instead of string concatenation:
public class ProductController : ControllerBase
{
[HttpGet("search")]
public IActionResult Search([FromQuery] string name)
{
var products = dbContext.Products
.Where(p => p.Name.Contains(name))
.ToList();
return Ok(products);
}
}ASP.NET Core provides additional security through the JsonSerializerOptions configuration:
services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
// Prevent type confusion attacks
options.JsonSerializerOptions.AllowTrailingCommas = false;
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Disallow;
});
For Web Forms applications, disable ViewState encryption for debugging and validate all <asp: controls:
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default"
ViewStateEncryptionMode="Always" %>
<asp:ScriptManager ID="ScriptManager1" runat="server"
EnableScriptGlobalization="false"
EnableScriptLocalization="false" />
Implement Content Security Policy headers to restrict script execution:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline';");
await next();
});
}Finally, use middleBrick's continuous monitoring to ensure sandbox escape vulnerabilities don't reappear as your codebase evolves. The Pro plan's CI/CD integration can automatically scan your staging APIs before deployment, failing builds if new vulnerabilities are detected.