Unrestricted Access to All User Information | REST API Oversharing
作者在HackerOne上发现了一个敏感数据泄露漏洞:通过将API端点从`/api/user/me`改为`/api/user/all`,可以获取所有用户信息及3,156个验证令牌。 2025-4-25 06:7:14 Author: infosecwriteups.com(查看原文) 阅读量:2 收藏

Clement 'Tino

Akwaaba! once again people. My lazy ass finally found time to write about this simple yet impactful vulnerability I came across during my hunting on a HackerOne program last year. If you haven’t read my previous post about Easy $150: Misconfigured SSO Led to Account Takeover, please do — it's a simple exploit you can also do to earn a few $$$.

🔗READ it for FREE

Banner

Alright, I’m not gonna bullshit you or sensationalize this, it was a simple vulnerability that doesn’t require any mental gymnastics.

What’s the vulnerability?

Summary of the vulnerability description

Yeah, that’s it. As described in the image above, there was a Sensitive Data Exposure vulnerability in the REST API. By simply changing the API endpoint from /api/user/me to /api/user/all, we are able to dump all existing user information.

How did I find it?

Some general recon, subdomain discovery revealed a domain:

  • xyz-onboarding.target.com

I was able to sign up via a registration page. After signing up, I logged in with my account. Taking note of the API calls being made when you visit the app loads, I noticed the API wasn’t hosted on a different subdomain, instead, it was hosted on a dedicated /api path. So, we have all API calls being made to

Upon successful login, an API call is made to:

via a GET request and your account details are returned. These details get rendered to browser interface for your view. As you can see, the Content-Length of this response was 440.

GET request to retrieve your accound details

So, I tried the classic attack of changing the path from /api/user/me to /api/user/all and it worked! This returned a large response as seen by the Content-Length. I was surprised myself because this was such a CTF-style exploitation which I didn’t expect to come across.

Dumping all User information

Yet Another Sensitive Exposure in the API

That wasn’t the end of it, I noticed, the token that was part of the verification link sent to my email was also leaked in my account details. It was contained in the verify_identity parameter.

Email verification token leaked in API response

So, I dialed up my French and quickly compared this token to the one in my email and I was right! They matched.

Email Containing Verification link

I run back to the /api/user/all endpoint to see if the tokens of other users are leaked there also. Yes, their tokens were leaked! I got access to 3,156 tokens of various types of users.

Like I said, this was quite simple:

Login => Grab /api/user/me Request => Change /me to /all

Discovery Timeline

How did I know to check the /all endpoint?

It is a common endpoint where developers tend to store all user information, I have come across it in many pentests but it was mostly limited to internal applications. So, I decided to give it a shot. Whenever I see a /api/me API endpoint, some similarly misconfigured endpoints I normally check for include:

  • /api/users
  • /api/user/ (if it contains a UUID, remove the UUID, or the trailing / also)
  • /api/all/
  • /api/ALL (capitalization can make a difference)
  • /api/user/*
  • /api/users/*
  • etc.

How can this be Prevented?

As a developer, before you pull this shameless line on me:

But the application doesn’t make a request to the /api/user/all endpoint by itself, you had to manually request it by yourself

Just know the vulnerability exists, it is THERE! Implement proper access controls. If you are going to keep this endpoint up, perhaps limit it to administrators or internal use only. For example, in Flask, you can check the user’s role from their JWT payload before granting/denying access.


@app.route('/api/user/all', methods=['GET'])
@jwt_required()
def get_all_users():
# get_jwt_identity() method returns the user's role from their JWT
current_role = get_jwt_identity()
if current_role == 'admin': # Only allow admin to access this endpoint
return jsonify(users), 200
return jsonify({"msg": "Access forbidden"}), 403

if __name__ == '__main__':
app.run(debug=True)

Hey, see you later.

Bye

文章来源: https://infosecwriteups.com/unrestricted-access-to-all-user-information-rest-api-oversharing-e4a9a7e5bade?source=rss----7b722bfd1b8d---4
如有侵权请联系:admin#unsafe.sh