Insecure Direct Object References occur if any application provides direct access to any object based on user-supplied inputs. As a result, the attackers can bypass the authorization of the authenticated user and access resources directly to inject some malicious code, for instance database records or files etc. Insecure Direct Object References allows attackers to bypass authorization and provides direct access to resources by changing the value of a parameter used to directly point to an object. Such resources can be database entries belonging to other users, files in the system, and more. If we are not proving strong validation to validate authenticated user, it causes the application to take user supplied input and use it to retrieve an object without performing sufficient authorization checks.
Malicious Attack Examples
Example 1
With the authentication made for the logged-in user with the given credentials, and based on the role the authorization provided, then we should allow access to the granted screens, modules, and components etc. And we should not allow other users' information. So while processing any request from the end user (may be the logged in user or the anonymous user), we have to provide strong validation before processing the request. If we are not strongly validating the request before processing it then we are providing an opportunity to the attacker to perform some unauthorized access to inject some malicious code into your system. Let's say you logged in with user “TestUser”. After login is successful it will redirect to his/her home screen. See the below screenshot for reference.
If you observe in the above screenshot, the browser's URL is http://test-site:2001/#/requestor. Now if you replace “requestor” with “admin” then the URL would be http://test-site:2001/#/admin. See the below screenshot,
Here it allowed the logged in user to access other URL requests even though the logged in user is not authorized to access it.
Example 2
The application uses unverified data in a SQL query call that will access account information.
- string sql_query = "SELECT * FROM User_Account_Info WHERE accountName = ?";
- PreparedStatement str = connection.prepareStatement(sql_query , ? );
- str.setString( 1, request.getParameter("act"));
- ResultSet response = str.Example ecuteQuery( );
The attacker modifies query string parameters ("
act") value in the browser to point to other users.
URL Request,
http://testsite.com/app/accountInfo?act=admin URL Request query string parameter's value can be changed with:
http://testsite.com/app/accountInfo?act=approver
http://testsite.com/app/accountInfo?act=requestor Example 3
The value of a parameter is used directly to retrieve a database record.
Sample URL request,
http://testsite.com/testpage?invoiceId=12345 Here the query string value of an "
invoiceId" parameter is used as an index of an "
invoice" table in the database. The application takes the query string value as an input parameter and uses it in a query to the database and the application returns the invoice information to the end user.
Since the value of "
invoiceId" goes directly into the query without any additional validation, by modifying the value of the given parameter it is possible to retrieve any invoice object irrespective of the user to whom the invoice actually belongs. To test this scenario the tester should try with the "
invoiceId" which does not belong to the current logged in user (ensuring he/she is not supposed to view this information).
Example 4
The value of a parameter is used directly to perform an operation in the system.
Sample request,
http://testsite.com/changepwd?user=someone In this case, the value of the query string tells the application for which user it should change the password. In general this step will be a part of a multi-step operation. In the first step it tells the application which will get a request stating which user's password needs to be changed, and in the next t step the end user provides a new password (without prompting for the current password).
The given value for a parameter is used to directly reference a query for whom the password change operation is to be performed. To test this scenario the tester should attempt with a different test user name than the one currently logged in, and needs to check whether it is possible to modify the password of another user successfully or not.
Example 5
Suppose we are getting employee data based on the employee ID and we are sending the employee id to the UI when login is successful. Even though in every request we are validating Authentication and authorization, and based on the user id which we are getting back from the UI, we are fetching all records of the employee using his/her employee id. In that scenario, the user can change their Employee id using different techniques as in the below image and he will be able to get data of other employees.
Prevention mechanism We simply have to validate the data received.
Before using any input in a function, we SHOULD validate it. We have to compare the given inputs against what is the example expected. If we do this, we will never have security vulnerability in any application we create.
Make sure that the below points are taken care of,
- Proper Authentication and Authorization is done by both UI and service sides.
- Never depend on UI side for any kind of validation.
- Don’t do any hard code for testing; if we are doing it for some special case then make sure that you remove all hard code while deploying it in production.