Source: MSDN
Translation: Yunzhongcheng BLOG
application scope:
ASP.NET version 1.1
ASP.NET version 2.0
Summary:
This text mainly introduces how to verify user input to prevent injection attacks. It is very necessary to verify user input. Almost all program-level attacks contain malicious input methods.
You should verify including fields, query string parameters, Cookies and other user input items are used to protect your program from injection attacks. You have to assume that all user input is malicious and ensure that all user input is verified on the server side. Using client-based validation can reduce the page's Improve the number of stays, improve performance, and improve user experience, but don't rely solely on this, because client-side validation can easily be fooled by hackers.
In order to validate input content, you should define acceptable input rules for each input field. A better approach is to make constraints based on the length, range, format, and type of the input field. Use an acceptable character constraint list instead of an illegal character list to constrain input. Using illegal character list constraints is not good because you almost It is impossible to filter all harmful input.
If you need to accept HTML character input, it is best to use a method such as HtmlEncode to encode it safely before displaying it.
Content:
Purpose
Overview
Step-by-Step Implementation Feed
Step 1. Using ASP .NET request verification.
Step 2. Use rights constraint input.
Step 3. Encode unsafe input.
Step 4. Use command parameters for Sql statements.
Step 5. Verify ASP.NET errors. are not returned to the client.
Additional resources
-------------------------------------------------- ------------------------------
Purpose:
Constrain the input string length, range, format and type.
Use request validation to prevent injection attacks when developing ASP.NET programs.
Use ASP.NET validation controls for input validation.
Encode unsafe output.
Prevent injection attacks using command parameter set pattern.
Prevent error details from being returned to the client.
Overview:
You should validate all untrusted input in your application. You should assume that all user input is invalid. Users can provide form fields, query strings, client cookies and browser environment values in the application such as user Proxy strings and IP addresses, etc.
Weak input validation usually provides opportunities for injection attacks. The following are common methods of attack using weak input validation or no input validation.
SQL injection. If you use user input values to dynamically construct SQL statements, the database may execute offensive and harmful SQL statements.
Cross-site scripting. Cross-site scripting attacks exploit web page validation vulnerabilities to inject client-side scripts. These codes are then sent to the trusted client computer and interpreted and executed by the browser. Because these codes come from trusted site, so the browser has no way of knowing that the code is harmful.
Unauthorized file access. If your code accepts input from the caller, a malicious user can see your file operations and access protected files or use your code to inject illegal data.
Note: Injection attacks can be made by using HTTP or HTTPS Secure Socket Layer (SSL) connections. Transport encryption techniques cannot be used to prevent attacks.
Common input validation methods are summarized below. You should perform validation everywhere that input is required over the network, such as Text boxes and other form input fields, query string parameters, cookies, server-side variables and network method parameters. Note that the filtering strategy should only allow correct input and reject illegal input. This is because defining the correct input strategy is better than filtering all It is easier to detect illegal input, but it is usually difficult to include all illegal input.
Verify the input content through the following aspects:
Constraints. Verify that the input is of the correct type, character length, format, and range. ASP.NET validation controls can be applied to constrain server control input. Regular expressions and custom validation rules can be used to constrain input from other sources.
Reject. Detect known harmful data input and reject it.
Filtering. Sometimes you will want to filter out those parts of user input that pose security risks. For example, if your application allows free-form input, such as memo fields, you will allow certain safe HTML tags like <b>, <i > and other HTML tags.
Step Summary
Protect your ASP.NET application from injection attacks by following these steps:
Step 1. Use ASP.NET request verification.
Step 2. Constrain input.
Step 3. Encode unsafe output.
Step 4. Use command parameters for SQL query statements.
Step 5. Verify that ASP.NET error information is not leaked to the client.
The following chapters will discuss these steps in detail.
Step 1. Use ASP.NET request validation.
By default, ASP.NET 1.1 and 2.0 request validation checks whether the data sent to the server contains HTML markup elements and reserved characters. This prevents users from entering scripts into the program. Request validation will be matched against a list of potentially threatening strings, and if an exception is found it will throw an exception of type HttpRequestValidationException.
You can do this in your web.config file by < Add validateRequest="false" to the pages> element or set ValidateRequest = "false" in the @Pages element of a separate page to disable this feature.
If you want to disable request validation, you can disable it only on the pages where you need it. For example, if you include a field on the program page that accepts input in HTML format,
make sure that the request validation feature is turned on in the Machine.config file
. The request validation feature is enabled by default in ASP.NET. You can do this in the Machine.config.comments file. You see the following default settings.
<pages validateRequest = "true" ... />
Make sure you have not modified the default settings in your server's Machine.config and application's Web.config files.
Test ASP.NET request validation
You can test the effect of request validation. Create an ASP.NET page and disable request validation by setting ValidateRequest = "fasle" as follows:
<%@ Language="C#" ValidateRequest="false" %>
<html>
<script runat="server">
void btnSubmit_Click(Object sender, EventArgs e)
{
// If ValidateRequest is false, then 'hello' is displayed
// If ValidateRequest is true, then ASP.NET returns an exception
Response.Write(txtString.Text);
}
</script>
<body>
<form id="form1" runat="server">
<asp:TextBox id="txtString" runat="server"
Text="<script>alert('hello');</script>" />
<asp:Button id="btnSubmit" runat="server" OnClick="btnSubmit_Click"
Text="Submit" />
</form>
</body>
</html>
When you run the page, "Hello" is displayed in a message box because the script in the txtString is executed and processed by the client's browser.
If you set ValidateRequest = "true" or remove the ValidateRequest page attribute, ASP .NET request validation will reject script input and throw an error message like the one below.
A potentially dangerous Request.Form value was detected from the client (txtString="<script>alert('hello").
Be careful not to rely solely on the request verification function, but only use it as a guidance method for custom verification.
Step 2. Constrain the input
.To constrain the input, use the following method:
Use server-side input validation. Do not rely on client-side validation, as it can be easily bypassed. Use client-side validation to reduce the number of page bounces, improve performance, and improve user experience.
Validate the length, range, format and type of the input. Make sure the input content is correct and meets the requirements.
Use strong data types. Specify a type such as Integer or Double for numeric input. Specify the String data type for character input. Specify the DateTime type for date and time input.
To validate HTML control input fields in a form, perform validation in server-side code. Using the Regex regular expression type can help constrain character input. The following section describes how to constrain variables of common input types.
Validating string fields
To validate string fields such as name, address, fax, and birth certificate number, use regular expressions.
Constrains the acceptable range of characters.
Enable formatting rules. For example, pattern-based fields such as tax ID, zip code, and postal code require specified character patterns.
Verify length.
Use regular expression validation control (RegularExpresionValidator)
To use regular expression validation control, you need to set the control name to be verified (ControlToValidate), validation expression (ValidationExpression) and error message (ErrorMessage). For related property settings, please see the code example below .
<form id="WebForm" method="post" runat="server">
<asp:TextBox id="txtName" runat="server"></asp:TextBox>
<asp:RegularExpressionValidator id="nameRegex" runat="server"
ControlToValidate="txtName"
ValidationExpression="^[a-zA-Z'.s]{1,40}$"
ErrorMessage="Invalid name">
</asp:regularexpressionvalidator>
</form>
In the above code, a regular expression is used to limit the input name to letters (uppercase and lowercase letters are allowed), spaces, single-name ellipses like O'Dell and periods. Additionally, the input character length is limited to 40 characters Characters.
Note that the regular expression validation control (RegularExpressionValidator) will automatically add the caret (^) and dollar sign ($) as the starting and ending delimiters. If you have not added them in the custom expression, it is best to add them. Adding delimiters is just to let your expression get the part of the data you want.
Use the regular expression class (Regex Class)
if you are not using server-side controls (meaning you cannot use validation controls), or you need other For input field sources other than form fields (such as query string parameters and cookies), you can use a regular expression class (Regex class).
Use the regular expression class
to import the System.Text.RegularExpressions namespace by adding a statement with the using prefix.
Make sure the regular expression contains "^" and "$" (at the beginning of the string, at the end of the string).
Call the IsMatch method of the Regex class, the following is a code example.
//Instance method:
Regex reg = new Regex(@"^[a-zA-Z'.s]{1,40}$");
Response.Write(reg.IsMatch(txtName.Text));
// Static method:
if (!Regex.IsMatch(txtName.Text,@"^[a-zA-Z'.s]{1,40}$"))
{
// Name does not match expression
}
If you cannot cache frequently used regular expressions, you should use the IsMatch static method to improve performance and prevent unnecessary object creation.
Validating numeric fields
In most cases, you should validate numeric input and ranges. Use server controls To verify the input and range of numeric fields, use the RangeValidator control. RangeValidator supports currency, date, integer, double precision and string type data.
To use the RangeValidator control, you need to set the control name (ControlToValidate), type (Type), and minimum Value (MinimumValue), maximum value (MaximumValue), and error message (ErrorMessage) properties. Here is the code example:
<asp:RangeValidator
ID="RangeValidator1"
Runat="server"
ErrorMessage="Invalid range. Number must be between 0 and 255."
ControlToValidate="rangeInput"
MaximumValue="255"
MinimumValue="0" Type="Integer" />
If you are not using a server control, you can complete range verification of numbers by converting the input value to an integer and then validating it. For example, to verify whether an integer is legal, use the new method Int32.TryParse provided by ASP.NET 2.0 to convert the input value into the variable type of System.Int32. This method will return false if the conversion fails.
Int32 i;
if (Int32.TryParse(txtInput.Text, out i) == false)
{
//Conversion failed
}
If you are using an earlier version of ASP.NET, you can use the Int32.Parse or Convert.ToInt32 method in a try/catch block and handle the FormatException that is thrown when the conversion fails.
The following sample code demonstrates how to validate from HTML The type and range of the integer type of the text box.
<%@ Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
if (Request.RequestType == "POST")
{
int i;
if (Int32.TryParse(Request.Form["integerTxt"], out i) == true)
{
// TryParse returns true if the conversion succeeds
if ((0 <= i && i <= 255) == true)
{
Response.Write("Input data is valid.");
}
else
Response.Write("Input data is out of range");
}
else
Response.Write("Input data is not an integer");
}
}
</script>
<html>
<body>
<form id="form1" action="NumericInput.aspx" method="post">
<div>
Enter an integer between 0 and 255:
<input name="integerTxt" type="text" />
<input name="Submit" type="submit" value="submit" />
</div>
</form>
</body>
</html>
Validating Date Fields
You need to verify that date fields are of the correct type. In most cases, you will also need to verify their range, such as verifying whether they are in the future or in the past. If you are using a server control to capture a date input value, and if you want the value to be within a specific range, you can use the range validation control (RangeValidator) and set its allowed type to the Date type. This control allows you to specify a special time period by setting the starting moment. If you need to use today's time as a reference to verify, such as verifying whether a time is in the future or in the past, you can use the CustomValidator validation control.
Using the CustomValidator control to validate a date requires setting the ControlToValidate and ErrorMessage properties, and specifying a custom validation logic method in the OnServerValidate event. The following is sample code.
<%@ Page Language="C#" %>
<script runat="server">
void ValidateDateInFuture(object source, ServerValidateEventArgs args)
{
DateTime dt;
// Check for valid date and that the date is in the future
if ((DateTime.TryParse(args.Value, out dt) == false) ||
(dt <= DateTime.Today))
{
args.IsValid = false;
}
}
</script>
<html>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" Runat="server"
Text="Future Date:"></asp:Label>
<asp:TextBox ID="futureDatetxt" Runat="server"></asp:TextBox>
<asp:CustomValidator
ID="CustomValidator1" Runat="server"
ErrorMessage="Invalid date. Enter a date in the future."
ControlToValidate="futureDatetxt"
OnServerValidate="ValidateDateInFuture">
</asp:CustomValidator>
<br />
<asp:Button ID="submitBtn" Runat="server" Text="Submit" />
</div>
</form>
</body>
</html>
Note that the above code uses the method DateTime.TryParse which is a new method provided by ASP.NET 2.0.
To filter free text fields
to filter input, you need to ensure that unsafe input is not treated as code. For example, your program allows the user to The data in the shared database cannot be read. You first need to filter the data so that they are not dangerous when output. Use the HttpUtility.HtmlEncode method to first encode the input value.
Allows limited input HTML code
Add the following fields to the @Page page element ValidateRequest = "false" to disable ASP.NET request validation. Use the HtmlEncode method to encode the input string. Use the StringBuilder object and call its Replace method to replace the HTML in the characters. The following code gives Here is an example of this approach. This page disables ASP.NET request validation by setting ValidateRequest = "fasle". Its HTML encoding allows the use of <b> and <i> tags in order to display simple text formatting.
<%@ Page Language="C#" ValidateRequest="false"%>
<script runat="server">
void submitBtn_Click(object sender, EventArgs e)
{
// Encode the string input
StringBuilder sb = new StringBuilder(
HttpUtility.HtmlEncode(htmlInputTxt.Text));
// Selectively allow and <i>
sb.Replace("<b>", "<b>");
sb.Replace("</b>", "");
sb.Replace("<i>", "<i>");
sb.Replace("</i>", "");
Response.Write(sb.ToString());
}
</script>
<html>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="htmlInputTxt" Runat="server"
TextMode="MultiLine" Width="318px"
Height="168px"></asp:TextBox>
<asp:Button ID="submitBtn" Runat="server"
Text="Submit" OnClick="submitBtn_Click" />
</div>
</form>
</body>
</html>
Validate query string value
Validate the length, range, format, and type of a query string. Typically, you use a combined regular expression to accomplish the following tasks:
Constrain input values Set explicit range checks Specify the input type and convert it to the ASP.NET platform The following type, handles any exceptions caused by type conversions. The following code example demonstrates using the Regex class to validate the name string passed in the query string.
void Page_Load(object sender, EventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(
Request.QueryString["Name"], @"^[a-zA-Z'.s]{1,40}$"))
Response.Write("Invalid name parameter");
else
Response.Write("Name is " + Request.QueryString["Name"]);
}
Validate Cookie Values
Values stored in cookies like query strings can easily be modified by the user. Also validate the length, range, format, and type of these values.
Validate file and URL addresses.
If your program allows input of file names, file Address or file storage path, you need to verify that they are in the correct format and that it points to a valid location according to the actual situation of your program. If this verification fails, your program may be mistakenly asked to access the file.
Verify the file path
in order To prevent your program from being exploited by users to access files, prevent it from accepting files or file paths entered by user-written code. For example:
If you accept input file names, use the System.IO.Path.GetFileName method to obtain the full name of the file. If you must Accepts an input file path and uses System.IO.Path.GetFullPath to get the full file path. Use the MapPath method to prevent cross-application mapping.
If you use the MapPath method to map a provided virtual directory to a physical directory on the server, use an overloaded version of the Request.MapPath method with a bool parameter to prevent cross-application mapping. Here is sample code for this technique:
try
{
string mappedPath = Request.MapPath( inputPath.Text,
Request.ApplicationPath, false);
}
catch(HttpException)
{
// Cross-application mapping attempted
}
The final false parameter will prevent cross-application mapping. This means that users are not allowed to use the "..." syntax to provide an illegal path that is not within the virtual directory you specified.
If you use server controls, you can use the Control.MapPathSecure method to obtain the actual directory address corresponding to the virtual directory.
The Control.MapPathSecure method throws an HttpException when accessing an unauthorized file. For more information, see the Control.MapPathSecure method introduction in the .NET Framework documentation.
Using code access security to limit file input and output
Administrators can limit a program's ability to read and write files to the virtual directory where it resides by setting its credibility to "medium". The .NET code security mechanism ensures that the program does not have any file access rights outside the virtual directory where it is located.
To set the trust level of an application to "medium", you can add:
< trust level = "Medium" />
Verify URL
You can use regular expressions like the following to match URLs.
^(?:http|https|ftp)://[a-zA-Z0-9 .-]+(?::d{1,5})?(?:[A-Za-z0-9.;:@&=+$,? /]|%u[0-9A-Fa-f]{4}|%[0-9A-Fa-f]{2})*$
This only constrains the input format and does not verify whether it is acceptable in the application within the scope of your application. You should verify that it is valid within the context of your application. For example, does your application communicate with the server you specify?
Step 3. Encode unsafe code
If you enter text into a For a web page, use the HttpUtility.HtmlEncode method to encode it. If the text comes from user input, a database, or a local file, be sure to always do this.
Likewise, if you write a URL that contains unsafe characters because they come from For user input content, databases, etc., use the HttpUtility.UrlEncode method to encode.
In order to prevent encoding before storing the data, which may damage the stored data, please make sure to encode them as later steps as possible when displaying them.
Use HtmlEncode For unsafe output encoding,
HtmlEncode replaces HTML tags with special textual strings to represent these symbols and prevents the browser from interpreting them as HTML tags. For example, "<" is replaced with < " ( colon) is replaced with " These tags are displayed as harmless text.
<%@ Page Language="C#" ValidateRequest="false" %>
<script runat="server">
void submitBtn_Click(object sender, EventArgs e)
{
Response.Write(HttpUtility.HtmlEncode(inputTxt.Text));
}
</script>
<html xmlns=" http://www.w3.org/1999/xhtml " >
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="inputTxt" Runat="server"
TextMode="MultiLine" Width="382px" Height="152px">
</asp:TextBox>
<asp:Button ID="submitBtn" Runat="server" Text="Submit"
OnClick="submitBtn_Click" />
</div>
</form>
</body>
</html>
To see the effect of HTML encoding, please create a virtual directory and put the aforementioned files into it, run this page, enter some HTML code in the text box, and click the submit button. For example, the following input is displayed as ordinary text.
Run script and say hello <script>alert('hello');</script>
If you remove the call to the HtmlEncode method and simply enter the text content, the browser will execute the code and pop up a prompt box.
Using the UrlEncode method is not safe Encoding the URL address
If you need to obtain the URL parameters with the user input part, which may bring certain security risks, use the HttpUtility.UrlEncode method to encode the address string.
HttpUtility.UrlEncode(urlString);
Step 4. SQL The statement uses the command parameter method.
To avoid injection attacks, please use the SQL parameter method. The Parameters collection provides type detection and length detection. If you use the parameter collection, the input content will be treated as a text value, and the database will not The code contained in it will be executed. An additional benefit of using the parameter set method is that you can strictly limit the type and length of the input. If the input type is out of range, an exception will be triggered.
When calling a stored procedure, use the parameter set
below The code snippet demonstrates an example of using parameter sets when calling a stored procedure.
SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin",
myConnection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter parm = myCommand.SelectCommand.Parameters.Add(
"@LoginId", SqlDbType.VarChar, 11);
parm.Value = Login.Text;
Use parameter sets when creating your own SQL statements.
If you cannot use stored procedures, you can still use parameter sets, see the code below.
SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", myConnection);
SQLParameter parm = myCommand.SelectCommand.Parameters.Add(
"@au_id" ,SqlDbType.VarChar, 11);
Parm.Value = Login.Text;
For more information on how to prevent SQL injection attacks, see How to: Protect From SQL Injection in ASP.NET.
Step 5. To verify that ASP.NET error messages are not returned to the client,
you can use the <customErrors> element. To configure the client, general error messages should be returned to the client by the program error detection mechanism.
Please confirm that you have changed the mode attribute in web.config to "remoteOnly", the following is an example.
<customErrors mode = "remoteOnly">
In After installing an ASP.NET program, you can specify the client's error message page as follows.
<customErrors mode = "on" defaultRedirect = "YourErrorPage.htm">
For additional resources, please view related topics:
How to use regular expressions to constrain input in ASP.NET.
Prevent SQL injection attacks
and prevent cross-site scripting attacks.
PS: I finally finished reading it. I’m so tired. It took me nearly three days. In fact, these sentences are very simple if you look at them. This is my first time doing a translation. Please forgive me if the translation is not good, thank you.