Return to
HomePage
Security Guidelines: ASP.NET 2.0 Security
* Auditing and Logging
* Authentication
* Authorization
* Code Access Security
* Configuration
* Data Access
* Exception Handling
* Impersonation / Delegation
* Input Validation
* Secure Communication
* Sensitive Data
Auditing and Logging
*
Use the health monitoring feature introduced in ASP.NET 2.0 to instrument key business critical application events *
Intrument user management events like, Password resets, Password changes, Account lockout, User registration and Authentication events etc. *
Instrument events like Malicious input, too many logins over a period of time, logins from different source IP, or replay of an old authentication ticket. * * Create event source at the time of application installation*
Additional considerations
*
In addition to failures and errors, log Security events in case of unexpected behavior and other exception conditions. *
Log application events on a separate, protected server to ensure that logs cannot be tampered by attackers. * *Logs should be written by a process with write permission only. Logs should read by users with administrative access. *
*
Log application events with sufficient details, so as to permit reconstruction of system activity *
High volume, per-request events should be captured with performance counters, to minimize the impact on performance.
Authentication
*
Use Windows Authentication wherever possible.
Windows Authentication
*
Do not Impersonate the original user unless required like, when you need to flow the original caller's security context to the middle tier and/or data tier of your Web application to support fine-grained (per-user) authorization.
Forms Authentication
*
Use Membership Providers instead of custom authentication. *
Use Secure Sockets Layer (SSL) to protect credentials and authentication cookies. *
If you cannot use SSL, consider reducing the cookie lifetime by reducing the timeout value. *
Validate user login information. *
Do not store passwords directly in the user store; store password digests with salt instead. *
Enforce strong passwords. *
Protect access to your credential store. *
Do not persist authentication tickets on the client side. *
Site is partitioned to restricted areas and public areas.
Additional Considerations
*
Use only one mechanism through which users can authenticate to the system. *
Set the httpOnly cookie attribute and validate data from the cookie to help prevent cross site scripting attacks *
Use unique path/name combinations for Application cookies.
Authorization
*
Use URL authorization for page and directory access control. *
Use File authorization with Windows authentication. *
Use principal demands on classes and methods. *
Use explicit role checks for fine-grained authorization
Roles Authorization
*
Use Roles Providers for using Roles Authorization. *
Use the SqlRoleProvider with Roles data in SQL Server, when using Forms Authentication with user store in SQL Server *
Use the WindowsTokenRoleProvider with ASP.NET applications that use Windows authentication mode and use Windows groups as roles. *
Use the AuthorizationStoreRoleProvider with AzMan Policy store in AD / ADAM when using Windows Authentication in ASP.NET applications or Forms Authentication using AD and application roles are different then windows groups. *
Use the AuthorizationStoreRoleProvider with AzMan Policy store in ADAM in conjunction with Forms authentication using ADAM. *
Use cookies for caching roles, to improve performance. *
Use SSL to protect Roles cookie. *
If you cannot use SSL, consider reducing the cookie lifetime by reducing the timeout value *
Do not persist Roles cookie on the client side.
Additional Considerations
*
Set the httpOnly cookie attribute and validate data from the cookie to help prevent cross site scripting attacks
Code Access Security.
*
Care for Code Access security when developing medium / partial trust application. *
When choosing trust level for your application make sure you do not give more than required permissions. *
Use Medium trust for shared hosting enviorment. *
Customize trust policy if your application needs additional permissions then available standard trust policies *
If you do not want all of the pages in your ASP.NET application to have a particular extended permission granted to them, then you can use a wrapper assembly to control access to your resources. *
When executing untrusted code ensure that you give specific permissions, required for that code and nothing more.
Configuration
*
Configuration file retrieval is blocked by using HttpForbiddenHandler. *
Encrypt configuration sections which store senstive data. *
Configure Machine key to use same hashing and decryption keys on all servers in web farm scenario. *
To enforce machine-wide policy, Web.config settings are locked by using allowOveride="false" in Machine.config.
Additional Consideration
*
Use least privileged account for running ASP.NET applications.
Data Access
*
Use Windows Authentication where ever possible. *
When using windows authentication use trusted subsytem approach rather than impersonation / delegation, as connection pooling can be used better and account management is easy. *
In no trust enviorment use windows authentication with service accounts (mirrored accounts). *
When using SQL authentication, use strong password *
If SQL Authentication is used, secure user credentials over the network using IPSec / SSL etc. *
Encrypt connection strings using DPAPI/RSA alongwith aspnet_regiis utility. *
Use least privileged accounts for accessing database. *
Input passed to data access methods that originates outside the current trust boundary is validated *
Use type safe SQL parameters with Stored procedures and/or prepared statements to access the database. *
Dynamic queries that accept user-submitted parameters should not be used.
Additional Considerations
*
When the ASP.NET process is running under Network Service account, give access to machine account (domainName\machineName$) on the remote database, as the network service is identified by machine account on network. *
Applications that use database connection pools to access remote resources should do so over an encrypted channel.
Exception Handling
*
Use structured exception handling. *
When errors are encountered by the web application, the server should return concise error messages to the service client; specific details should be logged securely on the server and not disclosed *
Return generic error pages to the client. *
Implement page-level or application-level error handlers. *
The application should distinguish between errors and exception conditions.
Impersonation / Delegation
*
When doing fixed identity impersonation using credentials in config file, make sure to encrypt the identity section of the configuration. *
Disable anonymous access in IIS, when impersonating original caller. *
Impersonate original user only if you have to do OS auditing or resource access against original user identity, else its not recommended. *
When doing programatic impersonation make sure you revert the identity as soon as the resource access is done. *
If original user has logged in using authentication other than Windows Authentication use Protocol transfer for delegation. *
Configure Machine accounts for delegation rather than user accounts. *
Use constrained delegation and give delegation rights to only required services / servers.
Input/Data Validation
*
Do not rely on ASP.NET RequestValidation. *
Validate length, range, format and types. *
Do not rely on client-side validation. *
Validate input from other sources like QueryString, Cookies, HTML controls. *
Validate File and URL Paths. *
Encode output with HtmlEncode and UrlEncode. *
SQL parameters are used in data access code to validate length and type of data and to help prevent SQL injection.
Secure Communication
*
Use Secure Sockets Layer (SSL) to encrypt the communication channel between specific client applications and a server, when you need granular channel protection for a particular application rather than for all applications and services running on a computer. *
Use Internet Protocol Security (IPSec) to secure the communication channel between two servers and to restrict which computers can communicate with one another. *
Optimize pages that use SSL by including less text and simple graphics and partition your site and ensure that only those pages than contain sensitive data use SSL.
Sensitive Data
*
Use SSL or IPSec to protect sensitive data on the wire. *
Do not pass sensitive data across pages; maintain it using server-side state management. *
Do not store sensitive data in cookies, hidden form fields, or query strings. *
Do not cache sensitive data. Output caching is off by default. *
Protect sensitive data stored in persistent store (like database) or memory.
Additional Considerations
*
Never store user passwords in clear text or encrypted form, always store them in non-reversible hash format using salt. *
Do not store plain text passwords in Web.config and Machine.config files. (use aspnet_regiis for encrypting the section storing them.) "what to do"
"why"
"how" - pattern, then point to depth/how to.
The
HttpOnly cookie option is used for defense in depth to help prevent cross-site scripting.
Character encoding is set by the server (ISO-8859-1 is recommended).
Input/Data Validation
*
Do not rely on ASP.NET RequestValidation. *
Validate length, range, format and types. *
Do not rely on client-side validation. *
Validate input from other sources like QueryString, Cookies, HTML controls. *
Validate File and URL Paths. *
Encode output with HtmlEncode and UrlEncode.
Do Not Rely On ASP.NET RequestValidation.
Treat ASP.NET
RequestValidation as an extra precautionary measure in addition to your own input validation and do not rely on it. Ensure that it is enabled for all pages except those that need to accept a range of HTML elements. By default,
RequestValidation is enabled by default. validateRequest is set to true on the <pages> element in the Machine.config.comments file.
Validate length, range, format and types.
Check for known good data and constrain input by validating input data for type, length, format, and range. For Web form applications that obtain input through server controls, use the ASP.NET validator controls such as the
RegularExpressionValidator, RangeValidator and
CustomValidator to validate and constrain input. For other sources of input data, such as query strings, cookies, and HTTP headers, constrain input by using the Regex class from the
System.Text.RegularExpressions namespace.
Check all numeric fields for type and range. If you are not using a server control, you can validate a numeric range by converting the input value to an integer and then performing a range check.
Do not rely on client-side validation
Do not rely on client-side validation because it is easily bypassed. For example, a malicious user could disable your client-side script routines, for example, by disabling
JavaScript. Use client-side validation in addition to server-side validation only to reduce round trips to the server and to improve the user experience.
Validate File and URL Paths.
To prevent a malicious user manipulating your code’s file operations, avoid writing code that accepts user-supplied file or path input. If you must accept file names as input, ensure that they are well formed and are verifiably valid within your application's context. For example, ensure they only refer to a file within your application's virtual directory hierarchy if that is appropriate. When obtaining file names, use the full name of the file by using
System.IO.Path.GetFullName. If you must accept file paths as input, use the full file path by using
System.IO.Path.GetFullPath. If you use
MapPath to map a supplied virtual path to a physical path on the server, use the overload of
Request.MapPath that accepts a bool parameter so that you can prevent cross-application mapping. The following code example shows this technique.
try
{
string mappedPath = [Request.MapPath(] inputPath.Text,
[Request.ApplicationPath,] false);
}
catch [(HttpException)]
{
// Cross-application mapping attempted
}
The final false parameter prevents cross-application mapping. This means that a user cannot successfully supply a path that contains ".." to traverse outside of your application's virtual directory hierarchy. Any attempt to do this results in an exception of type
HttpException. You can also use code access security to restrict file operations to specific directories on the server. For example, by running your application using the Medium trust level, you restrict file access to your application's virtual directory hierarchy.
Validate input from other sources like QueryString, Cookies, HTML controls.
If you are not using server controls (which means you cannot use the validator controls), or you need to validate input from sources other than form fields (such as from query string parameters or cookies), you can use a Regex class. To use the Regex class
- Add a using statement to reference the System.Text.RegularExpressions namespace.
- Ensure that the regular expression is contained in the ^ and $ anchor characters (beginning of string, end of string).
- Call the IsMatch method of the Regex class, as shown in the following 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 your regular expression for frequent use, you should use the static
IsMatch method where possible for performance reasons, to avoid unnecessary object creation.
Encode output with HtmlEncode and UrlEncode
Never just echo input back to the user without validating and/or encoding the data. If you write text output to a Web page, encode it using
HttpUtility.HtmlEncode. Do this if the text came from user input, a database, or a local file. Similarly, if you write
URLs that might contain unsafe characters because they have been constructed from input data or data from a shared database, use
HttpUtilty.UrlEncode to make them safe. Avoid the mistake of encoding the data early. Make sure you encode at the last possible opportunity before the data is displayed to the client.
Authentication
Forms Authentication
*
Use Membership Providers instead of custom authentication. *
Use SSL. *
Validate user login information. *
Do not store user passwords. *
Do not send passwords over unprotected channels. *
Enforce strong passwords. *
Do not persist authentication tickets on the client side. *
Protect access to your credential store.
Use SSL.
Do not pass your authentication ticket over unprotected channels.
Do not store user passwords.
If you need to store credentials, then do not store the passwords. Store one-way hashes with salt.
Windows Authentication
*
Authorization
Roles Authorization
*
Use Roles Providers for using Roles Authorization. *
Use the SqlRoleProvider to store Roles data in SQL Server. *
Use the WindowsTokenRoleProvider with ASP.NET applications that use Windows authentication mode and use Windows groups as roles. *
Use the AuthorizationStoreRoleProvider with AzMan Policy store in AD when using Windows Authentication in ASP.NET applications. *
Use the AuthorizationStoreRoleProvider with AzMan Policy store in ADAM in conjunction with windows authentication or Forms authentication using AD. *
Use cookies for caching roles, to improve performance. *
Protect access to the Roles cookie.
Use Roles Providers for using Roles Authorization
A role provider implements the methods of the Role Management API and provides a simple method of programmatically testing for role membership for a user regardless of the actual role management data store used. You can configure ASP.NET applications to allow or deny access based on a user's membership of a role. Use one of the supplied Roles Providers:
SqlRoleProvider, WindowsTokenRoleProvider or
AuthorizationStoreRoleProvider, or implement your own custom role provider.
Use the SqlRoleProvider along with Forms Authentication with SqlMembershipProvider to use the same database for authentication and authorization.
Configure your application to use the
SqlRoleProvider to store Roles data in SQL Server. You can also configure Forms Authentication to store user account data in the same SQL Server database, though this is not required. For more information on how to configure Role management and Forms Management in SQL Server, see
HowToUseASPNETRolesWithFormsAuthenticationAndSQLServer.
Use the WindowsTokenRoleProvider with ASP.NET applications that use Windows authentication mode and use Windows groups as roles
Use the
WindowsTokenRoleProvider if your application retrieves role information for a Windows user based on Windows security groups. It is most useful with ASP.NET applications that use Windows authentication mode where the IIS authentication settings disable anonymous authentication.
For more information on how to configure the
WindowsTokenRoleProvider, see
HowToUseASPNETRolesWithWindowsAuthentication.
Use the AuthorizationStoreRoleProvider with AzMan Policy store in AD when using Windows Authentication in ASP.NET applications
If your application uses Windows Authentication, your user accounts are in Active Directory, and your roles are not the same as Windows groups,but are application-specific, you can store roles data in SQL Server or in an Authorization Manager
(AzMan) store in AD.
AzMan provides a convenient Microsoft Management Console utility to create and manage roles, and manage role membership for users. For more information on using the
AuthorizationStoreRoleProvider to store Roles data in an
AzMan store in AD, see
HowToUseASPNETRolesWithAuthorizationStoreRoleProvider.Note: When using the
AuthorizationStoreRoleProvider you don't get the
AzMan business logic (Operations, tasks etc), if want to use it then Pinvoke the
AzMan API directly.
Use the AuthorizationStoreRoleProvider with AzMan Policy store in ADAM in conjunction with windows authentication or Forms authentication using AD
If your user accounts are in AD, but you cannot use Windows authentication and must use Forms authentication because your users connect over the Internet, then a good solution for Roles management is to use the
AuthorizationStoreRoleProvider with an
AzMan Policy store in an Active Directory Application Mode (ADAM) store.
Use cookies for caching roles, to improve performance
When the
CacheRolesInCookie property is set to true in the Web.config file, role information for each user is stored in a cookie. When role management checks to see whether a user is in a particular role, the roles cookie is checked before calling the role provider to check the list of roles at the data source. The cookie is dynamically updated to cache the most recently validated role names.
<roleManager enabled="true"
cacheRolesInCookie="true"
... >
</roleManager>
Protect access to the Roles cookie
* Set the
cookieProtection attribute to "All". This ensures that the role names in the cookie are encrypted, and protects against the cookie being altered.
* Set the
cookieSlidingExpiration attribute to "true" and the cookieTimeout atribute to a integer number of minutes (for example "30"). The cookie expires when the timeout expires and must be renewed.
* Set the
cookieRequireSSL attribute to "true" to specify that SSL (Secure Sockets Layer) is required to return the role names cookie to the server.
* Set the
createPersistentCookie attribute to "false" to ensure that the roles cookie is session-based and not a persistent cookie.
For example:
<roleManager enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="true"
cookieSlidingExpiration="true"
cookieProtection="All" >
</roleManager>
!!!
Design Considerations
Input /Data Validation
* Constrain input, Then Sanitize
* Validate un-trusted input and data for length, range and format.
* Use server-side input validation; do not rely on client side validation.
* Use the ASP.NET
RequestValidation option as an additional measure.
* Explicitly Check Input from Form Fields
* Use Validation Controls for Server Controls (Custom Validation Control gives flexibility)
* Validate input from other sources like
QueryString, Cookies, HTML controls etc
* Validate File and URL Paths
* Protect code and data paths to only enable read-only access
* Validate System Input, like shared un-trusted database.
* Always use
HtmlEncode to Encode Unsafe Output, when you are sure that no HTML specific tags are used in the Output to protect from XSS.
* If you want to allow know good html tags, first
HtmlEncode the output then replace the known good tags and then output to protect from XSS
* Set Correct Character encoding to restrict valid data for your web pages.
* Not all data bound controls perform encoding when displaying data retrieved from a bound data component; thus, it will be your responsibility to perform encoding on non-trusted data components in order to prevent XSS attacks. For example, a data component cannot be trusted in a scenario where different applications share a single database.
* Avoid using dynamic SQL Queries instead use Store Procedure with Command Parameters.
* Use Command Parameters for dynamic SQL Queries
* Use least privileged SQL account for accessing database
* Return user friendly messages in case of Database errors, sensitive information should not be revealed.
* Use the
HttpOnly Cookie Option, to avoid client-side scripts from accessing the cookie
* Use the <frame> Security Attribute, this allows to restrict security on indivisual frame, so that it does not support client side script execution.
* When using InnerHTML property to build a page, use the innerText Property as this property renders content safe and ensures that scripts are not executed.
Issues:
Needs to be more like keeping the user input out of the control channel and making input safe,
Authentication
Forms Authentication
* Protect credentials and authentication tickets using SSL.
* Secure restricted pages with SSL.
* To avoid having to use SSL across your entire site partition your Web site, so that secured pages are seperated from anonymously accessible pages.
* Use URL Authorization for restricting anonymous access to restricted pages.
* Secure the authentication cookie, by setting the protection attribute to default value of "All", so that the cookie is encrypted and hashed as well.
* Use SSL (HTTPS) when passing the authetication cookie over the network.
* Limit cookie lifetime, by setting the fixed expiration time.
* Do not persist authentication cookies.
* Keep authentication and personalization cookies separate.
* Use distinct cookie names and paths.
* Use absolute
URLs for navigation.
* Use secure credential management.
* Use one-way hashes for passwords.
* Use strong passwords, by default for both providers the password strength is 1 non alpha nummeric character, password length 7, you can use attributes in the provider configuration to change this value additionally can specify a regular expression for detremining strength of the password.
* Use Membership Providers instead of custom authentication
* Use
SqlMembershipProvider if users are non-windows users.
* Use
ActiveDirectoryMembershipProvider if users are windows users.
* Explicitly set requiresUniqueEmail="true" attribute for Membership Providers, for unique email id’s, this by default is set to false.
* Use ASP.NET configuration tool for user management or Use Login controls
(CreateUserWizard, ChangePassword etc) for user management.
* When using
ActiveDirectoryMembershipProvider, secure the user credentials that need to be configured encrypting the config section using aspnet_regiis.
* Ensure that ASP.NET process identity have access to the SQL Provider database, and it has minium rights so that it can not compromise under attack or accidentally.
Windows Authentication
* Rely on IIS Integrated Authentication when using ASP.NET windows authentication.
* Impersonate the original user only when you need to flow the original caller's security context to the middle tier and/or data tier of your Web application to support fine-grained (per-user) authorization.
* Impersonate the original user when you need to flow the original caller's security context to the downstream tiers to support operating system level auditing.
* Do not use Impersonation or Use fixed identity impersonation if you want to use a fixed identity to access downstream resources (for example, databases) in order to support connection pooling.
* Use Application pool identity for fixed identity impersonation.
Roles Authorization
* Use Roles Providers for using Roles Authorization.
* Use
SqlRoleProvider along with Forms Authentication with
SqlMembershipProvider, so that you can use the same database for authentication and authorization.
* Use ASP.NET Configuration tool for managing the roles in
SqlRoleProvider. *
WindowsTokenRoleProvider can be used only with ASP.NET applications that use Windows authentication mode and uses windows group as roles.
* Use Windows Computer Management tool for managing roles in
WindowsTokenRoleProvider. * Use
AuthorizationStoreRoleProvider with
AzMan Ploicy store in AD when using Windows Authentication in ASP.NET applications. (Note
AzMan Policy Groups / Roles are different then Windows Groups)
* Use
AuthorizationStoreRoleProvider with
AzMan Ploicy store in ADAM in conjunction with windows authentication or Forms Authentication using AD.
* Use
AuthorizationStoreRoleProvider with
AzMan Policy store in xml only for development purpose.
* Give appropriate access to ASP.NET process identity or orginal caller in case of impersonation to
AzMan Policy store.
* When using
AuthorizationStoreRoleProvider you don't get the
AzMan buisness logic (Operations, tasks etc), if want to use it then Pinvoke the
AzMan API directly.
* Use ASP.NET Configuration tool for managing roles in
AuthorizationStoreRoleProvider. * Use cookies for caching roles, to improve performance.
* Limit Roles cookie life time.
* Secure the Roles cookie.
* Restrict the Roles cookie to HTTPS connections.
* Encrypt the Roles cookie.
* Do not persist Roles cookies.
Authorization
* Use URL authorization for page and directory access control.
* Use File authorization with Windows authentication.
* Use principal demands on classes and methods.
* Use explicit role checks for fine-grained authorization.
Code Access Security
* Use Medium trust for shared hosting enviorment.
* Customizing trust policy is recommended method rather than wrapping privileged code.
* When choosing trust level for your application make sure you do not more than required permissions.
* If you do not want all of the pages in your ASP.NET application to have a particular extended permission granted to them, then you can use a wrapper assembly to control access to your resources.
* When executing untrusted code ensure that you give permissions, you know are required for that code and nothing more.
* Use seperate
AppDomain for executing un-trusted rather than denying permissions before calling the untrusted code.
Data Access
* Use Windows Authentication where ever possible.
* Use least privileged accounts for accessing database.
* When the ASP.NET process is running under Network Service account, give access to machine account (domainName\machineName$) on the remote database, as the network service is identified by machine account on network.
* When using windows authentication use trusted subsytem approach rather than impersonation / delegation, as connection pooling can be used better and account management is easy.
* In no trust enviorment use service accounts (mirrored accounts).
* Encrypt connection strings using DPAPI/RSA alongwith aspnet_regiis utility.
Impersonation
* When doing programatic impersonation make sure you revert the identity as soon as the resource access id done.
* Use Appilication pool identity when doing fixed identity impersonation.
* When doing fixed identity impersonation using credentials in config file, make sure to encrypt the identity section of the configuration.
* Impersonate original user only if you have to OS auditing or resource access against original user identity, else its not recommended.
* Disable anonymous access in IIS, when impersonating original caller.
Delegation
* Use delegation if you have to make multiple hops for original user’s identity.
* If original user has logged in using authentication other than Windows Authentication use Protocol transfer.
* Configure Machine accounts for delegation rather than user accounts.
* Use constrained delegation and give delegation rights to only required services / servers.
Issues:
* Using Programmatic Impersonation
* Impersonating using Application Pool.
* Securing Credentials.
Sensitive Data
* Do not cache sensitive data.
* Do not pass sensitive data from page to page.
* Avoid plain text passwords in configuration files
* If sensitive data is being stored in config file, use DPAPI / RSA with aspnet_regiis for configuration section encryption along.
* Encrypt only the configuration section that stores senstive data, encryption has performance cost associated with it.
* Use RSA for configuration section encryption in case of web farm scenario, as it allows to export the keys.
* With Both RSA and DPAPI use machine store rather than user store and have
ACLs on the machine store to ensure who can access the keys.
* Use DPAPI to avoid key management.
* Turn Off Output Caching for Sensitive Data
* Secure Sensitive data over the wire.
* Secure sensitive data in persistent store.
Session Management
* Require authentication for sensitive pages.
* Do not rely on client-side state management options.
* Do not mix session tokens and authentication tokens.
* Use SSL effectively.
* Secure the session data.
ViewState and Forms Authentication Ticket.
* Protect view state with
MACs. – Avoid using
ViewState (Perf and Security issues).
* Avoid storing sensitive data in
ViewState. * If storing sensitive data in
ViewState is required, encrypt the viewState, but storing sensitive information is not good practice as the view state size dramatically increases and is hit on performance.
* For encryption
ViewState or forms Authentication use 3DES / AES (Not Sure) as this is more secure.
* Use SHA1 for hashing rather than MD5 as it produces larger hash and hence more secure.
* In case of web scenario, use manually generated validation and decryption keys and make sure they are prapogated to all the web servers.
* Use
Page.ViewStateUserKey to counter one-click attacks. (how to?)
Issues:
* Application managed authorization for server checks of client parms
*
ViewState protection has a price.
Exception Management
* Fail securely.
* Return generic error pages to the client.
* Implement page-level or application-level error handlers.
Issues:
* Fail securely needs to be more like defaulting to a safe mode, when in doubt.
Auditing and Logging
* High volume, per-request events should be captured with performance counters, to minimize the impact on performance.
* In case of web farm scenario the events should be logged to central repository.
Issues:
Event Log Permission
Related Resources
*
ASPNETWhidbeySecuritySnapshot
Threats and Countermeasures
*
CodeInjection *
SessionHijacking *
IdentitySpoofing *
ParameterManipulation *
NetworkEavesdropping *
InformationDisclosure
Design Considerations
*
Use server-side input validation. *
Partition your Web site. *
Consider the identity that is used for resource access. *
Protect credentials and authentication tickets. *
Fail securely. *
Consider authorization granularity. *
Place Web controls and user controls in separate assemblies. *
Place resource access code in a separate assembly.
Use Server-side Input Validation
At design time, identify all the various sources of user input that your Web pages and controls process. This includes form fields, query strings, and cookies received from the Web user, as well as data from back-end data sources. The Web user clearly lives outside your application's trust boundary, so all of the input from that source must be validated at the server. Unless you can absolutely trust the data retrieved from back-end data sources, that data should also be validated and sanitized before it is sent to the client. Make sure your solution does not rely on client-side validation because this is easily bypassed.
Partition Your Web
Your Web site design should clearly differentiate between publicly accessible areas and restricted areas that require authenticated access. Use separate subdirectories beneath your application's virtual root directory to maintain restricted pages, such as checkout functionality in a classic e-commerce Web site that requires authenticated access and transmits sensitive data such as credit card numbers. Separate subdirectories allow you to apply additional security (for example, by requiring SSL) without incurring SSL performance overhead across the entire site. It also allows you to mitigate the risk of session hijacking by restricting the transmission of authentication cookies to HTTPS connections. The following figure shows a typical partitioning.
http://msdn.microsoft.com/library/en-us/dnnetsec/html/f10thcm02.gif
A Web site partitioned into public and secure areas
Note that in the above, the restricted subfolder is configured in Internet Information Services (IIS) to require SSL access. The first <authorization> element in Web.config allows all users to access the public area, while the second element prevents unauthenticated users from accessing the contents of the secured subfolder and forces a login.
In your site design, make sure that secure pages that require authenticated access are placed in a subdirectory that is separate from the anonymously accessible pages. The followig figure shows a typical arrangement in the Visual Studio .NET Solution Explorer window. Notice how the Forms login page is placed along with other restricted pages in a separate subdirectory.
http://msdn.microsoft.com/library/en-us/dnnetsec/html/f10thcm03.gif
Subdirectory for restricted pages that require authenticated access
Note: If you are using Server.Transfer in your application to transfer from an anonymous page to a secure page, .NET Framework version 1.1 or earlier bypasses authentication checks, so code that uses Server.Transfer should be verified to ensure that it does not transfer to a secure directory.
Consider the identity that is used for resource access
On Windows 2000, ASP.NET Web applications run in IIS 6
ApplicationPools, which by default run using the least privileged Network Service account. On Windows 2000, the least privileged ASPNET account is used to run the aspnet_wp.exe worker process.
* Use a custom least privileged account to run your application pools
By using a custom least privileged account you:
* Have sepaerate identities for multiple Web applications running on a single server
* Have separate auditability
* Can configure
ACLs (and database permissions) specifically for the custom account
Protect Credentials and Authentication Tickets
Your design should factor in how to protect credentials and authentication tickets. Credentials need to be secured if they are passed across the network and while they are in persistent stores such as configuration files. Authentication tickets must be secured over the network because they are vulnerable to hijacking. Encryption provides a solution. SSL or
IPSec can be used to protect credentials and tickets over the network and DPAPI provides a good solution for encrypting credentials in configuration files.
Fail Securely
If your application fails with an unrecoverable exception condition, make sure that it fails securely and does not leave the system wide open. Make sure the exception details that are valuable to a malicious user are not allowed to propagate to the client and that generic error pages are returned instead. Plan to handle errors using structured exception handling, rather than relying on method error codes.
Consider Authorization Granularity
Consider the authorization granularity that you use in the authenticated parts of your site. If you have configured a directory to require authentication, should all users have equal access to the pages in that directory? If necessary, you can apply different authorization rules for separate pages based on the identity, or more commonly, the role membership of the caller, by using multiple <authorization> elements within separate <location> elements.
For example, two pages in the same directory can have different <allow> and <deny> elements in Web.config.
Place Web controls and user controls in separate assemblies.
When Web controls and user controls are put in their own assemblies, you can configure security for each assembly independently by using code access security policy. This provides additional flexibility for the administrator and it means that you are not forced to grant extended permissions to all controls just to satisfy the requirements of a single control.
Place resource access code in a separate assembly
Use separate assemblies and call them from your page classes rather than embedding resource access code in your page class event handlers. This provides greater flexibility for code access security policy and is particularly important for building partial-trust Web applications.
Input Validation
*
ConstrainThenSanitize
CrossSiteScripting
* Validate input.
* Encode output.
Output Encoding
If you write text output to a Web page and you do not know with absolute certainty that the text does not contain HTML special characters (such as <, >, and "&"), then make sure to pre-process it using the
HttpUtility.HtmlEncode method. Do this even if the text came from user input, a database, or a local file. Similarly, use
HttpUtility.UrlEncode to encode URL strings.
The
HtmlEncode method replaces characters that have special meaning in HTML to HTML variables that represent those characters. For example, < is replaced with < and " is replaced with ". Encoded data does not cause the browser to execute code. Instead, the data is rendered as harmless HTML.
Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));
Data-Bound ControlsData bound controls are web controls that are bindable to data components through a public inherited
'DataSource' property. To mention a few, you will find
DataGrid, ListBox and
DropDownList to be used very often. Not all data bound controls perform encoding when displaying data retrieved from a bound data component; thus, it will be your responsibility to perform encoding on non-trusted data components in order to prevent XSS attacks. For example, a data component cannot be trusted in a scenario where different applications share a single database. If an attacker has the ability to insert malicious
XSS code into the database (by abusing a vulnerability in one of the applications, for instance) all applications using non-encoding web controls bound to it, will turn vulnerable. Only avoid encoding if you can be certain that the output from the data component will always be valid.
Examples of data bound controls that do not perform encoding are
DataGrid, DataList, RadioButtonList and
CheckBoxList. Performing encoding for a data bound control may vary depending on each specific control. For example, for a
DataGrid control, you have the following options:
* Turn all columns into templates and manually use
HtmlEncode()/UrlEncode() on each call to
DataBinder.Eval * Override one of its
DataBinding methods, such as
OnDatabinding or
OnItemDataBound and perform encoding on its items. The following example illustrates how to override the
OnItemDataBound method of a
DataGrid control in order to encode its items by either using
HtmlEncode() or
UrlEncode() when required:
...
[DefaultProperty("Text"),
ToolboxData("<{0}:DataGrid runat=server></{0}:DataGrid>")]
public class [DataGrid] : [System.Web.UI.WebControls.DataGrid]
{
/// <summary>
/// The [ItemDataBound] event is raised after an item is data bound to the [DataGrid]
/// control. This event provides you with the last opportunity to access the data
/// item before it is displayed on the client. After this event is raised, the data
/// item is nulled out and no longer available. - .NET Framework Class Library
/// </summary>
/// <param name="e"></param>
protected override void [OnItemDataBound(DataGridItemEventArgs] e)
{
[base.OnItemDataBound] (e);
switch [(e.Item.ItemType)]
{
case [ListItemType.Item:]
case [ListItemType.AlternatingItem:]
case [ListItemType.EditItem:]
case [ListItemType.SelectedItem:]
case [ListItemType.Footer:]
case [ListItemType.Header:]
case [ListItemType.Pager:]
// even though not all of these [ListItemTypes] are data bound,
// perform [HtmlEncode] or [UrlEncode] on each control. If there are
// no controls, we perform [HtmlEncode] on any available text.
// Also, don't let 's be encoded.
[TableCellCollection] cCells = e.Item.Cells;
foreach [(TableCell] tc in cCells)
{
if (tc.Controls.Count > 0)
{
foreach (Control ctrl in tc.Controls)
{
// don't perform [HtmlEncode] on URL's
if (ctrl is [HyperLink)]
{
[HyperLink] hLnk = [(HyperLink)ctrl;]
if (hLnk.Text.Length > 0)
hLnk.Text = [HttpUtility.HtmlEncode(hLnk.Text);]
if [(hLnk.NavigateUrl.Length] > 0)
[hLnk.NavigateUrl] = [HttpUtility.UrlEncode(hLnk.NavigateUrl);]
}
else if (ctrl is [LinkButton)]
{
[LinkButton] lButton = [(LinkButton)ctrl;]
if (lButton.Text.Length > 0)
lButton.Text = [HttpUtility.HtmlEncode(lButton.Text);]
}
else if (ctrl is Button)
{
Button cButton = (Button)ctrl;
if (cButton.Text.Length > 0)
cButton.Text = [HttpUtility.HtmlEncode(cButton.Text);]
}
}
}
else
{
// there are no controls in the table cell
// [HTMLEncode] any available text
if (tc.Text.Length > 0)
{
if (" " != tc.Text)
tc.Text = [HttpUtility.HtmlEncode(tc.Text);]
}
}
}
break;
default:
break;
}
}
}
...
Authentication
* Partition your Web site.
* Secure restricted pages with SSL.
* Use URL Authorization.
* Restrict the Authentication Cookie-to-HTTPS Connections.
* Use absolute
URLs for navigation.
* Use secure credential management.
Use URL Authorization
Use URL Authorization
For page-level and directory-level access control, use URL authorization, which is configured by the <authorization> element. To restrict access to specific files or directories, place the <authorization> element inside a <location> element.
To allow anonymous access to public pages, use the following <authorization> element.
<system.web>
<!-- The virtual directory root folder contains general pages.
Unauthenticated users can view them and they do not need
to be secured with SSL. -->
<authorization>
<allow users="*" />
</authorization>
</system.web>
Use the following <authorization> element inside a <location> element in Web.config to deny access to unauthenticated users and force a redirect to the login page that is specified on the <forms> element:
<!-- The restricted folder is for authenticated and SSL access only. -->
<location path="Secure" >
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
Secure the Authentication Cookie
To prevent session hijacking and cookie replay attacks, secure the cookie by making sure that it is only passed over SSL connections using the HTTPS protocol. For additional risk mitigation, encrypt the cookie before sending it to the client and limit the period for which the cookie is valid. To secure the authentication cookie:
* *Restrict the authentication cookie to HTTPS connections. *
* *Encrypt the cookie. *
* *Limit cookie lifetime. *
*
Consider using a fixed expiration period. * *Do not persist authentication cookies. *
* *Keep authentication and personalization cookies separate. *
* *Use distinct cookie names and paths. *
Restrict the Authentication Cookie-to-HTTPS Connections
Cookies support a "secure" property that determines whether or not browsers should send the cookie back to the server. With the secure property set, the cookie is sent by the browser only to a secure page that is requested using an HTTPS URL.
If you are using .NET Framework version 1.1, set the secure property by using requireSSL="true" on the <forms> element as follows:
<forms loginUrl="Secure\Login.aspx"
requireSSL="true" . . . />
If you are using .NET Framework version 1.0, set the secure property manually in the Application_EndRequest event handler in Global.asax using the following code:
protected void Application_EndRequest(Object sender, [EventArgs] e)
{
string authCookie = [FormsAuthentication.FormsCookieName;]
foreach (string sCookie in Response.Cookies)
{
if (sCookie.Equals(authCookie))
{
// Set the cookie to be secure. Browsers will send the cookie
// only to pages requested with https
Response.Cookies[sCookie].Secure = true;
}
}
}
Encrypt the Cookie
Encrypt the cookie contents even if you are using SSL. This prevents an attacker from viewing or modifying the cookie if he or she manages to steal it through a XSS exploit. In this event, the attacker can still use the cookie to gain access to your application. The best way to mitigate this risk is to implement the appropriate countermeasures to prevent XSS attacks (described under "Cross-Site Scripting" earlier in this chapter), and limit the cookie lifetime as described in the next recommendation.
To provide privacy and integrity for the cookie, set the protection attribute on the <forms> element as follows:
<forms protection="All" Privacy and integrity
Authorization
* Use URL authorization for page and directory access control.
* Use File authorization with Windows authentication.
* Use principal demands on classes and methods.
* Use explicit role checks for fine-grained authorization.
Impersonation
Sensitive Data
* Do not pass sensitive data from page to page.
* Avoid plain text passwords in configuration files.
* Use DPAPI to avoid key management.
* Do not cache sensitive data.
Session Management
* Require authentication for sensitive pages.
* Do not rely on client-side state management options.
* Do not mix session tokens and authentication tokens.
* Use SSL effectively.
* Secure the session data.
Parameter Manipulation
* Protect view state with
MACs. * Use
Page.ViewStateUserKey to counter one-click attacks.
* Maintain sensitive data on the server.
* Validate input parameters.
Exception Management
* Return generic error pages to the client.
* Implement page-level or application-level error handlers.
Auditing and Logging
Archive
*
ASPNETWhidbeySecurityGuidelinesArchive1
Return to
HomePage