Does ASP:Textbox TextMode Securely Enforce Input Validation?

December 11, 2023 by · Comments Off on Does ASP:Textbox TextMode Securely Enforce Input Validation?
Filed under: Development, Security 

When building .Net Webform applications, the ASP:Textbox has a TextMode property that you can set. For example, you could indicate that the text should be a number by setting the property below:

<asp:TextBox ID=”txtNumber” runat=”server” TextMode=”Number” />

As you can see in the above example, we are specifically setting the TextMode attribute to Number. You can see a list of all the available modes at: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.textboxmode?view=netframework-4.8.1.

But what does this actually mean? Is it limiting my input to just a number or can this be bypassed?

It is important to understand how this input validation works because we don’t want to make assumptions from a security perspective on what this field may contain. So many attacks start with the input and our first line of defense is input validation. Limiting a field to just a Number or a Date object can mitigate a lot of attacks. However, we need to be positive that the validation is enforced.

Let’s take a look at what this attribute is doing.

From a display standpoint, the simple code we entered above in our .ASPX page turns into the following in the browser:

<input name=”txtNumber” type=”number” id=”txtNumber” />

We can see that the TextMode attribute is controlling the Type attribute in the actual response. By default, the ASP:Textbox would return a type of Text, but here it is set to Number.

The number type will change the textbox that the user uses so that it is limiting to basically just numbers. The image below shows the new field.

Number box

If you try to submit the value with values other than numbers, it will display a message that indicates only numbers are allowed.

Number box error

** Note that the restrictions for character input in the textbox itself may differ depending on the browser. Edge will only allow numbers and the letter ‘e’ to be input at all. If you try to enter ‘test’ it will only show the ‘e’. Whereas, Firefox will allow the characters to be added to the textbox. They both will alert the error though when clicking the submit button that it can only be numbers.

This initial testing validates that there is some client-side validation going on. This is great for immediate user feedback, but not for security. We need to ensure that the validation is happening on the server as well. It is too easy to bypass client-side validation and we should never trust it. Always verify your validation at the server level.

To test the server-side validation, we will just intercept the request using a web proxy. I use Burp Suite from Portswigger. Once you have the proxy configured we can turn intercept on and wait for the form to be submitted. Remember, the client-side validation is enforcing numbers, so we need to just enter a regular number in the textbox to submit the form. We will change this to something else in the intercept window. Here we can see the number passed up in the paused request.

Intercept 1

Next, we will modify the number to a regular string.

Intercept 2

Once we click turn intercept off, the request will now get to the code-behind. Let’s see what the Server now sees as the value of the textbox.

Server text 1

We can see that the value is “someTextString”, indicating that there is no validation happening on the server side. This means that while the TextMode will cause a change to how the textbox works on the client, it doesn’t have any effect on how it works on the server.

How do we add server side validation?

There are a few ways to do this, depending on how your team works. one way would be to try and parse the txtNumber.Text value into an Int or some other numeric type. If successful, you know you have just a number, if it fails, the data is no good.

Another way would be to add a regular expression validator to the form. This could look like this:

Regex1

Here we have the regular expression ‘^[0-9]*$’ configured to only allow the digits 0-9. The great thing about these validators is that they provide both client and server-side validation out of the box. There is just one caveat to that. We have to make sure to check the Page.IsValid property, otherwise the server-side check will not be enforced. This would look like this:

Regex 2

With this new check, if the text matches the regular expression, then everything will work as expected. If it does not match, then an error message is returned indicating that it is invalid text.

Wrap Up

Understanding the framework and how different features work is critical in providing good security. It is easy to assume that because we set the type to number that the server will also enforce that. Unfortunately, that is not always the case. Here we clearly see that while client-side validation is being enforced, there are no matching enforcements on the server. This leaves our application open to multiple vulnerabilities, such as SQL Injection, Cross-Site Scripting, etc., depending on how that data is used.

Always make sure that your validation is happening at the server.

Input Validation for Security

August 22, 2022 by · Comments Off on Input Validation for Security
Filed under: Development, Security 

Validating input is an important step for reducing risk to our applications. It might not eliminate the risk, and for that reason we should consider what exactly we are doing with input validation.

Should you be looking for every attack possible?

Should you create a list of every known malicious payload?

When you think about input validation are you focusing on things like Cross-site Scripting, SQL Injection, or XXE, just to name a few? How feasible is it to attempt to block all these different vulnerabilities with input validation? Are each of these even a concern for your application?

I think that input validation is important. I think it can help reduce the ability for many of these vulnerabilities. I also think that our expectation should be aligned with what we can be doing with input validation. We shouldn’t overlook these vulnerabilities, but instead realize appropriate limitations. All of these vulnerabilities have a counterpart, such as escaping, output encoding, parser configurations, etc. that will complete the appropriate mitigation.

If we can’t, or shouldn’t, block all vulnerabilities with input validation, what should we focus on?

Start with focusing on what is acceptable data. It might be counter-intuitive, but malicious data could be acceptable data from a data requirements statement. We define our acceptable data with specific constraints. These typically fall under the following categories:

* Range – What are the bounds of the data? ex. Age can only be between 0 and 150.
* Type – What type of data is it? Integer, Datetime, String.
* Length – How many characters should be allow?
* Format – Is there a specific format? Ie. SSN or Account Number

As noted, these are not specifically targeting any vulnerability. They are narrowing the capabilities. If you verify that a value is an Integer, it is hard to get typical injection exploits. This is similar to custom format requirements. Limiting the length also restricts malicious payloads. A state abbreviation field with a length of 2 is much more difficult to exploit.

The most difficult type is the string. Here you may have more complexity and depending on your purpose, might actually have more specific attacks you might look for. Maybe you allow some HTML or markup in the field. In that case, you may have more advanced input validation to remove malicious HTML or events.

There is nothing wrong with using libraries that will help look for malicious attack payloads during your input validation. However, the point here is to not spend so much time focusing on blocking EVERYTHING when that is not necessary to get the product moving forward. Understand the limitation of that input validation and ensure that the complimenting controls like output encoding are properly engaged where they need to be.

The final point I want to make on input validation is where it should happen. There are two options: on the client, or on the server. Client validation is used for immediate feedback to the user, but it should never be used for security.

It is too easy to bypass client-side validation routines, so all validation should also be checked on the server. The user doesn’t have the ability to bypass controls once the data is on the server. Be careful with how you try to validate things on the client directly.

Like anything we do with security, understand the context and reasoning behind the control. Don’t get so caught up in trying to block every single attack that you never release. There is a good chance something will get through your input validation. That is why it is important to have other controls in place at the point of impact. Input validation limits the amount of bad traffic that can get to the important functions, but the functions still may need to do additional processes to be truly secure.