Passman is a web challenge that features a password manager application built with GraphQL. Analysis of the code reveals an insecure direct object reference vulnerability in the UpdatePassword
function within the mutationType
schema. This vulnerability can be exploited to change the password of the admin
user by using a session cookie of a newly registered user. Signing in to the admin
user's account provides access to the flag.
Initial visit to the Docker instance brought up a login page:
Viewing the code provided with the challenge showed that it was built using GraphQL and entrypoint.sh
showed that the flag was located in the admin
user's account.
There was an option to create a new account, so I registered a new user mike
:
Dashboard after logging in:
After further analysis of the code, I found a /graphql
route which contained the schema.
I sent the following query from HackTricks to the /graphql
route which extracts the types, names, fields, and arguments from the database schema.
?query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
The UpdatePassword
function seemed worth taking a look at.
Here's the UpdatePassword
function code:
The UpdatePassword
function takes two arguments username
and password
, but the function isn't checking if the authenticated user has permission to update the password of the user specified in the username
argument. It simply checks if the user attempting to update the password is authenticated at all. This means that any authenticated user's session cookie can be used to update the password of any other user on the system by changing the value of the username
argument when sending a query to the database.
In other words, the function is blindly accepting the username
and password
arguments as long as the session cookie being used belongs to any user on the system, it doesn't necessarily need to belong to that specific user.
This is an example of insecure direct object reference, which is when a direct object reference based on user input can be leveraged, in this case username
, to access unauthorized resources or perform unauthorized actions.
Since the UpdatePassword
function code was vulnerable to IDOR, I was able to use the session cookie of the user I created (mike
) to update the password of the admin
user with the following payload:
{
"query": "mutation { UpdatePassword(username: \"admin\", password: \"admin\") { message } }"
}
The response returned "Password updated successfully!"
, so I tried logging in as the admin
user with the updated password:
It worked, and brought me to the dashboard for admin
:
Only thing left was to view the password and reveal the flag: