Просмотр исходного кода

fix(page): replace findById with findByIdAndViewer in publish/unpublish/content-width endpoints

Fixes an IDOR vulnerability where any authenticated user could publish,
unpublish, or change content-width of pages they do not have access to,
bypassing the page grant system (GRANT_OWNER, GRANT_USER_GROUP, etc.).

Fixes #10811
Yuki Takei 6 дней назад
Родитель
Сommit
9b8a7aa710

+ 12 - 1
apps/app/src/server/routes/apiv3/page/index.ts

@@ -1201,12 +1201,23 @@ module.exports = (crowi: Crowi) => {
       );
 
       try {
+        const page = await Page.findByIdAndViewer(pageId, req.user);
+        if (page == null) {
+          return res.apiv3Err(
+            new ErrorV3(
+              'Page is unreachable or empty.',
+              'page_unreachable_or_empty',
+            ),
+            400,
+          );
+        }
+
         const updateQuery =
           expandContentWidth === isContainerFluidBySystem
             ? { $unset: { expandContentWidth } } // remove if the specified value is the same to the system's one
             : { $set: { expandContentWidth } };
 
-        const page = await Page.updateOne({ _id: pageId }, updateQuery);
+        await Page.updateOne({ _id: page._id }, updateQuery);
         return res.apiv3({ page });
       } catch (err) {
         logger.error('update-content-width-failed', err);

+ 8 - 2
apps/app/src/server/routes/apiv3/page/publish-page.ts

@@ -45,9 +45,15 @@ export const publishPageHandlersFactory = (crowi: Crowi): RequestHandler[] => {
       const { pageId } = req.params;
 
       try {
-        const page = await Page.findById(pageId);
+        const page = await Page.findByIdAndViewer(pageId, req.user);
         if (page == null) {
-          return res.apiv3Err(new ErrorV3(`Page ${pageId} is not exist.`), 404);
+          return res.apiv3Err(
+            new ErrorV3(
+              'Page is unreachable or empty.',
+              'page_unreachable_or_empty',
+            ),
+            400,
+          );
         }
 
         page.publish();

+ 8 - 2
apps/app/src/server/routes/apiv3/page/unpublish-page.ts

@@ -47,9 +47,15 @@ export const unpublishPageHandlersFactory = (
       const { pageId } = req.params;
 
       try {
-        const page = await Page.findById(pageId);
+        const page = await Page.findByIdAndViewer(pageId, req.user);
         if (page == null) {
-          return res.apiv3Err(new ErrorV3(`Page ${pageId} is not exist.`), 404);
+          return res.apiv3Err(
+            new ErrorV3(
+              'Page is unreachable or empty.',
+              'page_unreachable_or_empty',
+            ),
+            400,
+          );
         }
 
         page.unpublish();