Here's a write-up of a security vulnerability that I found and reported to a company regarding profile pictures
The company I reported this to have asked not to be named in this post, which I have happily respected. The company creates a web platform, where each user has a dashboard and their own profile. Each user can see the profiles of accounts associated with them on the dashboard. This means that users need to see their own profile picture, and the profile pictures of those associated user accounts. They see no other profile pictures when using the dashboard. The user is therefore expected to be restricted to only being able to view these images, or in other words: the principle of least privilege, where a user is only given access to what they need access to in order to do what they need to do.
In my spare time, I was taking a look in the Network tab in DevTools. A lot of GET requests are being made to endpoint URLs with user ID entries. Now, I am at a point where I can test all of these endpoints with neighbouring IDs, to see if the IDs are incremental (aka forced browsing). Most endpoints needed the session ID in the cookie; only one instead needed it in a different request header, which I was able to test with some Fetch API jiggery-pokery in the console (aka making a request with the Auth header!). All of them returned errors when using an ID that was not the one of the authenticated user, except for the one to get profile pictures. It was expected that it should return an error on any ID that is not the users, or the ID of an associated user account to that user. But any valid user ID was accepted and the profile picture returned.
Here's an example of what the request to the endpoint looked like:
Why fix it?
By having a combination of incremental IDs and the profile pictures of all IDs being accessible from an authenticated user, it would be very simple to write a script to take all the images and display them on a webpage. Mark Zuckerberg's 'Facemash' comes to mind.
Here's a pseudo-code example of a script that takes the pictures:
set base_url = "https://example.org/dash/getprofilepicture?userid=" set user_id = "001" set exists = true while exists: set url = base_url + user_id send GET request to url if response status code is 200: display profile picture set user_id = zero-padded string representation of (int(user_id) + 1) else: exists = false
KEY green: method, blue: variable, purple: control flow, red: string
This code assumes that the ID is always three characters long. In the loop, the url is constructed using this
user_id value. If the response status code is 200, indicating a successful response, the profile picture is displayed and
user_id is incremented by
1 and converted back to a zero-padded string representation. If the response status code is not 200, indicating that the user ID doesn't exist, the loop breaks by setting
exists to false.
OpenAI's ChatGPT would like me to make sure I let you know that this code was written by them. And that it is pseudo-code, so the implementation will depend on the programming languages and libraries you will be using. Read my full conversation with ChatGPT to get this pseudo-code.
The company were very happy to fix the issue. The endpoint now acts the same as the other endpoints... When authenticated, you can view your own profile picture and the profile pictures of users associated with yourself. An exemplary reponse to a report in my books! Many thanks to the company for their commitment to user privacy and safety.
First ticket inputted into support system
No response to first ticket. Second ticket inputted asking for acknowledgement.
Acknowledgement explaining that they could not find first ticket, even with ticket ID. Asked for further details.
I replied with a copy of my first ticket.
Company responded asking for my user details
I responded with my user details
Company acknowledged that it had been raised internally
Company responds saying they are looking into it and asking for some more details about my user account/ticket. They also asked, out of interest, how I found the issue.
I respond clarifying details and explaining how I found the issue
Acknowledged that they recieved last email and that how I found the issue was interesting. Explained they were still looking into it.
Fix published to production environment. Acknowledged via email.
© 2022 Edward JA Coldrick. All rights reserved.
Email: [email protected]