Secure and controlled access to user files
import play.api.mvc._
import play.api.libs.json._
class UserController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
def getUserData(userId: String) = Action { implicit request: Request[AnyContent] =>
val user = User.find(userId)
user match {
case Some(u) => Ok(Json.toJson(u))
case None => NotFound
}
}
}
The
getUserData function in the
UserController class is vulnerable to Insecure Direct Object References (IDOR) vulnerability. This function takes a
userId as a parameter, retrieves the user information from the database, and returns it as a JSON object.
The issue here is that there is no authorization check to verify if the user requesting the data is allowed to access it. This means that if an attacker knows or guesses the
userId of another user, they can access or manipulate their data. This is because the
userId is directly used to fetch the user data from the database without any additional access control checks.
The lack of proper access control checks can lead to unauthorized information disclosure, data tampering, and other security issues, making the system vulnerable to IDOR attacks.
This vulnerability can be exploited by an attacker by simply sending a GET request to the
getUserData endpoint with the
userId of the user whose data they want to access or manipulate.
import play.api.mvc._
import play.api.libs.json._
class UserController @Inject()(cc: ControllerComponents, authAction: AuthenticatedAction) extends AbstractController(cc) {
def getUserData(userId: String) = authAction { implicit request: Request[AnyContent] =>
val loggedInUser = request.user
if(loggedInUser.id == userId) {
val user = User.find(userId)
user match {
case Some(u) => Ok(Json.toJson(u))
case None => NotFound
}
} else {
Unauthorized
}
}
}
The updated code now includes an
authAction which is an instance of
AuthenticatedAction. This is a custom action builder that checks if a user is authenticated before the action is executed. If the user is not authenticated, it will return an Unauthorized result.
In the
getUserData method, we first retrieve the logged-in user from the request. This user is set in the
AuthenticatedAction after successful authentication.
Next, we check if the logged-in user's id matches the
userId parameter. If it does, we proceed to find the user and return the user data. If it doesn't, we return an Unauthorized result. This ensures that users can only access their own data.
This approach effectively mitigates the insecure direct object reference vulnerability by implementing proper authentication and authorization checks. It ensures that only authenticated and authorized users can access the
getUserData endpoint.