Writing secure ASP.NET code – Part 4

This is the fourth part of the multi-part series on writing secure ASP.NET code. The post series was inspired by the online training class Creating Secure Code for ASP.NET offered by TeamProfessor from Security Innovations. In the previous posts, I have discussed input validation, types of online attacks, secure error handling, best practices for storing sensitive data, and securing web application by proper configuration. Today, I am going to discuss best practices for user account management and secure logging.

User account management

User account security plays a pivotal role in application security. A compromised application security allows the attacker to perform one or more of the following attacks:

  • Escalation of privilege: The attacker accesses the application at the higher privilege level than granted.
  • Data theft: The attacker steals the information belonging to other users.
  • Impersonation: The attacker performs action as another user.
  • Non-repudiation: The attacker performs action as another user and the user gets blamed for the action.

There are several best practices that can make it more difficult for the attacker to execute these types of attacks.

Account lockout after several failed login attempts. Even though it may be an effective policy, it can be abused by the attacker for denial-of-service attack (DOS). Protection against DOS attacks includes higher login attempt limit, longer timeout between unsuccessful login attempts, and incremental timeout period between failed login attempts.

Requiring a complex password. The password should be at least 8 characters long and maximum length should be at least 20 characters. It should allow all characters and require at least one of the following: lowercase, uppercase, and numbers. It should be changed by the user at regular intervals.

Password renewal can be enforced using ASP.NET membership provider:

bool changePass = false;
string username = HttpContext.Current.User.Identity.Name;
MembershipProvider membershipProvider = Membership.Provider;
MembershipUser user = membershipProvider.GetUser(username, true);

TimeSpan diff = DateTime.Now - user.LastPasswordChangedDate;
if (Roles.IsUserInRole("Admin") && diff.Days >= 30)
{
  changePass = true;
}

if (Roles.IsUserInRole("Users") && diff.Days >= 90)
{
  changePass = true;
}

if (changePass)
{
  HttpContext.Current.Response.Redirect("ChangePass.aspx", true);
}

The lockout policy can be configured using ASP.NET membership provider:

<membership defaultprovider="SqlProvider" userisonlinetimewindow="30">
  <providers>
    <add applicationname="MyApp" connectionstringname="MyAppMembershipDatabase" enablepasswordreset="true" enablepasswordretrieval="false" maxinvalidpasswordattempts="4" name="MyAppMembershipProvider" passwordattemptwindow="10" passwordformat="Hashed" requiresquestionandanswer="true" type="System.Web.Security.SqlMembershipProvider">
  </add>
</providers>
</membership>

Secure logging procedures

A well-secured application should log information that can be used for auditing purposes. Logging should always be available. The logging system must not be able to be bypassed, nobody should be able to modify logs.

It should be resilient to attacks, not consume too much resources, and it should be written in a human readable format. The application should not disclose the location of log files.

The application should have write only access privilege in order to prevent potentially compromised application to read the log files.

User supplied data should not be logged. If it needs to be logged, then it should be treated as unsecure input and sanitized appropriately.

In order to reduce the risk of potential loss information, the logging system should only append to the log file. In order to prevent the system from getting overloaded and avoid denial of service attack the log rotation may be used along with log throttling. It limits number of times an event can be written to the log.

Using an external application for logging can improve availability of logging system. Even when the application goes down the log files are kept up to date. The external application makes it tougher for the attacker to find out the location of the log files.

If ASP.NET health monitoring is not used, disabling will reduce the attack surface of the application.

Next week

In the last article of the marathon series on writing secure ASP.NET code, we will describe best practices for authorization implementation.