Skip to main content

Insecure object reference - Financial information

Need

Secure access to financial information

Context

  • Usage of C# for building robust and scalable applications
  • Usage of _context for managing state and sharing data across components

Description

Non compliant code

[HttpGet]
public IActionResult GetCreditCardDetails(string encryptedProductId)
{
var creditCard = _context.CreditCards
.FirstOrDefault(c => c.EncryptedProductId == encryptedProductId);

if (creditCard == null)
{
return NotFound();
}

return Ok(creditCard);
}

The above code snippet represents a controller action in an ASP.NET Core application that retrieves credit card details based on an encrypted product ID. The product ID is passed as a parameter in the HTTP GET request.

The vulnerability lies in the fact that there are no checks to ensure that the user making the request is authorized to view the details of the credit card associated with the encrypted product ID. This means that if a user has a valid session, they can potentially retrieve the details of any credit card by simply knowing or guessing the encrypted product ID.

This is a classic example of an insecure direct object reference (IDOR) vulnerability, where an application exposes an internal implementation object, such as a file, directory, or database key without any access control checks or other protection. In this case, the internal object is the encrypted product ID.

The best way to mitigate this vulnerability is to implement proper access control checks that ensure the user making the request is authorized to view the details of the requested credit card.

Steps

  • Implement proper authentication and authorization mechanisms to ensure that only authorized users can access the credit card details.
  • Validate the user's session and ensure that the account associated with the credit card matches the authenticated user's account.
  • Do not rely solely on the encrypted product number for authorization. Use a more secure and unique identifier, such as a user-specific token or ID.
  • Implement access controls to restrict access to the credit card details based on the user's role or permissions.
  • Regularly review and update the code to address any new security vulnerabilities that may arise.

Compliant code

[HttpGet]
[Authorize]
public IActionResult GetCreditCardDetails(string encryptedProductId)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = _context.Users.FirstOrDefault(u => u.Id == userId);

if (user == null)
{
return Unauthorized();
}

var creditCard = _context.CreditCards
.FirstOrDefault(c => c.EncryptedProductId == encryptedProductId && c.UserId == userId);

if (creditCard == null)
{
return NotFound();
}

return Ok(creditCard);
}

The updated code now includes an [Authorize] attribute on the GetCreditCardDetails method. This ensures that only authenticated users can access this method.

Next, we retrieve the userId from the authenticated user's claims. This userId is then used to retrieve the user from the database.

If the user is not found in the database, the method returns an Unauthorized response. This is an additional security measure to ensure that only valid users can access the credit card details.

The creditCard is then retrieved from the database using both the encryptedProductId and the userId. This ensures that the credit card details can only be accessed by the user associated with the credit card.

If the credit card is not found in the database, the method returns a NotFound response. This is a standard response for a GET request when the requested resource cannot be found.

Finally, if the credit card is found and the user is authorized, the method returns an Ok response with the credit card details. This is the expected behavior for a successful GET request.

This updated code provides a more secure way of accessing credit card details by ensuring that only the authorized user can access their own credit card details. It also provides a more robust authorization mechanism by using a user-specific identifier (the userId) in addition to the encryptedProductId.

References