Security must be established from the moment application coding begins
for the simple reason that the cost of fixing a security flaw grows
astronomically as the application evolves. A study by IBM's Systems Sciences
Institute found that the relative cost of fixing software defects after
deployment is nearly 15 times greater than the cost of detecting and
eliminating them during development.
In order to secure applications while minimizing costs, vendors are
calling on developers to take more responsibility for delivering secure
applications that are resistant to attack. However, few developers have the
training or tools needed to implement security at the inception of
development. While learning to write secure code is a complex process that
should be taught in universities, internal training seminars, and industry
conferences, understanding the following five common ASP.NET application
security flaws and recommended code fixes will give developers a head start
on building security directly into applications at their birth.
Never Trust User Input
The cardinal security sin of Web application development is developers'
tendency to trust user input. Assuming that users (even malicious ones) are
bounded by the browser and will use only the browser to interact with the
site leaves the application wide open to attack. Hackers have a rich toolkit
of programs that interact and attack sites outside the boundaries of the
browser. From the lowest raw/line-mode interface (e.g., telnet), through CGI
scanners, Web proxies, and Web application scanners, malicious users have a
diverse spectrum of possible attack modes and means.
The only way to counteract hacker attacks is to validate user input. You
can perform several, even overlapping, validations. For instance, a program
may validate all its input upon reception, to make sure it consists of valid
characters, and that no field is too long (potential buffer overflow). Then
some routines carry out further validations, making sure that the data is
reasonable and valid for the specific purposes for which it will be used. A
more fine-grained character set validation may be applied, as well as length
restriction enforcement. Following these maxims will help you to properly
validate user input:
1. Always validate all user input in multiple tiers and on a trusted
platform.
2. Validate input to allow nothing other than the functions expected to
be input and output.
3. Set a trusted code base and validate all data before it can enter the
trusted environment.
4. Test each data type before entry (i.e., Web, registry, file system,
configuration files).
5. Define all data formats (i.e., buffer length, integer type).
6. Define valid user requests and reject all others.
7. Look for valid, rather than invalid, data.
8. Never mirror Web input.
9. Encode or encrypt output.
How to Avoid Five Common ASP.NET Security Flaws
The following five examples will illustrate how to implement these
maxims by demonstrating security flaws as they appear in code, the dangers
the flaws present, and how to simply rewrite a few lines to greatly reduce
the risk of attack.
Parameter Tampering
Using ASP.NET Field Validators
Trusting user input is the number one enemy of secure Web applications.
Parameters submitted in HTML forms are a major source of user input; failing
to validate these parameters may result in a severe security threat.
The following C# code queries a back-end SQL server (assuming the
variables "user" and "password" are taken directly from the user input):
SqlDataAdapter my_query = new SqlDataAdapter(
"SELECT * FROM accounts WHERE acc_user='" + user +
"' AND acc_password='" + password, the_connection);
These few innocent-looking lines of code enable a vicious SQL injection
attack. By entering "OR 1=1" in the "user" input field, the attacker can log
in to the system as an arbitrary user, or possibly execute shell commands
simply by appending the appropriate call right after the query.
'; EXEC master..xp_cmdshell(Oshell command here')--
Danger
The programmer assumed that the user input consists of solely "normal"
data real user names, real passwords that do not contain the character O
(apostrophe) enabling unexpected characters, such as O to execute SQL
attacks. By executing unanticipated SQL queries from the user input, a
hacker could call alternate functions or procedures.
Solution
A field validator is a mechanism that enables an ASP.NET developer to
enforce restrictions on the field value, for example, specifying that the
user input field match a given expression.
In order to block the attack shown above, forbid the apostrophe
character either by specifying what is not valid in the field: "[^']*" or
better yet, by allowing only alphanumeric characters in the field:
"[a-zA-Z0-9]*".
Parameter Tampering Revisited
Avoiding Validation Pitfalls
However, incorporating validators for every user input field will not
protect against all attempts to alter parameters. Range validation must also
specify the correct data type.
When using the range validator ASP.NET control, keep in mind that the
Type attribute must be set according to the type of input field expected, as
the Type attribute defaults to "String":
<!-- check for a number 1-9 -->
<asp:RangeValidator ... MinimumValue="1" MaximumValue="9" .../>
Danger
Since no Type is specified, this code will assume "String", meaning that
the order is a lexicographical one. Therefore, the validator will ensure
only that the string starts with 09. Strings such as "0abcd" will be
accepted.
Solution
The right way to test for integer range is to specify the type as
"Integer":
<!-- check for a number 1-9 -->
<asp:RangeValidator ... MinimumValue="1"
MaximumValue="9" Type="Integer"
Information Leakage
Keeping Hidden Fields Under Wraps
Information about ASP.NET applications can often be found in the
__VIEWSTATE hidden field in nearly all HTML pages. Often overlooked because
it is Base64 encoded, hackers can easily decode the Base64 data, exposing
the __VIEWSTATE data with minimal effort.
Danger
By default, the __VIEWSTATE data consists of:
Dynamic data from page controls
Data stored explicitly by the developer in the ViewState bag
The cryptographic signature of the above data
Solution
Enable encryption of the __VIEWSTATE data by setting
EnableViewStatMAC="true". Then, set the machineKey validation type to
"3DES". This instructs ASP.NET to encrypt the ViewState value using the
Triple DES symmetric encryption algorithm: <machineKey validation="3DES" />.
SQL Injection
Prevent by Using SQL Parameters
As described in the section on parameter tampering, a SQL query embeds
SQL script in the user input by placing a malicious character (such as an
apostrophe) in the input field, causing the SQL server to execute a
malicious query.
Danger
A malicious query can call for the delivery of information from back-end
databases such as a directory of customer credit card numbers.
Solution
A more robust solution, rather than allowing only the characters really
needed, is the use of SQL parameter APIs (such as those provided by ADO.NET)
in order to make the programming infrastructure (rather than the programmer)
construct the query.
Using APIs, the programmer provides a template query (or a stored
procedure), and a list of parameter values (embedded into the query), and
the result is executed by the SQL Server. The advantage is a guarantee that
the parameters will be embedded correctly. For example, apostrophes will be
escaped, thus rendering SQL injection attacks useless. At the same time, the
apostrophe will not be blocked, which is an upside of this approach.
So instead of the code in the section on parameter tampering, use:
SqlDataAdapter my_query = new SqlDataAdapter(
"SELECT * FROM accounts
WHERE acc_user= @user AND acc_pass
word=@pass", the_connection);
SqlParameter userParam =
my_query.Select_Command
.Parameters.Add(
"@user",SqlDb.VarChar,20);
userParam.Value=user;
SqlParameter passwordParam =
my_query.Select_Command
.Parameters.Add(
"@",SqlDb.VarChar,20);
passwordParam.Value=password;
Cross-Site Scripting
Encode Outgoing Data
Cross-site scripting embeds malicious user input in the response (HTML)
page. A simple ASP.NET page such as the following contains a serious
security flaw:
<%@ Page Language="vb" %>
<asp:Label id="Label1" runat="server">
INITIAL LABEL VALUE</asp:Label>
<form method="post" runat="server" ID="Form1">
Please Provide feedback<br>
<asp:Textbox ID="feedback" runat="server"/><br>
<asp:Button id="cmdSubmit" runat="server"
Text="Submit!" OnClick="do_feedback">
</asp:Button>
</form>
<script runat="server">
Sub do_feedback(sender As Object, e As System.EventArgs)
Label1.Text=feedback.Text
End Sub
</script>
Danger
An attacker can form a malicious request with JavaScript code that will
be executed at the client browser when the link is clicked. To see that this
is possible, this script can be fed with the following input:
<script>alert(document.cookie)
</script>
Solution
For a two-tier security architecture, use user input validation and
HTML-encode outgoing user data presented in the HTML page to ensure that the
data is not interpreted by the browser as anything other than plain text.
In this case, this can be done by adding a function call to HtmlEncode:
Label1.Text=Server.HtmlEncode(feedback.Text)
As a result, the response HTML stream will contain:
<script>alert(document.cookie)</script>
As a result, no JavaScript code is executed by the browser, because no
HTML "script" tag is present. The < and > symbols are replaced by their
HTML-encoded versions, < and > respectively.
Using Automated Security Testing Tools
With new applications deployed on average every three months by
organizations experiencing changing customer requirements and personnel
turnover, the demand placed on developers to develop robust, high-quality
software quickly is tremendous. While all developers should be instructed in
secure coding techniques, tools that can automatically check code for
security flaws can speed the development of secure applications.
Until now, developers have used only tools that cover specific aspects
of functionality testing such as performance and bug/crash spotting. Because
manual source code review is inconsistent in nature and presupposes
intensive secure coding training, tools concerned with security of the
application and its behavior under adverse conditions are also critical to
the production of high-quality applications.
The most effective solution for rapidly improving the quality and
security of applications is to provide developers with a tool that
automatically tests applications for defects within their existing workflow
environment. By using a tool that detects application-specific
vulnerabilities during unit testing and offers inline fix recommendations,
developers will immediately see the coding errors they have made and learn
how to fix the existing vulnerability and avoid future vulnerabilities for
ongoing improved security.
Conclusion
The dangers of insecure Web applications will only accelerate as Web
services explode, sending many more applications outside the firewall.
Developers will be under even more pressure to rapidly create new
applications under tight deadlines. In order to prepare for the Web services
of the future and to ensure high-quality applications today, attention and
resources must be devoted to secure coding practices. By taking a proactive
approach to security at the birth of applications, companies can construct
high-quality, secure applications while reducing costs and limiting risk.
About The Author
Amit Klein, director of Security and Research for Sanctum, Inc. is responsible for the security content of Sanctum's products, research of new technologies, and new product directions, as well as performing security audits, conducting security research, and acting as the security knowledge focal point for the corporation. Prior to joining Sanctum, Amit served in the Israeli Defense Force in various R&D positions including leading an algorithmic research team and later a software project development team.
info@sys-con.com
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com