[Bugcrowd] JSM customers can delete any approval
Description
I found that JSM customers can delete any approval from the JSM project. If JSM portal allows customers to self sign up (the default and commonly used configuration), anyone can sign up and delete approvals. The only requirement is that the attacker must specify id of the approval to delete, but it is and integer value and can be enumerated. The app allows to use approvals in JSM portal, so the scenario is actual.
Steps to reproduce:
Part 1. Configuration
-
Log in as admin, enable Jira Service Management if it is not enabled
-
On the left-side panel click
Apps->Approval Path -
Go to
Settings->Generaland enableAllow manual initiation of approvals -
Go to
Definitions -
Click
Create -
Set any name
-
Select the JSM project in
Space -
Enable
Available for JSM customersandCan be started by JSM customers -
Click
Add step-> and any step -
Click
Save definition -
Using Jira UI create a ticket in the JSM project (as a target to get a title of the issue)
-
Open the created issue
-
On the right-side panel expand
Approval Path -
On
Newtab clickStartto start an approval -
Go to requests history and find there a request to POST
https://app.approval-path.com/connect/jira/create, get theapprovalIdvalue from the response -
Also, get a request to
https://app.approval-path.com/connect/jira/rest/reference/approvals?collectionId=...and get the collection id parameter from the url. It is a project id, JSM users can get it in the JSM portal
Part 2. The vulnerability
-
Go to
https://<INSTANCE>.atlassian.net/servicedeskin an incognito browser window and sign up -
Confirm email to complete sign up
-
Go to
https://<INSTANCE>.atlassian.net/plugins/servlet/ac/ovh.atlassianinc.approval-path.jira/approval-dialog?classifier=json&project.id=<PROJECT_ID>with the collection id from step 16 of part 1 and get theurlvalue from the response -
Send the request below with the value from the previous step:
POST /connect/JIRA/api/atlassian-connect-app HTTP/2Host: app.approval-path.comContent-Type: application/jsonContent-Length: 1236{"url":"<URL>"}
Get the token value from the response. Send the request below with the JWT token and the id of the approval:
DELETE /connect/jira/delete/<APPROVAL_ID>?jwt=<TOKEN> HTTP/2Host: app.approval-path.com
Check that the approval was deleted.
@Adam Lipiński The issue was caused by a change made in
According to @Igor Hercer the issue with the
GET /connect/jira/rest/reference/approvalsendpoint returning approvals details to JSM customer is caused by changes from other task, by @Piotr Haraburda.That makes this task ready to be merged as we’ve gone through the other endpoints with Igor on a call and confirmed they are working as expected.
@Piotr Haraburda could you let me know which task causes the issue with
GET /connect/jira/rest/reference/approvalsendpoint? So I will make sure to check this again when testing.@Igor Hercer The test results are below:
Not intended responses
ApprovalsListRestController (/connect/jira/rest, /connect/confluence/rest)
GET /reference/approvals - Get reference approvals
- Uses flag to determine view permissions
The above endpoint used with token generated from JSM customer (as described in repro steps) returned me 200 OK and list of all approvals from a project. Also checked this on PROD and on PROD it returns 401 Unauthorized.
Responses I am not sure about:
DefinitionRestController (/connect/jira/rest/definition, /connect/confluence/rest/definition)
GET /reference - Get reference definitions
- Filters definitions by visibleToJsmUsers and canBeStartedByJsmUsers for JSM customers
Here I am always getting 500 Internal Server Error, I am not sure if this is okay but I might be doing something wrong. I am adding something like this to the request after the token value:
&definition-ids=<id1>%2C<id2>%2C<id3>ApprovalsBulkActionsController (/connect/jira/bulk, /connect/confluence/bulk)
DELETE /delete - Bulk delete approvals
- Blocks all JSM customers ("No access")
PATCH /archive - Bulk archive approvals
- Blocks all JSM customers ("No access")
Response to the above requests was 403 Forbidden with “Missing CSRF token” message.
Seems ok but please confirm that this is intended.
ApprovalRestController (/connect/jira, /connect/confluence)
POST /create - Create approval
- JSM customers can start approvals (bypasses canStartApproval check)
- Sets startedByJSMCustomer and canParametrize=false for JSM customers
POST /action - Submit approval action (approve/reject)
- Blocks JSM customers if approval has availableForJSMCustomers=false
Two requests above I didn’t test with the token as I am not sure how exactly do this - how to pass additional info, e.g. issueId etc.. Though I tested starting approvals and giving actions manually on JSM portal and I am not seeing any issues.
Responses I can confirm are correct:
DefinitionRestController (/connect/jira/rest/definition, /connect/confluence/rest/definition)
GET /{id} - Get definition by ID (view definition)
- JSM customers skip checkAccess, but are blocked if definition has availableForJSMCustomers=false
Response was either definition details for available ones or “No access” for not available ones.
ApprovalRestController (/connect/jira, /connect/confluence)
DELETE /delete/{id} - Delete approval
- Blocks all JSM customers ("No access")
GET /get-users-for-notification/{id} - Get users for notification
- Blocks all JSM customers ("No access")
PATCH /archive/{id} - Archive approval
- Blocks all JSM customers ("No access")
Response was “No access” for these.
If you want we can get on a call tomorrow to check the responses I am not sure about together.
Make sure that correct permissions are applied for JSM user after these changes.
DefinitionRestController (/connect/jira/rest/definition, /connect/confluence/rest/definition)
GET /{id} - Get definition by ID (view definition)
- JSM customers skip checkAccess, but are blocked if definition has availableForJSMCustomers=false
GET /reference - Get reference definitions
- Filters definitions by visibleToJsmUsers and canBeStartedByJsmUsers for JSM customers
ApprovalsListRestController (/connect/jira/rest, /connect/confluence/rest)
GET /reference/approvals - Get reference approvals
- Uses flag to determine view permissions
ApprovalRestController (/connect/jira, /connect/confluence)
POST /create - Create approval
- JSM customers can start approvals (bypasses canStartApproval check)
- Sets startedByJSMCustomer and canParametrize=false for JSM customers
POST /action - Submit approval action (approve/reject)
- Blocks JSM customers if approval has availableForJSMCustomers=false
DELETE /delete/{id} - Delete approval
- Blocks all JSM customers ("No access")
GET /get-users-for-notification/{id} - Get users for notification
- Blocks all JSM customers ("No access")
PATCH /archive/{id} - Archive approval
- Blocks all JSM customers ("No access")
ApprovalsBulkActionsController (/connect/jira/bulk, /connect/confluence/bulk)
DELETE /delete - Bulk delete approvals
- Blocks all JSM customers ("No access")
PATCH /archive - Bulk archive approvals
- Blocks all JSM customers ("No access")
@Igor Hercer This issue still occur exactly as before, I can still delete any approval from JSM project using customer’s token.
The issue has been successfully reproduced by QA with provided steps.
I was able to delete an approval using token generated from account that didn’t even create any query on the portal.