Prevention of unauthorized access and manipulation of restricted fields
[HttpPost]
public async Task RegisterEmployee(Employee employee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var existingEmployee = await _context.Employees.SingleOrDefaultAsync(e => e.DNI == employee.DNI);
if (existingEmployee != null)
{
existingEmployee.Name = employee.Name;
existingEmployee.Email = employee.Email;
existingEmployee.DateOfBirth = employee.DateOfBirth;
existingEmployee.Address = employee.Address;
existingEmployee.TelephoneNumber = employee.TelephoneNumber;
await _context.SaveChangesAsync();
}
else
{
_context.Employees.Add(employee);
await _context.SaveChangesAsync();
}
return Ok();
}
In the above code, the
RegisterEmployee
method in the controller is vulnerable to restricted fields manipulation. This is because it checks if an employee with the provided DNI (Identity Document Number) exists in the database, and if it does, it updates all the employee's information with the new data provided in the request.
This means that an attacker could potentially send a request with an existing DNI but with other fields manipulated, such as the name, email, date of birth, address, and telephone number. The application would then update the existing employee's information with this manipulated data, effectively allowing the attacker to change the information of any employee as long as they know their DNI.
This vulnerability is particularly dangerous because it allows for unauthorized access and manipulation of sensitive data, which could lead to a variety of potential issues including identity theft, unauthorized actions being taken on behalf of the affected employee, and potential legal issues for the company.
[HttpPost]
[Authorize]
public async Task RegisterEmployee(Employee employee)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var currentUser = await _userManager.GetUserAsync(User);
if (currentUser.CompanyId != employee.CompanyId)
{
return Unauthorized();
}
var existingEmployee = await _context.Employees
.Where(e => e.CompanyId == currentUser.CompanyId)
.SingleOrDefaultAsync(e => e.DNI == employee.DNI);
if (existingEmployee != null)
{
existingEmployee.Name = employee.Name;
existingEmployee.Email = employee.Email;
existingEmployee.DateOfBirth = employee.DateOfBirth;
existingEmployee.Address = employee.Address;
existingEmployee.TelephoneNumber = employee.TelephoneNumber;
await _context.SaveChangesAsync();
}
else
{
_context.Employees.Add(employee);
await _context.SaveChangesAsync();
}
return Ok();
}
The updated code now includes an
[Authorize]
attribute on the
RegisterEmployee
method. This ensures that only authenticated users can access this endpoint.
We also retrieve the current user's information using
_userManager.GetUserAsync(User)
. This allows us to check if the current user's
CompanyId
matches the
CompanyId
of the employee they are trying to modify. If they do not match, we return an
Unauthorized
response.
When looking for an existing employee, we now also check that the employee belongs to the same company as the current user. This prevents users from modifying employees from other companies.
The rest of the code remains the same. If an existing employee is found, their information is updated. If no existing employee is found, a new one is added. In both cases, the changes are saved to the database.
This code ensures that only authorized users can modify employee information, and only for employees that belong to the same company as them. This prevents unauthorized access and manipulation of employee data.