The vulnerability in Wagtail allowed a user with limited permissions to copy a page they did not have access to into a part of the site they controlled, thereby gaining access to its content. The root cause was a failure to check the user's permissions on the source page being copied; checks were only performed for the destination.
The analysis of the security patches reveals several key changes that pinpoint the vulnerable functions:
- The
wagtail.admin.views.pages.copy.copy view, the entrypoint for the copy action, was modified to explicitly check can_copy() permission on the source page.
- The core permission logic in
wagtail.models.pages.Page.can_copy() was fundamentally changed. The vulnerable version simply checked if the page was not a root page (return not self.page_is_root), while the patched version requires the user to have edit permissions (return self.can_edit()). This change is the crux of the fix.
- The
wagtail.models.pages.Page.can_copy_to() method was updated to first call the now-corrected can_copy() method, ensuring the source page permission check is always performed.
- The
wagtail.admin.forms.pages.CopyForm.clean() method, which handles validation, was updated to use the corrected can_copy_to permission check, replacing a weaker check.
- A similar vulnerability in page alias creation was fixed in
wagtail.actions.create_alias.CreatePageAliasAction.check() by adding the same can_copy_to permission check.
During exploitation, a runtime profiler would show calls to wagtail.admin.views.pages.copy.copy, which in turn invokes the other vulnerable methods on the CopyForm and Page models. The identified functions are those that were modified to add the missing, critical permission checks on the source page.