ASP.NET Misconfiguration: Not Using Input Validation Framework
Description
ASP.NET Misconfiguration: Not Using Input Validation Framework is a vulnerability where an ASP.NET application fails to utilize the built-in validation framework for checking user input. ASP.NET provides comprehensive validation controls and mechanisms designed to verify input data before processing, but when developers bypass or ignore these frameworks, they must implement validation manually—often incompletely or incorrectly. This omission leads to various injection vulnerabilities including cross-site scripting (XSS), SQL injection, command injection, and other input-based attacks.
Risk
Failing to use ASP.NET's input validation framework creates significant security exposures. Manually implemented validation is often inconsistent, incomplete, or contains bypasses. Developers may forget to validate all input points or implement validation incorrectly. Without framework-level validation, malicious input can reach database queries causing SQL injection, be reflected in pages causing XSS, or be processed by the system enabling command injection. The validation framework provides tested, standardized validation that handles edge cases and encoding issues that manual validation frequently misses.
Solution
Implement ASP.NET's validation framework comprehensively across all input points. Use validation controls like RequiredFieldValidator, RangeValidator, RegularExpressionValidator, CompareValidator, and CustomValidator on all web forms. Enable request validation at the application level and avoid disabling it unless absolutely necessary with proper alternatives. Use model validation with data annotations in MVC applications. Implement input validation on both client and server sides—client-side validation improves user experience, but server-side validation is essential for security. Validate that data types, lengths, formats, and ranges match expected values.
Common Consequences
| Impact | Details |
|---|---|
| Integrity | Scope: Integrity Unexpected State - Unchecked input leads to cross-site scripting, process control, and SQL injection vulnerabilities, causing unexpected application state and data integrity violations. |
Example Code
Vulnerable Code
<%-- Vulnerable: ASP.NET Web Form without validation --%>
<%@ Page Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html>
<html>
<head>
<title>User Registration</title>
</head>
<body>
<form id="form1" runat="server">
<!-- Vulnerable: No validation on any fields -->
<div>
<label>Username:</label>
<asp:TextBox ID="txtUsername" runat="server" />
<!-- Missing: RequiredFieldValidator, RegularExpressionValidator -->
</div>
<div>
<label>Email:</label>
<asp:TextBox ID="txtEmail" runat="server" />
<!-- Missing: Email format validation -->
</div>
<div>
<label>Age:</label>
<asp:TextBox ID="txtAge" runat="server" />
<!-- Missing: RangeValidator for numeric range -->
</div>
<div>
<label>Phone:</label>
<asp:TextBox ID="txtPhone" runat="server" />
<!-- Missing: RegularExpressionValidator for phone format -->
</div>
<div>
<label>Comments:</label>
<asp:TextBox ID="txtComments" runat="server" TextMode="MultiLine" />
<!-- Missing: Any validation, vulnerable to XSS -->
</div>
<asp:Button ID="btnSubmit" runat="server" Text="Register"
OnClick="btnSubmit_Click" />
</form>
</body>
</html>
// Vulnerable: Code-behind without validation
public partial class Registration : System.Web.UI.Page
{
protected void btnSubmit_Click(object sender, EventArgs e)
{
// Vulnerable: Directly using unvalidated input
string username = txtUsername.Text;
string email = txtEmail.Text;
string age = txtAge.Text;
string phone = txtPhone.Text;
string comments = txtComments.Text;
// Vulnerable: SQL Injection
string query = "INSERT INTO Users (Username, Email, Age, Phone, Comments) " +
$"VALUES ('{username}', '{email}', {age}, '{phone}', '{comments}')";
ExecuteQuery(query);
// Vulnerable: XSS when displaying back to user
Response.Write($"<h2>Welcome, {username}!</h2>");
Response.Write($"<p>Your comments: {comments}</p>");
}
}
// Vulnerable: ASP.NET MVC without model validation
public class VulnerableUserController : Controller
{
// Vulnerable: No model validation
[HttpPost]
public ActionResult Register(string username, string email, int age, string phone)
{
// Vulnerable: No validation before processing
// Direct use of parameters enables injection attacks
// Vulnerable: String concatenation SQL
var query = $"INSERT INTO Users VALUES ('{username}', '{email}', {age}, '{phone}')";
db.Database.ExecuteSqlCommand(query);
// Vulnerable: Unencoded output
ViewBag.Message = $"Welcome {username}!";
return View();
}
}
// Vulnerable: Model without validation attributes
public class UserModel
{
public string Username { get; set; } // No [Required], [StringLength]
public string Email { get; set; } // No [EmailAddress]
public int Age { get; set; } // No [Range]
public string Phone { get; set; } // No [Phone] or [RegularExpression]
}
<!-- Vulnerable: web.config disabling request validation -->
<configuration>
<system.web>
<!-- Vulnerable: Request validation disabled entirely -->
<pages validateRequest="false" />
<!-- Vulnerable: HTTP runtime validation disabled -->
<httpRuntime requestValidationMode="2.0" />
</system.web>
<!-- Vulnerable: Allowing dangerous HTML -->
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
</configuration>
Fixed Code
<%-- Fixed: ASP.NET Web Form with comprehensive validation --%>
<%@ Page Language="C#" AutoEventWireup="true" ValidateRequest="true" %>
<!DOCTYPE html>
<html>
<head>
<title>User Registration</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ValidationSummary ID="ValidationSummary1" runat="server"
HeaderText="Please correct the following errors:"
DisplayMode="BulletList" CssClass="validation-summary" />
<div>
<label>Username:</label>
<asp:TextBox ID="txtUsername" runat="server" MaxLength="50" />
<!-- Fixed: Required field validation -->
<asp:RequiredFieldValidator ID="rfvUsername" runat="server"
ControlToValidate="txtUsername"
ErrorMessage="Username is required"
Display="Dynamic" CssClass="error" />
<!-- Fixed: Format validation -->
<asp:RegularExpressionValidator ID="revUsername" runat="server"
ControlToValidate="txtUsername"
ValidationExpression="^[a-zA-Z0-9_]{3,50}$"
ErrorMessage="Username must be 3-50 alphanumeric characters"
Display="Dynamic" CssClass="error" />
</div>
<div>
<label>Email:</label>
<asp:TextBox ID="txtEmail" runat="server" MaxLength="100" />
<asp:RequiredFieldValidator ID="rfvEmail" runat="server"
ControlToValidate="txtEmail"
ErrorMessage="Email is required"
Display="Dynamic" CssClass="error" />
<!-- Fixed: Email format validation -->
<asp:RegularExpressionValidator ID="revEmail" runat="server"
ControlToValidate="txtEmail"
ValidationExpression="^[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}$"
ErrorMessage="Please enter a valid email address"
Display="Dynamic" CssClass="error" />
</div>
<div>
<label>Age:</label>
<asp:TextBox ID="txtAge" runat="server" MaxLength="3" />
<asp:RequiredFieldValidator ID="rfvAge" runat="server"
ControlToValidate="txtAge"
ErrorMessage="Age is required"
Display="Dynamic" CssClass="error" />
<!-- Fixed: Range validation -->
<asp:RangeValidator ID="rvAge" runat="server"
ControlToValidate="txtAge"
MinimumValue="13" MaximumValue="120"
Type="Integer"
ErrorMessage="Age must be between 13 and 120"
Display="Dynamic" CssClass="error" />
</div>
<div>
<label>Phone:</label>
<asp:TextBox ID="txtPhone" runat="server" MaxLength="20" />
<!-- Fixed: Phone format validation -->
<asp:RegularExpressionValidator ID="revPhone" runat="server"
ControlToValidate="txtPhone"
ValidationExpression="^[\d\s\-\+\(\)]{10,20}$"
ErrorMessage="Please enter a valid phone number"
Display="Dynamic" CssClass="error" />
</div>
<div>
<label>Comments:</label>
<asp:TextBox ID="txtComments" runat="server" TextMode="MultiLine"
MaxLength="500" />
<!-- Fixed: Custom validator for additional checks -->
<asp:CustomValidator ID="cvComments" runat="server"
ControlToValidate="txtComments"
OnServerValidate="ValidateComments"
ErrorMessage="Comments contain invalid content"
Display="Dynamic" CssClass="error" />
</div>
<asp:Button ID="btnSubmit" runat="server" Text="Register"
OnClick="btnSubmit_Click" />
</form>
</body>
</html>
// Fixed: Code-behind with proper validation
using System.Web.Security.AntiXss;
public partial class Registration : System.Web.UI.Page
{
protected void ValidateComments(object source, ServerValidateEventArgs args)
{
// Fixed: Custom validation logic
string comments = args.Value;
// Check for maximum length
if (comments.Length > 500)
{
args.IsValid = false;
return;
}
// Check for dangerous patterns
string[] dangerousPatterns = { "<script", "javascript:", "onerror=", "onload=" };
foreach (var pattern in dangerousPatterns)
{
if (comments.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0)
{
args.IsValid = false;
return;
}
}
args.IsValid = true;
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
// Fixed: Check page validation
if (!Page.IsValid)
{
return;
}
// Fixed: Use parameterized queries
using (var connection = new SqlConnection(connectionString))
{
var command = new SqlCommand(
"INSERT INTO Users (Username, Email, Age, Phone, Comments) " +
"VALUES (@Username, @Email, @Age, @Phone, @Comments)", connection);
command.Parameters.AddWithValue("@Username", txtUsername.Text.Trim());
command.Parameters.AddWithValue("@Email", txtEmail.Text.Trim());
command.Parameters.AddWithValue("@Age", int.Parse(txtAge.Text));
command.Parameters.AddWithValue("@Phone", txtPhone.Text.Trim());
command.Parameters.AddWithValue("@Comments", txtComments.Text.Trim());
connection.Open();
command.ExecuteNonQuery();
}
// Fixed: HTML encode output
string encodedUsername = AntiXssEncoder.HtmlEncode(txtUsername.Text, true);
Response.Write($"<h2>Welcome, {encodedUsername}!</h2>");
}
}
// Fixed: ASP.NET MVC with model validation
using System.ComponentModel.DataAnnotations;
// Fixed: Model with validation attributes
public class UserModel
{
[Required(ErrorMessage = "Username is required")]
[StringLength(50, MinimumLength = 3,
ErrorMessage = "Username must be 3-50 characters")]
[RegularExpression(@"^[a-zA-Z0-9_]+$",
ErrorMessage = "Username can only contain letters, numbers, and underscores")]
public string Username { get; set; }
[Required(ErrorMessage = "Email is required")]
[EmailAddress(ErrorMessage = "Please enter a valid email address")]
[StringLength(100)]
public string Email { get; set; }
[Required(ErrorMessage = "Age is required")]
[Range(13, 120, ErrorMessage = "Age must be between 13 and 120")]
public int Age { get; set; }
[Phone(ErrorMessage = "Please enter a valid phone number")]
[StringLength(20)]
public string Phone { get; set; }
[StringLength(500, ErrorMessage = "Comments cannot exceed 500 characters")]
public string Comments { get; set; }
}
// Fixed: Controller with validation
public class UserController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken] // Fixed: CSRF protection
public ActionResult Register(UserModel model)
{
// Fixed: Check model validation
if (!ModelState.IsValid)
{
return View(model);
}
// Fixed: Use parameterized queries via Entity Framework
using (var context = new AppDbContext())
{
var user = new User
{
Username = model.Username.Trim(),
Email = model.Email.Trim(),
Age = model.Age,
Phone = model.Phone?.Trim(),
Comments = model.Comments?.Trim()
};
context.Users.Add(user);
context.SaveChanges();
}
// Fixed: Use HtmlEncode in views via Razor
TempData["Message"] = model.Username;
return RedirectToAction("Success");
}
}
<!-- Fixed: web.config with proper security settings -->
<configuration>
<system.web>
<!-- Fixed: Request validation enabled (default) -->
<pages validateRequest="true" />
<!-- Fixed: Modern request validation mode -->
<httpRuntime targetFramework="4.8" requestValidationMode="4.5" />
<!-- Fixed: Custom errors to hide details -->
<customErrors mode="On" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/NotFound" />
<error statusCode="500" redirect="~/Error/ServerError" />
</customErrors>
</system.web>
<!-- Fixed: Request filtering with limits -->
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="false">
<requestLimits maxAllowedContentLength="10485760"
maxQueryString="2048"
maxUrl="4096" />
<denyQueryStringSequences>
<add sequence="<script" />
<add sequence="javascript:" />
</denyQueryStringSequences>
</requestFiltering>
</security>
</system.webServer>
</configuration>
CVE Examples
No specific CVEs are listed in the MITRE database for this CWE. However, input validation failures in ASP.NET applications have contributed to numerous XSS and SQL injection vulnerabilities in web applications.
References
- MITRE Corporation. "CWE-554: ASP.NET Misconfiguration: Not Using Input Validation Framework." https://cwe.mitre.org/data/definitions/554.html
- Microsoft. "ASP.NET Validation Controls."
- OWASP. "Input Validation Cheat Sheet."