Skip to content

Commit

Permalink
feat(id enumeration): add call from frontend to id enumeration vulner…
Browse files Browse the repository at this point in the history
…able `/api/users/id/:id` (#300)
  • Loading branch information
tamirGer authored Jan 6, 2024
1 parent fea6dfd commit 1d85d0f
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 10 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,8 @@ Additionally, the endpoint PUT /api/users/one/{email}/photo accepts SVG images,

* **Excessive Data Exposure** - The `/api/users/one/:email` is supposed to expose only basic user information required to be displayed on the UI, but it also returns the user's phone number which is unnecessary information.

* **Business Constraint Bypass** - The `/api/products/latest` endpoint supports a `limit` parameter, which by default is set to 3. The `/api/products` endpoint is a password protected endpoint which returns all of the products, yet if you change the `limit` param of `/api/products/latest` to be high enough you could get the same results without the need to be authenticated.
* **Business Constraint Bypass** - The `/api/products/latest` endpoint supports a `limit` parameter, which by default is set to 3. The `/api/products` endpoint is a password protected endpoint which returns all of the products, yet if you change the `limit` param of `/api/products/latest` to be high enough you could get the same results without the need to be authenticated.

* **ID Enumeration** - There are a few ID Enumeration vulnerabilities:
1. The endpoint DELETE `/users/one/:id/photo?isAdmin=` which is used to delete a user's profile picture is vulnerable to ID Enumeration together with [Broken Function Level Authorization](#broken-function-level-authorization).
2. The `/users/id/:id` endpoint returns user info by ID, it doesn't require neither authentication nor authorization.
7 changes: 7 additions & 0 deletions public/src/api/httpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ export function getUserData(
});
}

export function getUserDataById(id: string): Promise<any> {
return makeApiRequest({
url: `${ApiUrl.Users}/id/${id}`,
method: 'get'
});
}

export function getLdap(ldapProfileLink: string): Promise<any> {
return makeApiRequest({
url: `${ApiUrl.Users}/ldap?query=${encodeURIComponent(ldapProfileLink)}`,
Expand Down
7 changes: 4 additions & 3 deletions public/src/pages/auth/Login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ export const Login: FC = () => {
sessionStorage.setItem('email', email);
return getUserData(email);
})
.then((userData: UserData) =>
.then((userData: UserData) => {
sessionStorage.setItem(
'userName',
`${userData.firstName} ${userData.lastName}`
)
);
);
sessionStorage.setItem('user_id', userData.id);
});
};

const sendLdap = () => {
Expand Down
15 changes: 9 additions & 6 deletions public/src/pages/main/Userprofile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { FormEvent, useEffect, useState } from 'react';
import { Redirect } from 'react-router';
import {
getAdminStatus,
getUserData,
getUserDataById,
putUserData,
removeUserPhotoById
} from '../../api/httpClient';
Expand All @@ -19,8 +19,11 @@ const defaultUserData: UserData = {
};

export const Userprofile = () => {
const email: string | null =
const user_email: string | null =
sessionStorage.getItem('email') || localStorage.getItem('email');
const user_id: string | null =
sessionStorage.getItem('user_id') || localStorage.getItem('user_id');

const [user, setUser] = useState<UserData>(defaultUserData);
const [isAdmin, setIsAdmin] = useState<boolean>(false);

Expand All @@ -30,9 +33,9 @@ export const Userprofile = () => {
};

useEffect(() => {
if (email) {
getUserData(email).then((data) => setUser(data));
getAdminStatus(email).then((data) => setIsAdmin(!!data.isAdmin));
if (user_email && user_id) {
getUserDataById(user_id).then((data) => setUser(data));
getAdminStatus(user_email).then((data) => setIsAdmin(!!data.isAdmin));
}
}, []);

Expand All @@ -53,7 +56,7 @@ export const Userprofile = () => {

return (
<>
{email ? (
{user_email && user_id ? (
<AuthLayout>
<div className="login-form">
<form onSubmit={sendUserData}>
Expand Down

0 comments on commit 1d85d0f

Please sign in to comment.