CHAPTER-5.Design and implement security
Objective 5.1: Configure authentication
Authentication is the process of determining whether users are who they say they are.
Authenticating users
Authenticating a user is the process of ensuring his or her identity.
There are two parts to authentication in ASP.NET MVC:
- Microsoft Internet Information Services (IIS)
- .NET application framework.
Several types of authentication are available in IIS 7 and above, and they are generally categorized into two different HTTP approaches: challenge-based and login redirection–based authentication methods.
A challenge-based authentication process occurs when the client must respond to the server’s demand for credentials. Examples of these include Basic, Digest, Windows, Client Certificate Mapping, and IIS Client Certificate Mapping.
The login-redirection approach is when the client sends login credentials to the application without being required by the server. The application takes the login information and uses it to determine where the user should be redirected. Forms authentication is the primary example of login-redirection authentication.
Anonymous authentication in Windows IIS does not require any credentials from the user. It uses a common set of credentials as assigned on the server.
Versions 7 and above IIS do not install non-Anonymous authentication by default. You have to install the specific modules separately. A fresh installation of IIS provides only minimal functionality to enable the server to provide static information to anonymous users.
Provider Model Design Pattern and Specification
During the request process, an HttpModule
analyzes and verifies the user information, and adds it to the HttpContext
so it is available throughout the rest of the process in any code running in that same context.
When considering the use of authentication in .NET, there are two interfaces that provide information about the security context of the user:
-
System.Security.Principal.IPrincipal
It contains information about the user, including the user’s roles. -
System.Security.Principal.IIdentity
It contains information about the users, such as whether they are authenticated and their name.
Several implementations of these interfaces come with the framework:
-
WindowsIdentity
andWindowsPrincipal
The implementations that works with Active Directory and other Windows user stores -
FormsIdentity
andGenericPrincipal
The implementations that support forms authentication -
GenericIdentity
andGenericPrincipal
Implementations that support the more flexible custom user
Anonymous authentication
By default, Anonymous authentication is the only form of authentication that is installed and enabled in IIS 7 and above.
You can enable Anonymous authentication in IIS Manager, from within the configuration files, or by using the AppCmd.exe
command as follows: appcmd set config -section:anonymousAuthentication -enabled:true
Basic authentication
The Basic authentication protocol provides a simple way to transmit a user name and password between a client and server. However, the user name and password information are Base64 encoded but not encrypted. It is a wrapper around traditional Windows security.
Basic authentication can be enabled in IIS Manager, from within the configuration files, or by using the AppCmd.exe
command as follows: appcmd set config -section:basicAuthentication -enabled:true
Digest authentication
Digest authentication uses a challenge-response mechanism to ensure that the user credentials required for authentication are not sent in clear text (without encryption).
Forms authentication
Forms authentication is a way to allow authentication and authorization without having to use the built-in Windows security system.
Example: set an authentication cookie when using Forms authentication
[ControllerAction]
public void Authenticate(string uname, string pass)
{
User user = dbContext.Users.First (x=>x.UserName.Equals(uname();
if (user != null && user.Password.Equals(EncryptHash(pass))
{
FormsAuthentication.SetAuthCookie(uname, false);
RedirectToAction("Main", "DashBoard");
}
// unable to login
RenderView("Index", new LoginViewData
{
ErrorMessage = "Invalid credentials."
});
}
Windows authentication
Windows authentication manages the process of logging in through a Windows account. There are two authentication protocols: NTLM
and Kerberos
. These
protocols are supported only in Microsoft browsers.
ASP.NET Impersonation authentication
Impersonation authentication is an add-in to Windows authentication that allows your ASP.NET MVC application to use the Windows identity provided by Windows authentication in a more robust manner.
Client Certificate authentication and IIS Client Certificate authentication
Client Certificate–based authentication is the most complex form of authentication, especially regarding maintenance. Your server must have an SSL certificate installed, and every client that will access the site must have a client certificate installed. Client Certificate–based authentication depends on Active Directory and requires that both the IIS server and the client computer are members of an Active Directory domain. It also expects that user accounts are stored in Active Directory.
Custom authentication
Using the IIdentity
and IPrincipal
interfaces enables you to put custom objects into the thread’s currentPrinciple
property and into the HttpContext’s User
property, as you would the default authentication items.
LISTING 5-1 Implementing IPrincipal and IIdentity
public class CustomPrincipal : IPrincipal
{
public CustomPrincipal(CustomIdentity identity)
{
this.Identity = identity;
}
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
return true;
}
}
public class CustomIdentity : IIdentity
{
public CustomIdentity(string name)
{
this.Name = name;
}
public string AuthenticationType
{
get { return "Custom"; }
}
public bool IsAuthenticated
{
get { return !string.IsNullOrEmpty(this.Name); }
}
public string Name { get; private set; }
}
Enforce authentication settings
We do not recommend using Web.config
files to secure your MVC application because multiple URLs can potentially hit a controller as ASP.NET MVC is action-based rather than page-based. In addition, when adding the authentication checks to configuration files, it’s easy to inadvertently omit controllers/actions that are needed to support authentication. Instead, use the Authorize
and AllowAnonymous
attributes directly on the required actions.
You can apply the Authorize
attribute at many levels, including globally, which means it will be applied to every action taken in the site. To register this attribute as a global filter so that it applies to every action in the application, use the following:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
}
By default, when an ASP.NET MVC application is configured for Forms authentication, it uses a Forms authentication token to carry the information between server requests. This token can be stored in a cookie or in the query string. When a user first logs in, the token is set and the list of roles is added. The browser ensures that this information is sent on every request to the server. When working with Forms authentication and ASP.NET MVC, you must keep the token secure. One way to secure the token is to use HTTPS for all communications. You can apply RequireHttpsAttribute to an individual action, at the controller level, or add it to the global filters collection in the Global.asax file
:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute());
filters.Add(new RequireHttpsAttribute());
}
Choose between Windows, Forms, and custom authentication
Windows Authentication provider is the default authentication provider for ASP.NET applications. When a website is set up to use Windows authentication, every user logging in to the application will be matched to the domain or local server by IIS.
Manage user session by using cookies
Forms authentication uses a cookie to manage the Forms authentication ticket, which is an encrypted version of the authenticated user name stored in the Forms authentication cookie. This cookie is an HTTP-only container for the ticket and cannot be read or manipulated on the client side. The Forms authentication ticket is passed to the server with every request and is used on the server to identify previously logged-in and authenticated users.
LISTING 5-2 Creating a FormsAuthentication ticket
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.AddDays(90),
createPersistentCookie, // a Boolean indicating whether a cookie
// should be created on the user's machine
String.Join(";",rolesArr) //user's roles
);
// add cookie to response stream
string encTicket = FormsAuthentication.Encrypt(authTicket);
System.Web.HttpCookie authCookie = new System.Web.HttpCookie(FormsAuthentication.
FormsCookieName, encTicket);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);
For a currently authenticated user, the ticket can be found on the Ticket
property of the FormIdentity
class. If you are using Forms authentication in your application, the FormsAuthenticationToken
object is a valid place to store authentication information. This information is always passed as part of the request/response process. The trade-off is: passing information in the cookie or using the cookie to carry the identifier used to look up the session information.
Configure membership providers
The ASP.NET membership framework was designed to fulfill common website membership requirements of the time, which were generally a user name, password, and some ancillary profile information. Membership information also needed to be stored in a central repository for access from multiple servers.
LISTING 5-3 Configuring an ASP.NET membership provider to use the SqlMembershipProvider
WebSecurity.InitializeDatabaseConnection(string connectionString, string providerName,
string userTableName, string userIdColumn, string userNameColumn, bool autoCreateTables)
WebSecurity
is a wrapper over an ExtendedMembershipProvider
object. The only part of the WebSecurity
configuration typically used in SimpleMembership
is a database connection string.
You can use multiple authentication providers.
Create custom membership providers
To override a FormsAuthentication
class, you need to be concerned about two aspects:
-
FormsAuthentication
It does the work to set the cookie the first time. It has theSetAuthCookie
method, which sets the ticket into the cookie. The encryption is done by using the
configuration element of the server’sMachine.config
file. -
FormsAuthenticationModule
It does the work on every subsequent request. It is an HTTP module that looks for the cookie and ticket, and ensures that it can be decrypted and added to the HttpContext for that request.
To implement a custom membership provider, you need to inherit the MembershipProvider
abstract class from the System.Web.Security
namespace.
ASP.NET membership providers enable you to run multiple applications against the same back end by employing the concept of an ApplicationName value.
Objective 5.2: Configure and apply authorization
The best way to manage permissions is through roles. Although users come and go, roles tend to be more permanent and constant. When you are creating roles, consider using privileged-based groups rather than job title-based groups; for example, use CanEditOrder rather than OrderPicker.
Authorize roles programmatically
You can use the AuthorizeAttribute class at the controller level or at an action level, as follows: [Authorize(Roles="Administrator,CanEditOrder")]
Create custom role providers
To implement a custom role provider, create a class that inherits the RoleProvider
abstract class from the System.Web.Security
namespace. The RoleProvider
abstract class inherits the ProviderBase
abstract class from the System.Configuration.Provider
namespace.
implement WCF service authorization
If you use application-level credentials, you must create a proxy to the WCF service by using the Add Service Reference command in Visual Studio or another method. Then you can pass your credentials to the WCF service:
LISTING 5-5 Sending application-level credentials to a WCF service
WCFServiceCient client = new WCFServiceCient();
client.ClientCredentials.UserName.UserName = "Apps User Name";
client.ClientCredentials.UserName.Password = "Apps Password";
LISTING 5-6 Sending credentials to a WCF service using Windows authentication
NetworkCredential credentials = new NetworkCredential();
credentials.Domain = "windows domain";
credentials.UserName = " Apps User Name";
credentials.Password = " Apps Password";
WCFServiceCient client = new WCFServiceCient();
client.ClientCredentials.Windows.ClientCredential = credentials;
Objective 5.3: Design and implement claims-based authentication across federated identity stores
Windows Azure Active Directory Access Control (Access Control Service, or ACS) is a thirdparty, cloud-based tool that provides support for the authentication and authorization of users. ACS provides a means for you to work with many of the standards-based identity providers, such as a Microsoft account (formerly Windows Live ID) and Facebook.
Creating a custom security token by using Windows Identity Foundation
Windows Identity Foundation (WIF) is a framework for building identity-aware applications, and is a part of the .NET Framework.
A security token service (STS) is the service component that builds, signs, and issues security tokens according to the WS-Trust and WS-Federation protocols.
Objective 5.4: Manage data integrity
Understanding encryption terminology
Commonly used acronyms in encryption are MD5, SHA, DES, and AES, all of which are encryption algorithms.
Encryption refers to the transformation of readable or understandable text into an illegible format that can be decoded only when the appropriate key is provided to the system.
Hashing is the process of applying a formula to a string of text, which produces a return value of fixed length that cannot be decrypted back into the original value.
Salting is a process that strengthens file encryption and hashes, making them more difficult to break.
Applying encryption to application data
Sample of C# code that encodes to a stream
using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
{
// assumes that the key and initialization vectors are already configured
CryptoStream crypoStream = new CryptoStream(myManagedStream, rijndaelManaged.
CreateEncryptor(),CryptoStreamMode.Write);
};
Sample of C# code that decodes from a stream
using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
{
// assumes that the key and initialization vectors are already configured
CryptoStream crypoStream = new CryptoStream(myManagedStream, rijndaelManaged.
CreateDecryptor(),CryptoStreamMode.Read);
};
An example of how to use the RSACryptoServiceProvider
class to encrypt and decrypt data
using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider())
{
RSA.ImportParameters(RSAKeyInfo);
encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
decryptedData = RSA.Decrypt(encrypyedData, DoOAEPPadding);
}
Applying encryption to the configuration sections of an application
Two configuration providers are included in the .NET Framework to manage the encryption and decryption processes:
-
DPAPIProtectedConfigurationProvider
This provider uses the Windows Data Protection API (DPAPI). -
RsaProtectedConfigurationProvider
This provider uses the RSA encryption algorithm.
If you need to use identical, encrypted, configuration files on multiple servers, you should consider only RsaProtectedConfigurationProvider because it allows for the export and import of the keys used for encryption/decryption.
You can use the aspnet_regiis.exe
tool with the provider encryption (–pe
) command option to encrypt sections of the Web.config
file, as follows:
aspnet_regiis -pe "ConnectionStrings" -app "/MachineDPAPI" -prov
"RsaProtectedConfigurationProvider"
-pe
indicates which configuration section to encrypt, -app
indicates the virtual path to the application that will be using the config file, -prov
is the name of the provider.
When ASP.NET accesses the information and processes the file, it automatically decrypts the encrypted content.
Objective 5.5: Implement a secure site with ASP.NET
Secure communication by applying SSL certificates
SSL is the standard security technology for establishing an encrypted link over HTTPS between a web server and a browser.
Public Key Infrastructure (PKI)
Certificate Authority (CA)
Certificate Signing Request (CSR)
Workflow of activating SSL on a web server:
- Use IIS Manager to request a certificate
After you provide the requested information, the web server creates two cryptographic keys: a private key and a public key. The public key is saved into a CSR, it is then submitted the CA. - Load the file received from the CA
When you load the file received from the CA, the web server compares the public key that is part of the SSL certificate to the private key that is retained on the server. - Prepare the site to communicate using HTTPS by configuring an HTTPS binding
- Set
RequireHttps
attribute
TheRequireHttps
attribute ensures that any posts to the controller will be redirected to port 443, which handles HTTPS traffic, protecting the information.
Use HTML encoding to prevent cross-site scripting attacks (AntiXSS Library)
Adding <% Html.Encode(review.Title) %>
to the view will ensure that the malicious code is rendered as text rather than runnable code.
You can also encode the data before saving it in the database, as follows:
public ActionResult Create(string message)
{
var newEntry = new Entry();
newEntry.Message = Server.HtmlEncode(message);
newEntry.EntryDate = DateTime.Now;
db.Entries.InsertOnSubmit(newEntry);
db.SubmitChanges();
return RedirectToAction("Index");
}
Implement deferred validation and handle unvalidated requests
You can configure the application to use this form of deferred validation by setting the requestValidationMode attribute to 4.5 in the httpRuntime element within the Web.config file, as follows:
A new collection property in the HttpRequest class called Unvalidated enables access to all the standard request data, including Form, Cookies, and QueryString.
var s = context.Request.Unvalidated.Form["some_value"];
Prevent SQL injection attacks by parameterizing queries
To counter SQL injection attacks, you need to do:
- Always inspect the data as it is being processed
- Use type-safe SQL parameters when accessing your database
- Use a restricted account when accessing the database
- When you have a database error, do not show any information to the public in an error message or warning email
The following code demonstrates how to use the Parameters collection when calling a stored procedure:
SqlDataAdapter adapter = new SqlDataAdapter("AuthorLogin", conn);
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
SqlParameter param = adapter.SelectCommand.Parameters.Add("@id",
SqlDbType.VarChar, 11);
param.Value = submittedId;
You can use parameters with dynamic SQL as well:
SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT username, email FROM user WHERE id = @id", conn);
SQLParameter param = adapter.SelectCommand.Parameters.Add("@id",
SqlDbType.VarChar, 11);
paarm.Value = submittedId;