Unprotected Absence Reasons queries and mutations
CLN-001 — Unprotected Absence Reasons queries and mutations (Kolego)
Vulnerability ID: CLN-001
Vulnerability type: Access Control
Threat level: Moderate
Description:
Authorization and authentication are broken for GraphQL queries related to Absence Reasons.
Technical description:
GraphQL queries and mutations are respectively used to fetch data about Absence Reasons and to update Absence Reasons. Queries to fetch Absence Reasons can be successfully performed without any authentication, as in the following simple curl request:
curl -X POST https://sis5.c-b-e-s.de/graphql/ -H "Content-Type: application/json" -d
'{"query":"query absenceReasons {items: absenceReasons {id shortName name colour countAsAbsent
default canEdit canDelete tags {id name shortName}}}"}'
This request returns all the data for every Absence Reason (gqlabsenceReasons works as well). This vulnerability is also discoverable if the whoAmI responses from the GraphQL backend to the frontend are manipulated as in CLN-010 (page 23). Completely unauthenticated users can view the Absence Reasons menu and its contents if a proxy manipulates the permissions in the whoAmI responses, as in the following screenshot:
A logged-in Student user can also view the Absence Reasons menu by performing the same manipulation, but crucially a Student user can also edit the Absence Reasons. The following screenshot shows the Absence Reasons editing interface open for a test Student user:
On editing an Absence Reason, the front end returns an error but the mutation request is successful. As above, these mutation requests can be sent directly to the GraphQL backend as long as a valid sessionid from a logged-in Student account is included:
curl -X POST https://sis5.c-b-e-s.de/graphql/ -H "Content-Type:
application/json" -H "Cookie: sessionid=VALID_SESSION_ID_FOR_STUDENT" -d
'{"variables":{"input":[{"id":"5","shortName":"update","name":"update with
authorization","colour":"#000000","default":true}]},"query":"mutation updateAbsenceReasons($input:
[BatchPatchAbsenceReasonInput]!) {updateAbsenceReasons(input: $input) {items: absenceReasons {id
shortName name colour countAsAbsent default canEdit canDelete tags {id name shortName}}}}"}'
Impact:
The lack of proper authentication and authorization on the Absense Reasons functions results in:
- Exposure of sensitive information.
- Manipulation by underprivileged users.
Recommendation:
- Inspect and fix the access control logic for query and mutation actions related to Absence Reasons.