Type Confusion on Azure
How Type Confusion Manifests in Azure
Type confusion in Azure environments often emerges through deserialization vulnerabilities, dynamic object handling, and interface polymorphism. In Azure Functions and Azure App Services, this manifests when serialized objects are deserialized without strict type validation, allowing attackers to manipulate object types during the deserialization process.
A common Azure-specific scenario involves Azure Table Storage or Cosmos DB operations where entities are deserialized into strongly-typed objects. Consider this vulnerable Azure Function:
[FunctionName("ProcessUserData")]
public static async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "process")] HttpRequestData req,
ILogger log)
{
var body = await new StreamReader(req.Body).ReadToEndAsync();
var userData = JsonConvert.DeserializeObject<UserData>(body); // Type confusion risk
// Process user data without type validation
await ProcessDataAsync(userData);
return req.CreateResponse(HttpStatusCode.OK);
}
public class UserData
{
public string UserId { get; set; }
public string Data { get; set; }
}
An attacker could send a JSON payload that, when deserialized, creates a different object type than expected. For instance, if the backend expects a UserData object but receives a malicious AdminData object due to type confusion, it could lead to privilege escalation.
Azure Service Bus and Azure Event Grid are also susceptible when handling polymorphic message types. The Azure SDK's default deserialization behavior can be exploited if message schemas aren't strictly validated:
// Vulnerable Azure Service Bus message handler
[FunctionName("ProcessMessage")]
public static async Task Run(
[ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] object message,
ILogger log)
{
// No type validation - type confusion possible
var typedMessage = message as CustomMessage;
if (typedMessage != null)
{
await ProcessMessageAsync(typedMessage);
}
}
Azure's managed identity system can also be compromised through type confusion in token validation. When Azure AD tokens are parsed without proper type checking, an attacker might manipulate token claims to escalate privileges.
Azure-Specific Detection
Detecting type confusion in Azure requires a multi-layered approach combining static analysis, runtime monitoring, and specialized scanning tools. Azure Security Center and Defender for Cloud provide some detection capabilities, but they often miss subtle type confusion vulnerabilities.
middleBrick's Azure-specific scanning identifies type confusion through several mechanisms:
- Runtime Type Analysis: Examines the actual types being deserialized and processed at runtime
- Schema Validation: Checks if incoming data matches expected schemas before processing
- Interface Implementation Verification: Validates that objects implement expected interfaces before casting
- Serialization Boundary Testing: Tests how different data types are handled across Azure service boundaries
Here's how you'd scan an Azure Function for type confusion vulnerabilities using middleBrick:
npx middlebrick scan https://myazurefunction.azurewebsites.net/api/ProcessUserData --output json
The scanner tests for type confusion by sending crafted payloads that attempt to confuse the deserialization process. For Azure-specific endpoints, it includes tests for:
| Test Type | Azure Target | Detection Method |
|---|---|---|
| Deserialization Confusion | Azure Functions | Polymorphic JSON payloads |
| Interface Confusion | Azure Service Bus | Interface casting attacks |
| Token Type Confusion | Azure AD | Malformed JWT claims |
| Storage Entity Confusion | Azure Table Storage | Entity type manipulation |
For Azure DevOps pipelines, you can integrate type confusion detection directly into your CI/CD:
- name: Scan Azure Function
run: |
npx middlebrick scan ${{ secrets.AZURE_FUNCTION_URL }} --output json
continue-on-error: true
- name: Check Scan Results
run: |
if [ $(jq '.score' scan-results.json) -lt 80 ]; then
echo "Type confusion vulnerabilities detected!"
exit 1
fi
Azure Monitor and Application Insights can also help detect type confusion at runtime by monitoring for unusual type conversions and deserialization errors in your Azure applications.
Azure-Specific Remediation
Remediating type confusion in Azure environments requires strict type validation, secure deserialization practices, and leveraging Azure's built-in security features. The key principle is never to trust deserialized data without validation.
For Azure Functions, implement strict type validation before processing:
[FunctionName("ProcessUserData")]
public static async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "process")] HttpRequestData req,
ILogger log)
{
try
{
var body = await new StreamReader(req.Body).ReadToEndAsync();
// Strict type validation
var userData = JsonConvert.DeserializeObject<UserData>(body);
if (userData == null || string.IsNullOrEmpty(userData.UserId))
{
return req.CreateResponse(HttpStatusCode.BadRequest, "Invalid data format");
}
// Whitelist allowed properties
if (!IsValidUserData(userData))
{
return req.CreateResponse(HttpStatusCode.BadRequest, "Unauthorized data structure");
}
await ProcessDataAsync(userData);
return req.CreateResponse(HttpStatusCode.OK);
}
catch (JsonReaderException ex)
{
log.LogWarning(ex, "Deserialization failed");
return req.CreateResponse(HttpStatusCode.BadRequest, "Invalid JSON format");
}
}
private static bool IsValidUserData(UserData data)
{
// Whitelist validation - only allow expected properties
var allowedProperties = new[] { nameof(UserData.UserId), nameof(UserData.Data) };
var dataProperties = data.GetType().GetProperties().Select(p => p.Name);
return dataProperties.All(p => allowedProperties.Contains(p));
}
For Azure Service Bus, use strongly-typed message handlers with explicit type checking:
// Secure message handler with type validation
[FunctionName("ProcessMessage")]
public static async Task Run(
[ServiceBusTrigger("myqueue", Connection = "ServiceBusConnection")] Message message,
ILogger log)
{
try
{
var messageBody = message.Body.ToString();
var typedMessage = JsonConvert.DeserializeObject<CustomMessage>(messageBody);
// Validate message type and required properties
if (typedMessage == null || typedMessage.MessageType != "ExpectedType")
{
log.LogWarning("Invalid message type received");
return;
}
await ProcessMessageAsync(typedMessage);
}
catch (Exception ex)
{
log.LogError(ex, "Message processing failed");
}
}
Azure's managed identity system provides additional protection when configured correctly. Use Azure AD's token validation libraries to ensure proper type checking:
// Secure token validation with type checking
public static async Task<ClaimsPrincipal> ValidateTokenAsync(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://sts.windows.net/{tenant-id}/",
ValidateAudience = true,
ValidAudience = "api://your-api-identifier",
ValidateLifetime = true,
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
// Ensure token is from Azure AD
return GetAzureADSigningKeys();
}
};
try
{
var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
// Additional type validation
var claims = principal.Claims.ToList();
if (!claims.Any(c => c.Type == "role" && c.Value == "expected-role"))
{
throw new SecurityTokenValidationException("Invalid role claim");
}
return principal;
}
catch (Exception ex)
{
throw new SecurityTokenValidationException("Token validation failed", ex);
}
}
For Azure Storage operations, use strongly-typed entities with explicit type mapping:
public class SecureTableEntity : TableEntity
{
public string UserId { get; set; }
public string Data { get; set; }
public override void ReadEntity(IDictionary<string, EntityProperty> properties, OperationContext operationContext)
{
// Strict property validation
if (!properties.ContainsKey("UserId") || !properties.ContainsKey("Data"))
{
throw new InvalidOperationException("Missing required properties");
}
base.ReadEntity(properties, operationContext);
}
}
Enable Azure Defender for App Service and Azure Defender for Functions to get automated detection of deserialization and type confusion vulnerabilities in your Azure environment.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |