Skip to main content

Insecure functionality - Masking

Need

Secure data masking

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.Extensions.Logging for logging and tracing in .NET applications

Description

Non compliant code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace VulnerableApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
private readonly ILogger<UserController> _logger;

public UserController(ILogger<UserController> logger)
{
_logger = logger;
}

[HttpPost]
public IActionResult Post([FromBody] User user)
{
// Here we are directly using the user object without any masking
Console.WriteLine("Username: " + user.Username);
Console.WriteLine("Password: " + user.Password);
return Ok();
}
}

public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
}

The above code represents a simple ASP.NET Core backend application that has a vulnerability related to insecure functionality - masking. The application has a UserController that accepts POST requests. The POST request is supposed to receive a User object from the request body.

The User object contains a Username and Password property. When a POST request is made to the UserController, it directly prints out the Username and Password to the console without any form of masking.

This is a vulnerability because it exposes sensitive information, such as the user's password, in plain text. Anyone who has access to the console logs can see this sensitive information. This could potentially lead to unauthorized access if the logs fall into the wrong hands.

The application should mask or encrypt sensitive data to prevent it from being exposed in plain text. In this case, the password should be hashed or masked before being logged or stored.

Steps

  • Implement data masking techniques to hide sensitive information in the request and response.
  • Use secure methods to store and transmit sensitive data, such as hashing and encryption.
  • Avoid logging or printing sensitive information in plain text.
  • Consider using a secure logging framework that supports data masking.
  • Regularly review and update the data masking techniques to ensure they are effective against new vulnerabilities.

Compliant code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Security.Cryptography;
using System.Text;

namespace VulnerableApp.Controllers
{
[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
private readonly ILogger<UserController> _logger;

public UserController(ILogger<UserController> logger)
{
_logger = logger;
}

[HttpPost]
public IActionResult Post([FromBody] User user)
{
// Here we are directly using the user object without any masking
// Masking the password before logging
var maskedPassword = new String('*', user.Password.Length);
_logger.LogInformation("Username: " + user.Username);
_logger.LogInformation("Password: " + maskedPassword);

// Hashing the password before storing it
user.Password = ComputeSha256Hash(user.Password);

return Ok();
}

static string ComputeSha256Hash(string rawData)
{
// Create a SHA256
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));

// Convert byte array to a string
StringBuilder builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
}
}

public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
}

The updated code now includes data masking and hashing techniques to protect sensitive information.

In the Post method, the user's password is masked before it is logged. This is done by replacing each character of the password with an asterisk (*). This way, even if the logs are accessed, the actual password will not be revealed.

Next, the password is hashed using the SHA256 algorithm before it is stored. Hashing is a one-way function that scrambles the original data (in this case, the password). Even if the hashed password is accessed, it is extremely difficult to reverse-engineer the original password from the hashed value.

The ComputeSha256Hash method is used to hash the password. It takes a string as input and returns the hashed value as a hexadecimal string.

By implementing these changes, the system now masks sensitive data and uses secure methods to store and transmit such data, thereby fixing the insecure functionality vulnerability.

References