Skip to main content

Insecure functionality - Pass the hash

Need

Secure authentication mechanism to prevent unauthorized access using Pass The Hash technique

Context

  • Usage of C# for building robust and scalable applications
  • Usage of Microsoft.AspNetCore.Mvc for building web applications with ASP.NET Core
  • Usage of Microsoft.AspNetCore.Identity for managing user authentication and authorization in ASP.NET Core applications

Description

Non compliant code

public class AccountController : Controller
{
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
return View(model);
}
}

The above code is an example of a vulnerable login handler in an ASP.NET Core application. The PasswordSignInAsync function is used to authenticate a user based on their email and password.

The vulnerability lies in the fact that the password is being directly used in the authentication process without any form of hashing or encryption. This means that if the password is intercepted or leaked in any way, the attacker can use the same password to authenticate themselves as the user, gaining unauthorized access to the system.

This is a classic example of the "Pass the Hash" vulnerability, where an attacker can use a leaked hash to authenticate themselves without needing to know the actual password. In this case, the password is not hashed at all, making it even easier for the attacker to exploit the vulnerability.

To mitigate this vulnerability, passwords should never be stored or transmitted in clear text. Instead, they should be hashed using a strong cryptographic hash function before being stored or used in authentication. The PasswordSignInAsync function should then be replaced with a function that accepts hashed passwords, such as SignInWithHashAsync.

Steps

  • Implement strong password hashing algorithm
  • Use a salt value when hashing passwords
  • Implement multi-factor authentication
  • Enforce password complexity requirements
  • Implement account lockout mechanism
  • Implement secure session management
  • Regularly update and patch the application and its dependencies
  • Implement secure coding practices

Compliant code

public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;

public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}

[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
var result = await _signInManager.CheckPasswordSignInAsync(user, model.Password, false);
if (result.Succeeded)
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
else if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
}
return View(model);
}
}

The updated code now includes a UserManager and SignInManager which are used to manage users in ASP.NET Core Identity. The UserManager is used to find the user by their email and the SignInManager is used to check the password sign-in attempt.

In the Login method, the user is first found by their email. If the user exists, the password sign-in attempt is checked. If the sign-in attempt is successful, the user is redirected to the home page. If the user is locked out, they are redirected to a lockout page. If the sign-in attempt is unsuccessful, an error message is added to the ModelState and the user is returned to the login page.

This code mitigates the Pass The Hash vulnerability by using ASP.NET Core Identity's built-in features for managing users and sign-in attempts. These features include a secure password hashing algorithm, a salt value when hashing passwords, and an account lockout mechanism.

In addition to this, it is recommended to implement multi-factor authentication, enforce password complexity requirements, implement secure session management, regularly update and patch the application and its dependencies, and implement secure coding practices to further secure the application.

References